)
这周在学校的智联场景实训箱上连肝了四个传感器实验大气压强、温湿度、二氧化碳、电子围栏。代码基于实训箱自带工程全部实测跑通。这篇不贴大段代码驱动文件都在工程里重点讲每个实验的核心逻辑和真正踩过的坑给同样在做 STM32 传感器实验的兄弟姐妹省点时间。一、实验环境项目配置主控芯片STM32L431VCTxCortex-M4主频 80MHz开发环境Keil MDK5 STM32L4xx HAL 库操作系统B06 电子围栏用了 LiteOS鸿蒙智联场景显示 / 调试板载 TFT LCD240×320 串口 2115200传感器接口软件模拟 I2CPB13SCLPB14SDA/ LPUART1二、实验一大气压强传感器CPS121CPS121 是无锡康森斯克Consensic的MEMS 绝压传感器I2C 接口、从机地址0x6C、量程 30~130kPa、绝对精度 ±0.1kPa、平均功耗 5μA非常适合做气压计 / 海拔计。核心代码void CPS121_read_result(float *Pressure) { uint32_t press; uint8_t buff[6]; CPS121_measure(); // 发测量命令(0x30,0x0A)等20ms /* 软件I2C连续读3字节到 buff[0] buff[1] buff[2] */ press (buff[0] 16) (buff[1] 8) buff[2]; // 24bit合成 *Pressure ((float)press / 64.0f) / 1000.0f; // 转成kPa }业务上就是 1 秒读一次LCD 显示 大气压强值:xx.xxxkPa、串口打印、LED 每秒闪一下非常简单。实验现象读出来 99.8kPa 左右和天气 App 对得上哈尔滨海拔不高气压就在标准大气压附近。⚠️重点坑必看工程原代码合成气压时写的是 buff[3]但读数据只读了 buff[0~2] 三个字节 ——buff[3]是栈上没初始化的随机值运气好碰上是 0 读数就正常运气不好气压值直接跳到几百 kPa。这就是 实验能跑通 ≠ 代码是对的 的典型案例数值异常时先怀疑数组越界 / 未初始化。三、实验二温湿度传感器SHT30SHT30 是 Sensirion 家的数字温湿度传感器I2C 地址0x44温度 ±0.3℃、湿度 ±2% RH出厂校准不用标定是 DHT11 的理想升级款。核心代码void SHT30_read_result(float *Temperature, float *Humidity) { uint16_t tem, hum; uint8_t buff[6]; // 1. 发单次测量命令 0x2C 0x06高重复性等50ms转换完成 // 2. 连读6字节温度高/低/CRC 湿度高/低/CRC tem (buff[0] 8) buff[1]; // 温度16bit原始值 hum (buff[3] 8) buff[4]; // 湿度16bit原始值 // 3. 按数据手册公式换算 *Temperature 175.0f * (float)tem / 65535.0f - 45.0f; *Humidity 100.0f * (float)hum / 65535.0f; }实验现象教室 26℃、湿度 45% 左右对着传感器哈一口气湿度瞬间冲到 70%响应很灵敏。⚠️ 注意事项一是单次测量后要等 50ms再读等太短会读到旧数据二是 16 位原始值必须按手册公式换算别自己瞎猜比例三是读最后一字节按规范应该发 NACK原厂代码发的是 ACK实测能用但不符合标准。四、实验三二氧化碳传感器SGP30SGP30 能同时输出CO2ppm TVOCppbI2C 地址0x58CO2 量程 400~60000ppm很适合做空气质量 / 新风系统。核心代码void Init_SGP30(void) { SGP30_Write_Command(0x20, 0x03); } // 初始化(init_air_quality) void SGP30_Handle(uint16_t *CO2, uint16_t *TVOC) { SGP30_Write_Command(0x20, 0x08); // 开始测量(measure_air_quality) delay_ms(180); // 转换时间180ms四个传感器里最慢 Read_SGP30(CO2, TVOC); // 读6字节CO2高/低/CRC TVOC高/低/CRC }实验现象教室 30 多号人CO2 稳稳 800~1000ppm人少能掉到 500 以下趋势很合理。⚠️重点坑必看屏幕一直显示 二氧化碳:---别急着怀疑硬件 —— 工程代码里 if(CO2_value 300 CO2_value 500) 才显示显示范围被写死成 300~500ppm而教室 CO2 轻松破千根本不在区间里。把范围放宽300~20000或先串口打印原始值确认就知道数据其实一直是好的。另外两点提醒① SGP30上电后基线要漂移几个小时才准刚开机读数偏高是正常的② 读出来的 CRC 字节原代码根本没校验短线上 I2C 出错概率低所以实验能过但工业级代码必须补 CRC-8 校验。五、实验四电子围栏场景DYP-R01 微波雷达这个实验画风完全不同两台 DYP-R01 雷达组成 电子围栏闯入就报警还接了 WiFi 上华为云。它是跑在LiteOS上的main 里创建了 3 个任务采集 / 业务 / 显示并发调度 —— 单 while (1) 循环在这里已经不够用了。核心代码业务判定// Modbus-RTU 查询帧读从机0x01的保持寄存器0x0100 uint8_t send_data[] {0x01, 0x03, 0x01, 0x00, 0x00, 0x01, 0x85, 0xF6}; // 两路雷达距离都在50~100cm 正常否则 闯入 if(((data1 50) (data1 100)) ((data2 50) (data2 100))) { state 0; // 正常 } else { printf(** 存在非法闯入\r\n); state 1; // 闯入 → 蜂鸣器报警 }实验现象手伸进围栏区域LCD 从 正常 变 有人闯入、蜂鸣器嘀嘀响手撤回去恢复 入侵结束非常直观。⚠️重点坑必看原代码用 HAL_UART_Receive(hlpuart1, buf, 100, 300)阻塞接收—— 雷达帧明明只有 7 字节却要收 100 字节、超时 300ms。在 100ms 周期的采集任务里一旦没数据就被卡 3 个周期系统反应迟钝。工程做法是改 UART 空闲中断 DMA不想大改至少把接收长度改成 7、超时改小。另外两个雷达共用一路 LPUART1靠重新初始化串口切换读取UART_Change()切换瞬间可能读到脏数据偶发 9999 截断值所以切换代码里要留 HAL_Delay(1) 等时序稳定。六、四款传感器对比含总结传感器测量对象通信量程精度总结CPS121大气压软件 I2C 0x6C30~130kPa±0.1kPa国产绝压传感器功耗极低、精度够用适合气压 / 海拔场景。注意24bit 合成别读错字节越界坑SHT30温度 / 湿度软件 I2C 0x44-40~125℃ / 0~100%RH±0.3℃ / ±2%RH数字温湿度计的 标准答案出厂校准免标定。注意测量后等 50ms按手册公式换算SGP30CO2/TVOC软件 I2C 0x58400~60000ppm±(50ppm15% 读数)空气质量监测首选CO2TVOC 二合一。注意基线漂移需数小时、转换 180ms 最慢、显示范围别写死DYP-R01距离 / 入侵LPUART1 Modbus-RTU0.02~4m (以模块为准)视模块非接触安防雷达不怕光线灰尘。注意阻塞接收改中断 / DMA双雷达共用串口切换要留时序规格参数来自各芯片数据手册及模块公开资料实际以你手上的模块为准。附四个实验单次采集耗时对比图见随文 HTML 文件CPS121≈20ms / SHT30≈50ms / SGP30≈180ms / DYP 超时窗口 300ms浏览器打开截图即可插图。七、总结四个实验做下来最大的感受I2C 驱动万变不离其宗CPS121/SHT30/SGP30 全是 发命令 → 等转换 → 读数据 → 公式换算 四步走会一个就能照着写其他的。看数据手册比看别人代码重要SHT30 的 175/65535−45、SGP30 的 0x2008、Modbus 的 CRC这些 魔法数字 只有手册能给答案。不要相信模板代码buff[3] 越界、BH1750 注释、300~500 显示范围全是模板里埋的雷跑通之后一定要自己 review 一遍。单循环 vs RTOS三个传感器实验 while(1) 够用但到电子围栏这种 采集 显示 上云 按键 并行的场景LiteOS 多任务才是正解。如果帮到了你欢迎点赞收藏评论区交流本文基于学校智联场景实训箱STM32L431 Keil MDK5 HAL 库真实工程代码整理代码已实测跑通。