1. 项目概述:便携式PM2.5监测系统设计
作为一名长期从事嵌入式系统开发的工程师,我最近完成了一个基于STM32的PM2.5监测系统项目。这个便携式设备能够实时检测空气中的颗粒物浓度,并通过LCD显示屏直观展示数据,当浓度超标时还会触发声光报警。整个系统的核心是一块STM32F103C8T6单片机,搭配PM2.5传感器和1602液晶显示屏,构成了一个完整的空气质量监测解决方案。
这个项目的特别之处在于它完美结合了硬件设计和软件编程,实现了从数据采集到处理再到显示的完整流程。系统工作频率为72MHz,具有响应速度快、功耗低、体积小巧等特点,非常适合家庭、办公室等室内环境使用。下面我将详细介绍这个系统的设计思路、实现过程以及开发中遇到的挑战和解决方案。
2. 硬件系统设计详解
2.1 整体架构设计
系统硬件由五个关键模块组成,形成了一个完整的数据采集和处理链条:
- STM32控制模块:系统的"大脑",负责协调各模块工作
- PM2.5检测模块:使用ZPH01传感器采集空气质量数据
- LCD显示模块:1602液晶屏实时显示PM2.5浓度值
- 按键输入模块:三个按键用于设置报警阈值
- 声光报警模块:LED指示灯和蜂鸣器组成超标报警系统
这些模块通过精心设计的电路连接在一起,构成了下图所示的硬件架构:

提示:在实际PCB布局时,建议将传感器模块与主控板保持适当距离,避免电磁干扰影响传感器读数精度。
2.2 STM32F103C8T6主控模块
2.2.1 单片机选型考量
选择STM32F103C8T6作为主控芯片主要基于以下几点考虑:
- 性能与功耗平衡:72MHz主频提供足够的处理能力,同时保持低功耗
- 丰富的外设接口:内置ADC、定时器、USART等,满足系统需求
- 开发资源丰富:STM32生态系统完善,有大量参考设计和社区支持
- 成本效益:价格适中,适合量产应用
这款芯片的具体参数如下:
- 工作频率:72MHz
- Flash容量:64KB
- SRAM容量:20KB
- 工作电压:2.0-3.6V
- 内置12位ADC(1μs转换时间)
- 多种通信接口(USART、I2C、SPI)
2.2.2 最小系统电路设计
为了让STM32正常工作,必须设计正确的最小系统电路,包括:
-
电源电路:
- 使用AMS1117-3.3稳压芯片将5V转换为3.3V
- 在VDD和GND之间添加0.1μF去耦电容
-
复位电路:
- 10kΩ上拉电阻配合100nF电容构成复位电路
- 添加手动复位按钮便于调试
-
时钟电路:
- 8MHz晶振配合两个22pF负载电容
- 32.768kHz低速晶振(可选,用于RTC)
-
调试接口:
- SWD接口(SWDIO和SWCLK)用于程序下载和调试

注意:晶振的负载电容值需要根据具体晶振参数调整,不正确的电容值可能导致起振困难。
2.3 PM2.5传感器模块
2.3.1 ZPH01传感器特性
本设计采用的ZPH01传感器具有以下特点:
- 检测范围:0-1000μg/m³
- 分辨率:1μg/m³
- 响应时间:<10s
- 工作电压:5V DC
- 输出方式:PWM和串口双模式
传感器内部采用激光散射原理检测颗粒物浓度,具有精度高、响应快的优点。在实际使用中,我选择了串口输出模式,因为这种方式抗干扰能力更强,数据传输更可靠。
2.3.2 传感器接口电路
传感器与STM32的连接需要注意以下几点:
- 电平转换:由于传感器是5V电平而STM32是3.3V,需要添加电平转换电路
- 电源滤波:传感器电源端添加100μF电解电容和0.1μF陶瓷电容滤波
- 信号隔离:在数据线上串联100Ω电阻减少干扰
典型连接方式:
- VCC → 5V电源
- GND → 共地
- TXD → STM32 USART RX引脚(通过电平转换)
- RXD → STM32 USART TX引脚(通过电平转换)
2.4 按键输入模块设计
系统设置了三个按键用于用户交互:
- K3:进入/退出阈值设置模式
- K4:增加阈值
- K5:减小阈值
按键电路采用经典的接地设计,当按键按下时,将IO口拉低。电路设计要点:
- 上拉电阻:内部启用上拉电阻(约40kΩ)
- 消抖处理:软件消抖(检测到按键按下后延时20ms再次检测)
- ESD保护:在IO口添加TVS二极管防止静电损坏

2.5 显示与报警模块
2.5.1 LCD1602显示接口
1602液晶屏采用4位数据线模式连接,节省IO口资源。具体连接方式:
- RS → PA0
- RW → GND(只写模式)
- EN → PA1
- D4-D7 → PA4-PA7
- VCC → 5V
- VO → 10kΩ电位器调节对比度
2.5.2 声光报警电路
报警模块由红色LED、绿色LED和蜂鸣器组成:
- 红色LED:PM2.5超标指示(PC13)
- 绿色LED:空气质量正常指示(PC14)
- 蜂鸣器:有源蜂鸣器(PC15驱动)
蜂鸣器驱动电路使用NPN三极管(如S8050)放大电流,基极通过1kΩ电阻连接IO口。

3. 软件系统设计与实现
3.1 开发环境搭建
3.1.1 Keil MDK安装配置
-
安装步骤:
- 下载Keil MDK5安装包
- 安装STM32F1系列设备支持包
- 安装ST-Link驱动
-
工程配置要点:
- 选择正确的设备型号(STM32F103C8)
- 设置正确的晶振频率(8MHz)
- 配置Flash下载算法
- 优化等级选择-O2平衡代码大小和速度
-
调试设置:
- 选择SWD调试接口
- 启用Reset and Run选项
- 设置正确的Flash下载地址(0x08000000)
3.1.2 必要的库函数
本工程使用了以下标准外设库:
- GPIO库:控制LED和按键
- USART库:与传感器通信
- ADC库:备用模拟输入
- TIM库:定时器和PWM输出
3.2 主程序流程设计
系统软件采用前后台架构,主循环不断检测传感器数据并更新显示,中断处理紧急事件。下面是详细的程序流程图:

3.2.1 初始化模块
系统上电后首先进行各模块初始化:
c复制void System_Init(void)
{
RCC_Configuration(); // 时钟配置
GPIO_Configuration(); // GPIO初始化
USART_Init(9600); // 串口初始化
LCD_Init(); // 液晶屏初始化
TIM3_Init(); // 定时器初始化
NVIC_Configuration(); // 中断配置
}
3.2.2 主循环设计
主循环完成以下功能:
- 读取传感器数据
- 更新LCD显示
- 检查报警条件
- 处理按键输入
典型实现代码:
c复制while(1)
{
PM25_Value = Read_Sensor(); // 读取传感器数据
Update_Display(PM25_Value); // 更新显示
if(PM25_Value > Threshold) // 检查报警条件
{
Trigger_Alarm();
}
Key_Process(); // 按键处理
Delay_ms(100); // 适当延时
}
3.3 关键功能实现
3.3.1 传感器数据读取
ZPH01传感器通过串口发送9字节数据包,格式如下:
- 头字节:0xFF
- 命令字节:0x18
- 数据字节:PM2.5高/低字节
- 校验和:前面所有字节的和
数据读取函数实现:
c复制uint16_t Read_Sensor(void)
{
uint8_t buffer[9];
uint16_t pm25 = 0;
if(USART_Receive(buffer, 9) == SUCCESS)
{
if(buffer[0]==0xFF && buffer[1]==0x18)
{
uint8_t checksum = 0;
for(int i=0; i<8; i++)
checksum += buffer[i];
if(checksum == buffer[8])
{
pm25 = (buffer[2]<<8) | buffer[3];
}
}
}
return pm25;
}
3.3.2 报警逻辑实现
报警系统采用状态机设计,有三个状态:
- NORMAL:PM2.5低于阈值,绿灯亮
- WARNING:PM2.5超过阈值,红灯亮
- ALARM:持续超标,触发蜂鸣器
状态转换代码:
c复制void Alarm_State_Machine(uint16_t pm25)
{
static enum {NORMAL, WARNING, ALARM} state = NORMAL;
static uint32_t alarm_timer = 0;
switch(state)
{
case NORMAL:
if(pm25 > Threshold)
{
state = WARNING;
LED_Red(ON);
LED_Green(OFF);
}
break;
case WARNING:
if(pm25 > Threshold + 10) // 超过阈值一定值
{
state = ALARM;
Buzzer(ON);
alarm_timer = Get_Tick();
}
else if(pm25 <= Threshold)
{
state = NORMAL;
LED_Red(OFF);
LED_Green(ON);
}
break;
case ALARM:
if(pm25 <= Threshold)
{
state = NORMAL;
LED_Red(OFF);
LED_Green(ON);
Buzzer(OFF);
}
else if(Get_Tick() - alarm_timer > 5000) // 报警5秒后停止蜂鸣器
{
Buzzer(OFF);
}
break;
}
}
3.3.3 按键处理实现
按键处理采用状态机方式,支持短按和长按:
c复制void Key_Process(void)
{
static uint8_t key_state[3] = {0};
static uint32_t key_timer[3] = {0};
for(int i=0; i<3; i++)
{
if(KEY_Read(i) == PRESSED)
{
if(key_state[i] == 0) // 首次按下
{
key_state[i] = 1;
key_timer[i] = Get_Tick();
}
else if(key_state[i] == 1 && (Get_Tick()-key_timer[i])>1000) // 长按
{
key_state[i] = 2;
Key_Long_Press_Action(i);
}
}
else
{
if(key_state[i] == 1) // 短按释放
{
Key_Short_Press_Action(i);
}
key_state[i] = 0;
}
}
}
4. 系统调试与优化
4.1 硬件调试要点
4.1.1 常见问题排查
-
电源问题:
- 现象:系统不稳定或频繁复位
- 检查:测量3.3V电压是否稳定,纹波是否过大
- 解决:增加电源滤波电容,检查稳压芯片散热
-
传感器无数据:
- 现象:LCD一直显示0
- 检查:测量传感器电源,检查串口线连接
- 解决:确认波特率设置正确(9600bps),检查电平转换电路
-
LCD显示异常:
- 现象:显示乱码或对比度不佳
- 检查:确认数据线连接正确,调节对比度电位器
- 解决:重新初始化LCD,检查时序延迟
4.1.2 焊接注意事项
-
STM32焊接:
- 使用刀头烙铁,温度控制在300-330℃
- 先焊接对角两个引脚固定芯片
- 使用优质焊锡丝,避免虚焊
-
传感器接口:
- 使用排针和排母连接,便于更换传感器
- 避免长时间高温焊接损坏传感器
-
蜂鸣器极性:
- 有源蜂鸣器必须注意正负极
- 反接可能导致损坏
4.2 软件调试技巧
4.2.1 调试工具使用
-
printf调试:
- 重定向printf到串口
- 输出关键变量值和程序状态
-
逻辑分析仪:
- 抓取传感器数据波形
- 分析通信时序是否正确
-
Keil调试器:
- 设置断点观察程序流程
- 查看外设寄存器状态
4.2.2 性能优化
-
内存优化:
- 使用const存储常量
- 合理使用局部变量减少栈使用
-
速度优化:
- 关键代码使用寄存器变量
- 避免在循环中调用耗时函数
-
功耗优化:
- 不使用时关闭外设时钟
- 适当使用休眠模式
4.3 实测效果展示
系统完成后的实测效果如下:
- 正常状态:
- PM2.5值:2.0μg/m³
- 阈值:13.7μg/m³
- 绿灯亮,蜂鸣器静音

- 报警状态:
- PM2.5值:34.4μg/m³
- 阈值:13.7μg/m³
- 红灯亮,蜂鸣器报警

5. 项目总结与改进方向
5.1 项目成果总结
经过多次调试优化,本PM2.5监测系统已达到设计目标:
- 功能完善:实现了数据采集、显示、报警等全部设计功能
- 性能稳定:连续工作24小时无异常,数据准确可靠
- 用户体验:操作简单直观,报警响应及时
系统主要技术指标:
- 测量范围:0-1000μg/m³
- 分辨率:1μg/m³
- 刷新率:1次/秒
- 工作电流:<50mA
- 报警响应时间:<2秒
5.2 经验分享
在开发过程中积累了一些宝贵经验:
-
传感器选择:
- 激光式传感器比红外式精度高但价格贵
- 注意传感器预热时间,通常需要30秒稳定
-
抗干扰设计:
- 数字信号线加100Ω串联电阻
- 模拟部分使用独立供电
- 合理布局地平面
-
低功耗技巧:
- 适当降低主频可显著减少功耗
- 使用中断唤醒代替轮询
5.3 未来改进方向
虽然系统已经实现基本功能,但仍有改进空间:
-
硬件改进:
- 增加WiFi模块实现数据上传
- 改用OLED显示屏提升可视角度
- 添加温湿度传感器扩展功能
-
软件增强:
- 实现数据记录和趋势分析
- 增加校准功能提高精度
- 开发手机APP远程监控
-
外观设计:
- 3D打印专用外壳
- 优化按键布局
- 增加安装挂孔
这个项目让我深刻体会到嵌入式系统开发的乐趣和挑战。从电路设计到编程实现,每个环节都需要严谨的态度和创新的思维。特别是在调试阶段,通过逻辑分析仪捕捉信号波形,逐步排查问题的过程,既考验耐心又充满成就感。