当前位置: 首页 > news >正文

蓝桥杯嵌入式第七届省赛:模拟液位检测告警系统全模块解析

1. 项目背景与需求解析

第七届蓝桥杯嵌入式省赛的"模拟液位检测告警系统"是一个典型的工业控制场景应用。这个项目要求选手通过STM32开发板实现一个完整的液位监控系统,涉及模拟信号采集、数据处理、人机交互和通信协议等多个嵌入式开发核心技能点。

系统核心需求可以拆解为五个关键模块:

  • 模拟量采集:通过电位器R37模拟液位传感器输出,需要完成ADC采集和软件滤波
  • 阈值管理:支持三级阈值设置(默认30/50/70cm),参数需存储到EEPROM
  • 状态判断:根据当前液位高度自动划分四个等级(0-3级)
  • 通信接口:通过USART2实现与PC的数据交互(查询+自动上报)
  • 状态指示:三路LED分别表示运行状态、液位变化和通信事件

在实际工业场景中,类似的液位检测系统广泛应用于储罐监控、化工生产等领域。比赛中将工业场景简化为开发板上的电位器模拟,但完整保留了真实系统中的技术要点。

2. 硬件架构设计

2.1 核心硬件配置

系统基于蓝桥杯官方CT117E开发板,主控采用STM32F103RBT6,主要外设包括:

  • ADC通道:PA1连接电位器R37(模拟液位信号)
  • EEPROM:AT24C02芯片存储阈值参数
  • 显示模块:LCD12864液晶屏
  • 输入设备:四个独立按键(K1-K4)
  • 指示设备:三个LED灯(LD1-LD3)
  • 通信接口:USART2(PA2/PA3)

硬件连接示意图:

[电位器R37] --> [PA1(ADC1)] [按键K1-K4] --> [PE2-PE5] [LCD12864] <--> [FSMC接口] [USART2] <--> [CH340G USB转串口]

2.2 关键电路设计要点

  1. ADC前端处理

    • 电位器输出接入RC低通滤波(R=10kΩ, C=0.1μF)
    • 参考电压使用板载3.3V稳压源
    • 采样周期设置为239.5周期(对应约1ms采样时间)
  2. EEPROM电路

    • I2C总线需配置4.7kΩ上拉电阻
    • 地址引脚全部接地(设备地址0xA0)
    • 写入周期需延时5ms以上
  3. 抗干扰设计

    • 所有数字信号线串联22Ω电阻
    • 模拟地与数字地单点连接
    • 电源入口处增加100μF+0.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 模块化设计要点

  1. 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 i=0; i<FILTER_N; i++) { sum += filter_buf[i]; } return sum / FILTER_N; }
  2. EEPROM存储管理

    • 使用页写入模式(每页8字节)
    • 存储结构:
      地址内容长度
      0x00阈值1(30)2字节
      0x02阈值2(50)2字节
      0x04阈值3(70)2字节
  3. 状态机设计

    • 系统存在两个主要状态:
      graph LR A[监测模式] -->|K1按下| B[设置模式] B -->|K1按下| A
    • 设置模式下有三个子状态(对应三个阈值设置)

4. 关键难点解决方案

4.1 液位等级变化检测

这是本项目的核心难点,需要准确捕捉液位跨越阈值时刻。解决方案采用"新旧值对比法":

  1. 在全局变量区定义:

    int Liquid_Level; // 当前等级 int Old_Level; // 上次等级
  2. 初始化时通过Level_Init()函数获取初始等级

  3. 在主循环中实时比较:

    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 串口协议解析

采用状态机实现协议解析,支持两种查询指令和自动上报:

  1. 接收状态机设计:

    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; } }
  2. 数据打包示例:

    void Send_Threshold_Response() { char buffer[32]; sprintf(buffer, "S:TL%d+TM%d+TH%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 实时调试建议

  1. 利用SWD接口

    • 在Keil中设置实时变量监控(Watch窗口)
    • 重点监测:
      Liquid_Height, Liquid_Level, Threshold1-3
  2. 串口打印调试

    printf("ADC=%.2fV H=%dcm\r\n", ADC_Voltage, Liquid_Height);
  3. LED辅助调试

    • 临时修改LED闪烁模式指示不同状态
    • 例如:快速闪烁表示进入异常分支

6. 工程优化建议

6.1 代码结构优化

  1. 使用模块化头文件组织:

    /Inc ├── adc.h ├── eeprom.h ├── lcd.h ├── uart.h └── main.h
  2. 采用面向对象思想封装:

    typedef struct { uint16_t raw_adc; float voltage; int height; void (*update)(void); } LiquidSensor_TypeDef; void LiquidSensor_Update() { // 实现采集逻辑 }

6.2 性能提升方向

  1. ADC采样优化

    • 启用DMA连续采样模式
    • 采用硬件过采样(16倍)
  2. 通信协议增强

    • 添加CRC校验字段
    • 实现超时重传机制
  3. 低功耗设计

    void Enter_LowPower() { HAL_ADC_Stop(&hadc1); HAL_UART_DeInit(&huart2); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); }

7. 备赛训练建议

  1. 模块化训练路线

    • 第一阶段:独立模块练习(ADC、EEPROM、USART)
    • 第二阶段:功能组合实现(ADC+LCD显示)
    • 第三阶段:完整系统集成
  2. 真题训练顺序

    1. 第十一届省赛(基础外设)
    2. 第十届省赛(状态机设计)
    3. 第八届省赛(复杂通信协议)
    4. 第九届省赛(多任务调度)
  3. 调试能力培养

    • 熟练使用逻辑分析仪抓取时序
    • 掌握Keil在线调试技巧(断点、变量监控)
    • 建立系统化调试日志记录习惯

在实际开发中,我建议先使用STM32CubeMX生成基础外设配置,然后重点编写业务逻辑代码。比赛中要注意合理分配时间,先实现核心功能再完善细节。这个项目的完整代码已经过实际验证,在蓝桥杯官方开发板上运行稳定,可以作为可靠的参考实现。

http://www.jsqmd.com/news/1198793/

相关文章:

  • 中断服务函数 从入门到实战全解析
  • MOBA战术转换:AD发育不顺时如何帮打野起飞
  • 【Linux】imx6ull Kernel 源码获取与编译环境一站式搭建指南
  • 【硬件工程师】元器件选型,你真的懂‘通用’吗?
  • 《逆时追捕》 电视剧|在线观看|下载|完整版
  • 从摇号机开发看随机算法陷阱与工程化实践
  • 移动端芯片代号与性能定位全解析
  • 植物工具精准使用指南:白鼠尾草、迷迭香、薰衣草的核心逻辑
  • 从零打造高效能NanoPC-T4(RK3399)工作站:系统部署与开发环境全攻略
  • Proteus仿真STM32时钟配置避坑指南:从外部晶振失效到内部HSI的实战切换
  • 从Prompt工程师到行业解决方案专家:ChatGPT入门者的3个月跃迁路径图(附17个已验证垂直场景prompt库)
  • 2026年7月最新亨得利官方服务项目及价格查询|地址与电话权威信息通告 - 亨得利官方博客
  • MAX3232双路串口独立运行的关键:TTL端上拉电阻的抗干扰设计
  • C++线程安全队列:从互斥锁到条件变量的生产者-消费者模式实现
  • 阿里云百炼 GLM-5.2 Fast mode 降价 20%,对 OpenStarry 用户意味着什么?
  • KSC-Defender防火墙配置完全教程:保护你的网络连接
  • 2026 年更新:紫金专业的球墨铸铁井盖生产商电话,揭秘:这个老旧井盖的秘密竟能延长水管寿命? - 品质体验官
  • 3分钟掌握JetBrains IDE无限试用终极技巧:ide-eval-resetter完整指南
  • C++ std::invalid_argument异常:从原理到实战的全面解析与防御性编程指南
  • Cursor不是插件,是AI原生开发工作流的重新定义
  • 华为内部分享||从波形中淘金:如何在看似正常的仿真结果里揪出隐藏Bug
  • 图形渲染核心数学:点积在着色器中的原理与应用实战
  • 2026年一份GEO源头厂商避坑选型深度评测报告:浙江企业如何抓住AI搜索红利 - 品牌报告
  • HMIR系统服务管理揭秘:基于systemd的服务监控与自动化运维
  • 2026年7月最新亨得利官方服务项目及价格查询|详细地址及24小时热线权威信息公示 - 亨得利官方
  • 如何快速上手nvwa?5分钟掌握openEuler内核热升级神器
  • 嵌入式系统启动探秘:从BootROM到App的逐层解码
  • CAN过滤器配置实战:从掩码模式到列表模式的精准匹配
  • Siemens S7-1200 PLC Modbus RTU轮询通讯实战:从单表到多表的进阶配置
  • 小刘同学的模拟IC设计实践笔记:从拉扎维理论到仿真调试