这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【E22P-433MBH-SC无线模块开发测试套件】双机温湿度互联系统

共2条 1/1 1 跳转至页

【E22P-433MBH-SC无线模块开发测试套件】双机温湿度互联系统

高工
2026-09-27 08:10:19     打赏
STM32 + LoRa 双机温湿度互联系统(基于 Zephyr RTOS)

项目分享:把亿佰特 E22-433M30S LoRa 评估板演示固件从裸机移植到 Zephyr 4.4, 并在其上实现两块开发板的温湿度(SHT30)实时互联。

1. 项目简介

本项目在两块 STM32F103C8T6 + E22-433M30S(SX1268,433MHz LoRa) 开发板上实现:

  • 图形化菜单(SSD1306 OLED,u8g2 图形库 + MultMenu 菜单框架): LoRa 参数设置(SF/BW/CR/频率/功率/包数)、Tx/Rx 收发测试(含 RSSI、丢包统计)

  • 双机温湿度互联:每块板通过 SHT30 采集本地温湿度,经 LoRa 周期性互发; OLED 上实时显示互联状态(Online/Offline)、本地/对端温湿度、对端信号强度 RSSI、 收发包计数

  • USB CDC 虚拟串口控制台(诊断日志)、LED 收发指示、蜂鸣器按键音

整个系统运行在 Zephyr RTOS 4.4 上,由 AI 代理辅助完成移植与调试。

2. 硬件平台与接线

2.1 开发板资源(板载,无需接线)

功能引脚
LoRa 模组 SPI1PA5/PA6/PA7 + CS PA4
模组 RESET / BUSY / DIO1PB0 / PB1 / PA3
模组射频开关 TXEN / RXENPB12 / PB13
OLED(SSD1306,I2C2)PB10/PB11
按键 上/下/确认PB4 / PB9 / PB7
LED_TX / LED_RXPA15 / PB6
蜂鸣器(TIM2_CH2)PB3
USB CDCPA11/PA12
SWD 调试PA13/PA14

2.2 外接 SHT30(至少一块板)

板载硬件 I2C 引脚均被占用或未引出,SHT30 使用软件模拟 I2C:

SHT30 模块开发板排针(CON2)
VCC3.3V(针 2)
GNDGND(针 5)
SCLPB15(针 9)
SDAPB14(针 10)
  • 模块 ADDR 脚接法不限(0x44/0x45 固件自动探测)

  • 只靠芯片内部上拉即可工作;若读数不稳定,SCL/SDA 各加 4.7kΩ 上拉到 3.3V

3. 功能演示指南

  1. 两块板上电 → OLED 显示 logo → 进入菜单首页

  2. 菜单操作:上/下/确认三键(PB4/PB9/PB7),按键有蜂鸣提示音

  3. TH Link 页(双机互联主界面):

Link : Online          ← 双机互联状态(6s 内收到对端包)
Local: 25.3C  48.2%    ← 本机 SHT30
Peer : 24.9C  50.1%    ← 对端温湿度(无传感器显示 --)
RSSI : -45dBm  2s ago  ← 对端最近一包信号强度/距今时间
TX/RX: 123/45          ← 本板已发包数 / 已收对端包数

实物图:image.png

image.png

4. 系统架构

4.1 线程模型

main 线程:设备检查 → key/led/e22/th_link 初始化 → 创建菜单线程
菜单线程(1536B 栈):key_scan_tick() + Menu_Task(),2ms 节拍
互联线程(1536B 栈):每 2.0~2.8s(周期由芯片 UID 决定)读 SHT30 → LoRa 发包 → 挂接收
系统工作队列(2048B 栈):LoRa 接收回调(只做校验+数据更新)

4.2 代码结构(D:\luglZephyrproject\app\e22_433m30s_demo)

src/
 main.c        入口
 e22_demo.c    LoRa 应用层(Zephyr lora API:lora_config/send/recv_async)
 th_link.c     双机互联:SHT30 采集、数据包协议、收发调度、状态判定
 sw_i2c.c      自写软件 I2C 主机(GPIO bit-bang,方向切换式)
 key.c/led.c/buzzer.c/u8g2_hal.c   平台移植层
MultMenu/       菜单框架 + 应用回调(原工程代码,最小改动)
u8g2Lib/        u8g2 图形库(原工程裁剪版,零改动)
boards/stm32_min_dev_stm32f103xb.overlay   全部硬件描述(设备树)

4.3 互联协议

  • 数据包(8 字节,__packed):'T','H' | seq | temp×100(int16) | hum×100(int16) | CRC8

  • CRC-8 多项式 0x31 初值 0xFF(与 SHT30 相同),覆盖 crc8 之前所有字段

  • 传感器无效时发哨兵值 INT16_MAX:互联状态与传感器解耦,Link 照样 Online

  • 接收回调校验 magic + CRC,通过才更新对端数据与 RSSI

5. 关键技术点

  1. Zephyr LoRa 子系统:内核自带 SX1268 驱动(LBM 后端),TCXO 电压/射频开关/ 复位时序全部在设备树里声明,应用层只需 lora_config/lora_send/lora_recv_async

  2. u8g2 + MultMenu 整体复用:只重写约 100 行 I2C 移植层,几千行界面代码零改动

  3. 软件 I2C(方向切换式 bit-bang):STM32F1 硬件 I2C 全部被占用, PB15/PB14 上 GPIO 模拟,开漏语义用"输入带上拉=释放 / 输出低=拉低"实现

  4. 双机免同步错频:发包周期用 STM32 96 位唯一芯片 ID 派生(每片不同), 两台设备的发送窗口持续滑动,无需任何握手即可避免持续对撞

  5. 射频仲裁:进菜单 Tx/Rx 测试时后台互联自动挂起,退出自动恢复

6. 调试历程(踩坑记录)

这次开发中最有价值的部分——四个真实踩到的坑:

坑 1:J-Link 拒绝烧录(器件型号 64KB 限制)

Zephyr 按板型给 J-Link 传 STM32F103C8(标称 64KB),86KB 固件越界被拒。 解决:手动指定 STM32F103CB(128KB 兼容型号)烧录。C8 芯片实际多有 128KB, 设备树里把 flash0 扩到 128KB 即可。

坑 2:F1 内部上拉在输出模式无效(SHT30 读不到)

软 I2C 初版用"开漏输出 + 内部上拉",结果 SHT30 完全无应答。 根因:STM32F1 的内部上拉电阻只在输入模式生效(RM0008), 开漏输出模式下释放总线 = 引脚悬空。 解决:改为方向切换式——释放总线切成"输入+上拉",拉低切成"输出低"。

坑 3:双机持续对撞(偶尔收到一包)

两板都是固定 2s 发包周期,节拍接近时每轮都在同一瞬间发射, 发射期间收不到对方,只有晶振误差让相位慢慢漂开才偶尔收到一包 (现象:RSSI 有值但 "111s ago")。 第一版修复(失败):(启动时刻 + 序号×397) % 800 抖动——两板序号同步递增, 若上电时刻接近,抖动同步变化,依然对撞。 最终修复:用芯片唯一 ID 派生不同的基础周期(如 2.1s vs 2.45s), 发送窗口持续滑动,必然频繁错开。

坑 4:结构体填充字节毁掉 CRC(RX 恒为 0)

数据包结构体没加 __packed,编译器在 uint8 seq 和 int16 temp 之间插了 1 字节填充。发送方算 CRC 时把未初始化的填充字节和 crc 字段本身的垃圾值 算了进去,接收方用收到的真实 crc 值重算——必然不匹配,几乎每包都被丢弃 (约 1/256 概率碰巧对上,正好解释了"偶尔能收到")。 解决:__packed + 零初始化 + CRC 长度用 offsetof(crc8)。 教训:跨设备协议结构体必须 packed,CRC 覆盖范围要用 offsetof 显式表达, 不要依赖 sizeof 的巧合。

调试方法论

  • 固件里主动埋诊断:串口日志(每周期一条:发送计数/传感器错误码/ 收到对端包)+ OLED 上直接显示 TX/RX 包计数,不用串口也能分诊

  • 解耦排查:传感器无效也照常发包(哨兵值),把"射频通不通"和 "传感器通不通"拆成两个独立问题

  • 计数器分诊:TX 不涨=没发出、TX 涨 RX 不涨=收不到、RX 涨=通了

7. 构建与烧录

# 构建(Git Bash)
cd /d/luglZephyrproject
ZEPHYR_TOOLCHAIN_VARIANT=zephyr \
ZEPHYR_SDK_INSTALL_DIR='D:\luglZephyrproject\zephyr-sdk-1.0.1\zephyr-sdk-1.0.1' \
west build -b stm32_min_dev/stm32f103xb app/e22_433m30s_demo -p always

# 烧录(J-Link,注意用 STM32F103CB 型号)
"C:\Program Files\SEGGER\JLink\JLink.exe" -nogui 1 -if swd -speed 4000 \
   -device STM32F103CB -CommanderScript jlink_flash.jlink
# jlink_flash.jlink 内容:r / h / loadfile ...zephyr.hex / r / g / q

USB 串口(115200 8N1)可查看诊断日志:TH: SHT30 found at 0x44、 TH: local=25.3C/48.2% sent#12、TH: peer packet rssi=-45 等。

8. 资源占用

区域占用总量占比
FLASH89916 B128 KB68.6%
SRAM20160 B20 KB98.4%

SRAM 余量仅约 300B,为塞进 20KB 做的裁剪:主栈/中断栈各 1024、菜单与互联线程 各 1536、系统工作队列 2048(LoRa 接收回调需要)、CDC FIFO 256/256、USB 缓冲池 256。

9. 已知限制

  1. Zephyr LoRa 驱动只支持标准同步字(私有 0x1424),与原 Keil 固件(0x14)不互通; 两块 Zephyr 板之间互通

  2. 菜单 Tx/Rx 测试与后台互联共用射频,进入测试页时互联暂停(TH Link 显示 Offline 属正常),退出后自动恢复

  3. 软 I2C 约 50kHz,只服务 SHT30(每 2 秒约 1ms 事务),不影响显示与射频

  4. SRAM 余量小,如需加功能优先考虑砍 USB CDC(可省约 7.5KB RAM)

10. 总结

  • 移植:裸机 → Zephyr,换来驱动生态(LoRa/USB/PWM 现成)、硬件描述与代码解耦、 安全的并发模型;代价是资源开销与底层控制力下降

  • 互联:8 字节小包 + CRC + UID 错频 + 状态解耦,用最简单的机制实现了 免配置的双机数据互通

  • 调试:四个坑(烧录型号、F1 上拉、双机对撞、结构体填充)覆盖了嵌入式开发中 工具链、硬件特性、分布式时序、C 语言内存布局四类典型问题,值得复盘





关键词: E22P-433MBH-SC     无线     Zephyr         

专家
2026-09-28 08:38:10     打赏
2楼

谢谢分享


共2条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]