行业资讯
📅 2026/7/16 7:49:48
蓝桥杯嵌入式第七届省赛:模拟液位检测告警系统全模块解析
1. 项目背景与需求解析第七届蓝桥杯嵌入式省赛的模拟液位检测告警系统是一个典型的工业控制场景应用。这个项目要求选手通过STM32开发板实现一个完整的液位监控系统涉及模拟信号采集、数据处理、人机交互和通信协议等多个嵌入式开发核心技能点。系统核心需求可以拆解为五个关键模块模拟量采集通过电位器R37模拟液位传感器输出需要完成ADC采集和软件滤波阈值管理支持三级阈值设置默认30/50/70cm参数需存储到EEPROM状态判断根据当前液位高度自动划分四个等级0-3级通信接口通过USART2实现与PC的数据交互查询自动上报状态指示三路LED分别表示运行状态、液位变化和通信事件在实际工业场景中类似的液位检测系统广泛应用于储罐监控、化工生产等领域。比赛中将工业场景简化为开发板上的电位器模拟但完整保留了真实系统中的技术要点。2. 硬件架构设计2.1 核心硬件配置系统基于蓝桥杯官方CT117E开发板主控采用STM32F103RBT6主要外设包括ADC通道PA1连接电位器R37模拟液位信号EEPROMAT24C02芯片存储阈值参数显示模块LCD12864液晶屏输入设备四个独立按键K1-K4指示设备三个LED灯LD1-LD3通信接口USART2PA2/PA3硬件连接示意图[电位器R37] -- [PA1(ADC1)] [按键K1-K4] -- [PE2-PE5] [LCD12864] -- [FSMC接口] [USART2] -- [CH340G USB转串口]2.2 关键电路设计要点ADC前端处理电位器输出接入RC低通滤波R10kΩ, C0.1μF参考电压使用板载3.3V稳压源采样周期设置为239.5周期对应约1ms采样时间EEPROM电路I2C总线需配置4.7kΩ上拉电阻地址引脚全部接地设备地址0xA0写入周期需延时5ms以上抗干扰设计所有数字信号线串联22Ω电阻模拟地与数字地单点连接电源入口处增加100μF0.1μF去耦电容3. 软件架构实现3.1 主程序流程图void main() { HAL_Init(); SystemClock_Config(); Peripheral_Init(); Level_Init(); // 初始化液位等级 Init_Data(); // 从EEPROM加载阈值 while(1) { Setting(); // 按键处理与界面管理 Level_Control(); // 液位状态判断 Usart_Control(); // 串口通信处理 Led_Control(); // LED状态更新 } }3.2 模块化设计要点ADC采集与滤波采用递推平均滤波算法窗口大小10电压转高度公式Height ADC_Value * 3300 / 4096 * 100 / 3300关键代码#define FILTER_N 10 uint16_t filter_buf[FILTER_N]; uint16_t Get_Filtered_ADC() { static uint8_t index 0; filter_buf[index] HAL_ADC_GetValue(hadc1); if(index FILTER_N) index 0; uint32_t sum 0; for(uint8_t i0; iFILTER_N; i) { sum filter_buf[i]; } return sum / FILTER_N; }EEPROM存储管理使用页写入模式每页8字节存储结构地址内容长度0x00阈值1302字节0x02阈值2502字节0x04阈值3702字节状态机设计系统存在两个主要状态graph LR A[监测模式] --|K1按下| B[设置模式] B --|K1按下| A设置模式下有三个子状态对应三个阈值设置4. 关键难点解决方案4.1 液位等级变化检测这是本项目的核心难点需要准确捕捉液位跨越阈值时刻。解决方案采用新旧值对比法在全局变量区定义int Liquid_Level; // 当前等级 int Old_Level; // 上次等级初始化时通过Level_Init()函数获取初始等级在主循环中实时比较void Level_Control() { // 获取当前液位高度 Liquid_Height Get_Current_Height(); // 判断等级变化 if(Liquid_Height Threshold1) { Liquid_Level 0; } else if(Liquid_Height Threshold2) { Liquid_Level 1; } // 其他等级判断... // 检测变化 if(Liquid_Level ! Old_Level) { Send_Report(Liquid_Height, Liquid_Level); // 发送上报 Trigger_LED2(); // 触发指示灯 Old_Level Liquid_Level; // 更新旧值 } }4.2 串口协议解析采用状态机实现协议解析支持两种查询指令和自动上报接收状态机设计typedef enum { WAIT_START, RECEIVING, PARSE_COMPLETE } UART_State; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { static UART_State state WAIT_START; static uint8_t index 0; switch(state) { case WAIT_START: if(rx_buf[0] C || rx_buf[0] S) { state RECEIVING; index 1; } break; case RECEIVING: if(rx_buf[index] \n) { state PARSE_COMPLETE; } break; } }数据打包示例void Send_Threshold_Response() { char buffer[32]; sprintf(buffer, S:TL%dTM%dTH%d\r\n, Threshold1, Threshold2, Threshold3); HAL_UART_Transmit(huart2, (uint8_t*)buffer, strlen(buffer), 100); }5. 调试技巧与常见问题5.1 典型问题排查表现象可能原因解决方案ADC读数不稳定未做滤波/采样时间不足增加软件滤波调整采样周期EEPROM写入失败未满足写入时序要求添加5ms延时检查I2C上拉串口数据乱码波特率不匹配核对双方波特率9600-8-N-1液位变化误报Old_Level初始化错误上电后立即读取初始液位等级LCD显示异常未及时清屏切换界面时调用LCD_Clear()5.2 实时调试建议利用SWD接口在Keil中设置实时变量监控Watch窗口重点监测Liquid_Height, Liquid_Level, Threshold1-3串口打印调试printf(ADC%.2fV H%dcm\r\n, ADC_Voltage, Liquid_Height);LED辅助调试临时修改LED闪烁模式指示不同状态例如快速闪烁表示进入异常分支6. 工程优化建议6.1 代码结构优化使用模块化头文件组织/Inc ├── adc.h ├── eeprom.h ├── lcd.h ├── uart.h └── main.h采用面向对象思想封装typedef struct { uint16_t raw_adc; float voltage; int height; void (*update)(void); } LiquidSensor_TypeDef; void LiquidSensor_Update() { // 实现采集逻辑 }6.2 性能提升方向ADC采样优化启用DMA连续采样模式采用硬件过采样16倍通信协议增强添加CRC校验字段实现超时重传机制低功耗设计void Enter_LowPower() { HAL_ADC_Stop(hadc1); HAL_UART_DeInit(huart2); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); }7. 备赛训练建议模块化训练路线第一阶段独立模块练习ADC、EEPROM、USART第二阶段功能组合实现ADCLCD显示第三阶段完整系统集成真题训练顺序第十一届省赛基础外设第十届省赛状态机设计第八届省赛复杂通信协议第九届省赛多任务调度调试能力培养熟练使用逻辑分析仪抓取时序掌握Keil在线调试技巧断点、变量监控建立系统化调试日志记录习惯在实际开发中我建议先使用STM32CubeMX生成基础外设配置然后重点编写业务逻辑代码。比赛中要注意合理分配时间先实现核心功能再完善细节。这个项目的完整代码已经过实际验证在蓝桥杯官方开发板上运行稳定可以作为可靠的参考实现。