从零实现 STM32 空气质量检测:SGP30 采集等效 CO₂,LCD 显示 + 串口输出,附踩坑与偏差分析
重要提醒SGP30 输出的是等效二氧化碳 eCO₂并非直接物理检测真实 CO₂数值由芯片内部算法换算得出同时可以输出 TVOC 总挥发性有机物。0. 前言最近完成物联网嵌入式课程实验使用 STM32L4 单片机搭配 SGP30 气体传感器采用软件模拟 I2C的方式读取气体数据。通过硬件 SPI 驱动 LCD 屏幕做本地可视化串口向上位机输出测量结果LED 指示灯用来提示采样状态。网上很多相关示例只粘贴源码缺少原理讲解、真实实验现象记录、结果偏差分析以及故障排查。本篇博客完整记录硬件接线、实验目的、工作原理、核心代码、实验现象、踩坑经验和优化方案适合嵌入式新手学习也可以作为课程实验参考。实验目的理解 SGP30 气体传感器工作原理分清等效 eCO₂和真实二氧化碳的区别掌握软件模拟 I2C 通信时序。熟悉 STM32‑L4 HAL 库开发掌握系统时钟、GPIO、串口、SPI‑LCD 显示屏的配置与调用。实现 SGP30 传感器数据采集完成 LCD 本地显示、串口打印、LED 采样状态指示整套功能。学会利用HAL_GetTick()实现非阻塞定时采样理解传感器预热、测量延时对数据的影响对数据做简单有效性校验。体会嵌入式模块化分层编程能够对比预期与实际实验现象分析数据偏差掌握软硬件问题排查思路。开发环境主控芯片STM32L4传感器SGP30I2C 接口外设SPI‑LCD 显示屏、LED 指示灯、USART2 串口固件库STM32 HAL 库串口助手波特率115200一、硬件接线本项目采用软件模拟 I2C不使用芯片硬件 I2C 外设直接操作 GPIO 引脚模拟 I2C 总线时序。表格SGP30 引脚STM32 引脚说明VCC3.3V⚠️严禁接入 5V会直接烧毁传感器GNDGND开发板与传感器必须共地保证通信稳定SCLPB13I2C 时钟信号线SDAPB14I2C 数据信号线其余外设说明LCD 显示屏硬件 SPI3 进行通信USART2外接 USB‑TTL 模块连接电脑LED1普通 GPIO 引脚作为采样动作提示灯。二、整体工作原理2.1 SGP30 芯片关键点发送测量命令0x20 0x08后必须延时 180ms才能读取有效数据属于芯片手册硬性要求时间不足会读到乱码传感器上电存在预热过程刚上电输出数据无效传感单元需要加热稳定核心 I2C 指令初始化命令0x20 0x03启动测量命令0x20 0x08返回数据包包含 eCO₂、TVOC同时附带 CRC 校验字节。2.2 软件模拟 I2C没有使用片上硬件 I2C依靠 GPIO 输出高低电平模拟 I2C 起始、停止、应答、读写时序。⚠️延时精度高度依赖SYSCLOCK宏如果该宏和实际系统时钟不一致I2C 时序错乱直接通信失败。2.3 软件分层架构工程采用模块化分层各个模块职责分离便于调试与二次开发。表格文件功能说明main.c系统初始化程序入口主循环任务调度sgp30.c传感器驱动核心软件 I2C 时序、指令收发、数据解析handle.c业务逻辑层非阻塞定时采样、LCD 绘制、串口打印、数据有效性校验spi.c硬件 SPI 底层驱动专门服务 LCD 屏幕显示2.4 采样机制使用HAL_GetTick()实现1000ms 非阻塞定时采样不使用HAL_Delay()阻塞 CPU。简单过滤规则eCO₂数值处于 300‑500ppm 视为有效无效数据屏幕显示---。整体业务流程系统初始化 → LCD 开机界面绘制 → SGP30 传感器初始化 → 主循环运行 → 1s 周期触发采样 → 发送测量指令 延时 180ms → I2C 读取 eCO₂、TVOC → 数据校验 → LCD 刷新、串口打印、LED 电平翻转。三、核心代码片段I2C 底层工具函数起始、停止、读写字节属于通用工具代码文章不完整粘贴只展示业务核心部分。3.1 main.c 主函数int main(void) { HAL_Init(); SystemClock_Config(); LCD_Display_Init(); //屏幕初始化显示 gpio_module_open(LEDS); uart_open(uart2, 115200); printf(\r\n 二氧化碳检测实验 \r\n); printf(------------------------------\r\n); printf(开始本实验\r\n\r\n); Init_SGP30(); //SGP30传感器引脚初始化 printf(** 二氧化碳传感器初始化\r\n); while(1) { CO2_Handle(); //采样与业务处理函数 } }3.2 sgp30.c 驱动核心//传感器初始化发送初始化命令0x20 0x03 void Init_SGP30(void) { SGP30_GPIO_Init(); SGP30_Write_Command(0x20,0x03); } //发送测量指令 0x20 0x08启动一次气体测量 static void Start_SGP30(void) { SGP30_Write_Command(0x20,0x08); } //I2C读取CO2、TVOC以及CRC校验字节 static void Read_SGP30(uint16_t* CO2,uint16_t* TVOC) { uint8_t crc 0; SGP30_IIC_Start(); SGP30_Write_Byte(SGP30_ADD_READ); SGP30_IIC_Wait_Ack(); *CO2 (uint16_t)(SGP30_Read_Byte(ACK) 8); *CO2 (uint16_t)SGP30_Read_Byte(ACK); crc SGP30_Read_Byte(ACK); *TVOC (uint16_t)(SGP30_Read_Byte(ACK) 8); *TVOC (uint16_t)SGP30_Read_Byte(ACK); crc SGP30_Read_Byte(NOACK); SGP30_IIC_Stop(); } //对外读取接口180ms芯片强制要求不可删减 void SGP30_Handle(uint16_t* CO2,uint16_t* TVOC) { Start_SGP30(); delay_ms(180); Read_SGP30(CO2,TVOC); }3.3 handle.c 业务处理 CO2_Handlevoid CO2_Handle(void) { uint16_t CO2_value 0; uint16_t TVOC_value 0; char str[20]; static uint32_t tickstart; //非阻塞1000ms采样一次 if((HAL_GetTick() - tickstart) 1000) { tickstart HAL_GetTick(); memset(str,0,sizeof(str)); SGP30_Handle(CO2_value,TVOC_value); //简单有效性校验 if(CO2_value 300 (CO2_value 500)) { sprintf(str,二氧化碳浓度: %d,CO2_value); printf(** 读取二氧化碳传感器数据\r\n); printf(** 二氧化碳浓度:%d ppm\r\n\r\n, CO2_value); } else { sprintf(str,二氧化碳:---); } LCD_Fill(90,182,230,198,WHITE); //清除旧区域消除残影 Show_Str(90,182,BLUE,WHITE,(uint8_t *)str,16,1); led_toggle(LED1_PORT); //采样完成翻转LED } }3.4 spi.c 简要说明spi.c封装 SPI1/SPI2/SPI3 硬件外设提供初始化、开关、全双工读写接口LCD 屏幕依赖该驱动完成图像显示属于平台公共底层代码。四、实验结果与偏差分析✅预期目标LCD 屏幕正常上电初始化显示标题、图标每秒刷新 CO₂浓度串口助手输出初始化信息与浓度数据LED 指示灯 1s 闪烁一次表征采样正常室内环境 eCO₂稳定 400‑450ppm对着传感器呼气数值上升移开后回落上电预热阶段过滤无效数据屏幕显示---。实际实验现象LCD 上电出现蓝色背景展示标题 “二氧化碳检测实验” 与 CO₂图标上电初期显示二氧化碳:---等待数秒预热完成正常刷新浓度1 秒更新一次。串口助手波特率 115200可以正常打印日志与 ppm 数值。二氧化碳检测实验 ------------------------------ 开始本实验 ** 二氧化碳传感器初始化 ** 读取二氧化碳传感器数据 ** 二氧化碳浓度:421 ppmLED1 严格跟随采样周期每秒亮灭翻转。室内空气读数稳定在 410‑440ppm向传感器呼气读数上升至 700~900ppm停止呼气数值缓慢下降。⚠️实际结果与预期偏差分析预热时间比预想更长预期上电立刻输出有效值实际需要 5‑10s 才跳出---。原因SGP30 内部传感单元需要加热达到工作状态属于硬件固有特性不是程序 bug。测量数值存在小幅跳动不是固定不变预期得到一个恒定数值实际室内读数在小范围内来回波动。原因eCO₂为算法换算等效值本身带有测量噪声环境空气微小气流扰动本项目未添加软件滤波算法。呼气之后浓度回落速度慢预期移开之后读数快速恢复实际需要十几秒缓慢回归基线。原因传感器表面会短暂留存呼出气体气体扩散需要时间芯片内部自带平滑滤波算法抑制数值剧烈跳变。✨综合评价全部功能达到设计预期上述偏差均来自传感器硬件与内部算法不属于代码故障。五、常见问题全解踩坑记录问题 1LCD 一直显示二氧化碳:---读不到有效数据排查方向供电错误SGP30 必须 3.3V接 5V 会直接损坏I2C 引脚接错确认 PB13 (SCL)、PB14 (SDA) 接线检查虚接SYSCLOCK宏和实际系统时钟不匹配软件 I2C 延时错乱刚上电传感器还处于预热阶段等待一段时间观察。问题 2LCD 屏幕花屏、乱码看不到文字SPI 分频系数、时钟相位 CPHA 配置错误SPI 引脚接触不良核对spi_open()传入的模式参数。问题 3串口完全没有打印输出确认 USART2 硬件接线串口助手波特率设置 115200确认代码执行了uart_open(uart2, 115200)。问题 4采集的 CO₂数值乱跳数据完全异常重点检查delay_ms(180)这行代码不能删除、不能缩短测量指令发出后没有足够等待时间读取全部为无效数据。六、拓展优化方向阈值声光报警设定浓度阈值当 eCO₂1000ppm蜂鸣器鸣叫报警LCD 字体变色用于密闭空间空气质量预警TVOC 同步展示修改显示代码屏幕同时输出 eCO₂与 TVOC 两项参数软件滤波算法增加滑动平均滤波抑制数据跳动读数更加平滑温湿度补偿外接温湿度传感器调用 SGP30 补偿接口降低温湿度带来的测量误差上位机数据记录串口持续上传数据到 PC记录数据绘制浓度‑时间变化曲线鸿蒙 MQTT 上云外接 WiFi 模块移植鸿蒙轻量系统数据上传云平台实现远程查看空气质量低功耗改造STM32 进入休眠模式定时唤醒完成采样适合电池供电便携式设备。七、总结本次项目基于 STM32L4 SGP30 完成空气质量检测使用软件模拟 I2C 完成传感器驱动分层模块化的代码方便后期维护扩展。开发过程中有几个关键点一定要注意SGP30 测量之后必须等待 180ms、传感器存在上电预热、传感器只支持 3.3V 供电、软件 I2C 对延时参数非常敏感。需要分清 SGP30 输出的是等效 CO₂和工业级真实 CO₂传感器有区别更适合教学实验、室内空气质量趋势判断。CSDN 标签#STM32#SGP30#软件I2C#嵌入式#物联网#HAL库
上一篇/下一篇内容由系统自动关联
返回资讯列表 →