手把手教你用STM32F103和DL-22 Zigbee模块搞定颗粒物传感器无线传输(附完整代码)
从零构建STM32与Zigbee的颗粒物监测无线系统
最近在帮学校实验室搭建环境监测网络时,发现传统有线传感器布线不仅麻烦,而且灵活性极差。于是尝试用STM32F103搭配DL-22 Zigbee模块实现无线传输,过程中踩了不少坑,也积累了些实战经验。本文将分享从硬件连接到代码调试的完整流程,特别适合刚接触嵌入式开发的新手。
1. 硬件准备与模块配置
1.1 设备清单与选型建议
手头需要准备以下核心组件(以我的实际配置为例):
- 主控芯片:STM32F103VET6(发送端)/RCT6(接收端)
- 无线模块:DL-22 Zigbee透传模块×2
- 传感器:攀藤PMS5003颗粒物传感器
- 调试工具:USB-TTL转换器、杜邦线若干
注意:不同型号STM32的串口引脚可能不同,建议提前查阅对应芯片的datasheet。我用的VET6有5个USART接口,而RCT6只有3个。
1.2 Zigbee模块工作模式配置
DL-22支持两种通信模式,通过AT指令切换:
| 模式类型 | 特点 | 适用场景 |
|---|---|---|
| 点对点 | 需指定发送/接收端 | 定向数据传输 |
| 广播 | 所有模块同信道通信 | 组网广播 |
建议按以下步骤配置点对点模式:
- 用USB-TTL连接电脑,打开串口调试助手
- 发送
AT+MODE=P2P设置模式 - 发送端补充指令:
AT+ROLE=TX - 接收端补充指令:
AT+ROLE=RX - 双方设置相同信道:
AT+CH=15
# 示例配置流程(发送端) AT+MODE=P2P AT+ROLE=TX AT+CH=15 AT+SAVE2. 硬件连接与引脚分配
2.1 发送端接线方案
发送端需要同时连接传感器和Zigbee模块,具体引脚分配如下:
传感器接口:
- USART2(PA2/PA3) - 传感器TX/RX
- 5V - 传感器VCC
- GND - 共地
Zigbee模块:
- USART3(PB10/PB11) - 模块TX/RX
- 3.3V - 模块VCC
调试接口:
- USART1(PA9/PA10) - USB-TTL(可选)
2.2 接收端简化设计
接收端只需处理Zigbee通信:
- USART2(PA2/PA3) - Zigbee模块
- USART1(PA9/PA10) - 上位机通信
实际接线时遇到过的问题:曾将传感器TX误接单片机TX导致通信失败,切记RX-TX需要交叉连接。
3. 核心代码实现解析
3.1 发送端中断处理逻辑
传感器数据接收的关键在于USART2的中断服务函数。以PMS5003传感器为例,其数据帧格式为:
0xFF 0x01 0x03 PM2.5_H PM2.5_L ...对应中断处理代码:
#define DATA_LENGTH 10 uint8_t sensorBuffer[DATA_LENGTH]; volatile uint8_t dataFlag = 0; void USART2_IRQHandler(void) { static uint8_t count = 0; uint8_t byte = USART_ReceiveData(USART2); if(byte == 0xFF && count == 0) { sensorBuffer[count++] = byte; return; } if(count > 0 && count < DATA_LENGTH) { sensorBuffer[count++] = byte; // 完整帧校验 if(count == DATA_LENGTH && sensorBuffer[1] == 0x01) { uint16_t pm25 = (sensorBuffer[3]<<8) | sensorBuffer[4]; USART_SendData(USART3, pm25>>8); // 先发高字节 while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); USART_SendData(USART3, pm25); // 再发低字节 dataFlag = 1; count = 0; } } else { count = 0; // 异常重置 } }3.2 接收端数据转发实现
接收端需要将Zigbee数据转发给上位机:
void USART2_IRQHandler(void) { static uint8_t buffer[2], index = 0; uint8_t byte = USART_ReceiveData(USART2); buffer[index++] = byte; if(index == 2) { uint16_t pm25 = (buffer[0]<<8) | buffer[1]; printf("PM2.5: %dug/m3\r\n", pm25); index = 0; } }4. 调试技巧与性能优化
4.1 常见问题排查指南
根据实际调试经验,整理出以下问题排查表:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 无数据接收 | 接线错误 | 检查TX/RX交叉连接 |
| 数据乱码 | 波特率不匹配 | 确认所有设备波特率一致 |
| 通信不稳定 | 电源干扰 | 增加100uF电容滤波 |
| 丢包严重 | 中断处理耗时 | 优化ISR代码,避免复杂运算 |
4.2 中断服务优化建议
精简ISR代码:移除所有非必要操作,如:
- 避免在中断内调用printf
- 禁用浮点运算
- 使用静态变量减少栈操作
双缓冲技术:创建ping-pong缓冲区提高吞吐量
typedef struct { uint8_t buf[2][DATA_LENGTH]; volatile uint8_t activeBuf; } DoubleBuffer; DoubleBuffer dbuff; void USART2_IRQHandler(void) { static uint8_t pos = 0; uint8_t byte = USART_ReceiveData(USART2); dbuff.buf[dbuff.activeBuf][pos++] = byte; if(pos >= DATA_LENGTH) { dbuff.activeBuf ^= 1; // 切换缓冲区 pos = 0; // 触发主循环处理非活跃缓冲区数据 } }5. 系统扩展与进阶应用
5.1 多节点组网方案
通过修改Zigbee配置可实现星型网络:
- 设置一个协调器(Coordinator)
- 多个终端设备(End Device)连接传感器
- 使用广播模式传输数据
# 协调器配置 AT+MODE=BROADCAST AT+ROLE=COORD AT+CH=155.2 低功耗优化策略
对于电池供电场景:
- 启用STM32的STOP模式
- 配置传感器间歇工作
- 优化Zigbee发射功率
void Enter_LowPowerMode(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); SystemInit(); // 唤醒后需重新初始化时钟 }实际部署时发现,通过合理设置采样间隔(如5分钟一次),可使系统续航从1天提升至2周以上。
