前言:本实验用CW32L012作为主控,SC-4M01A为空气检测传感器实现测量六种空气值。
一、SC-4M01A模块简介:
SC-4M01A是一款六合一的空气质量检测模块。它具有:零点标定、六合一数据输出,高灵敏度、长寿命、低功耗,自动校准、自带温湿度补偿 ,UART串口信号输出,应用简单,可根据用户要求定制尺寸及输出信号等特点。他的应用领域也非常广泛可覆盖:车载及家用空气净化器,多合一空气质量监(检)测仪,新风换气系统及自动换气扇,空调自动换气及集成吊顶控制器 ,便携式多功能空气质量测试仪等领域。他的实物如下图。
该模块使用串口通讯,简单可实现性强。下附接口定义图和通讯协议图以及规格参数图。
二、串口通讯协议介绍:
什么是串口:串口就是两根线:TX 发送,RX 接收再加一根 GND 共地特点:一根线按位依次发数据,不是并行一次性传 8 位,是一位一位排队传,所以叫串行通信。
串口协议核心4个关键参数:
1.波特率:就是传输速度,单位 bps。常见:9600、115200意思:每秒发多少位。两边波特率不一样,直接乱码。
2.数据位:一般固定 8 位就是一次传输有效数据是 8bit = 1 字节。
3.停止位:发完一个字节,停顿多久告诉对方 “我发完了”。常用:1 位停止位
4.校验位:无校验(最常用),奇校验,偶校验一般项目都用 无校验。
串口一帧数据长什么样:
空闲时:电平一直高。发数据流程:
1.起始位:拉低电平,告诉对方「我要发数据了」
2.8 位数据位:从最低位开始,一位一位发 0/1
3.校验位(可选)
4.停止位:拉高电平,表示「这一个字节发完了」
串口通讯原则:
1.TX 接 RX,RX 接 TX 交叉接线
2.必须共 GND,不然电平参考不一样,乱码收不到
3.两边波特率、数据位、停止位、校验位 必须完全相同
4.串口是异步通信:没有时钟线,不靠时钟同步,全靠约定好的波特率定时采样
下附通讯协议及数据说明:
上面说完通讯原理及数据说明情况后,下面附具体Keil中的代码例程:
三、软件讲解:
#include "cw32l012.h"#include "cw32l012_sysctrl.h"#include "cw32l012_gpio.h"#include "cw32l012_uart.h"#include "OLED.h"#include <stdio.h>// 变量定义uint8_t RxStack[14]; // 模块一帧是14字节uint8_t StackPtr = 0;uint16_t TVOC_Val = 0, HCHO_Val = 0, CO2_Val = 0;float Temp_Val = 0.0f, Hum_Val = 0.0f;uint8_t AQI_Val = 0; // AQI 等级 (0~255)/**@brief 校验和计算:B0~B12累加,取低8位*/uint8_t Get_CheckSum(uint8_t *buf) {uint32_t sum = 0;for (int i = 0; i < 13; i++) {sum += buf[i];}return (uint8_t)(sum & 0xFF);}/**@brief 串口初始化:使用PA03作为接收*/void UART_Init_Sensor(void) {// 1. 时钟开启__SYSCTRL_GPIOA_CLK_ENABLE();__SYSCTRL_UART1_CLK_ENABLE();// 2. 引脚配置:显式初始化PA03GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pins = GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_Init(CW_GPIOA, &GPIO_InitStruct);PA03_AFx_UART1RXD();// 3. UART参数配置 (按24MHz主频配置,如果数值乱跳请改为8000000)UART_InitTypeDef UART_InitStruct = {0};UART_InitStruct.UART_BaudRate = 9600;UART_InitStruct.UART_Source = UART_Source_PCLK;UART_InitStruct.UART_UclkFreq = 24000000;UART_InitStruct.UART_Mode = UART_Mode_Rx;UART_Init(CW_UART1, &UART_InitStruct);// 4. 中断具体配置UART_ITConfig(CW_UART1, UART_IT_RC, ENABLE);UART_ClearITPendingBit(CW_UART1, UART_IT_RC);NVIC_SetPriority(UART1_IRQn, 0);NVIC_EnableIRQ(UART1_IRQn);}int main(void) {// 基础初始化SystemInit();// 【最关键】开启总中断开关__enable_irq();UART_Init_Sensor();OLED_Init();OLED_Clear();// 初始显示,确认OLED没死机OLED_Printf(0, 0, OLED_6X8, "System Ready...");OLED_Update();while (1) {// 在OLED上实时显示数值OLED_Printf(0, 0, OLED_6X8, "CO2: %d ppm ", CO2_Val);OLED_Printf(0, 10, OLED_6X8, "TVOC: %d ppb ", TVOC_Val);OLED_Printf(0, 20, OLED_6X8, "HCHO: %d ug/m3 ", HCHO_Val);OLED_Printf(0, 30, OLED_6X8, "Temp: %.1f C ", Temp_Val);OLED_Printf(0, 40, OLED_6X8, "AQI: %d ", AQI_Val);OLED_Printf(0, 50, OLED_6X8, "Hum: %.1f %% ", Hum_Val);OLED_Update();// 适当延时,减少刷屏频率for(volatile int i=0; i<100000; i++);}}/**@brief 串口中断服务程序 - 尝试两种可能的函数名如果你的启动文件里是 UART1_IRQHandler,就用现在的。如果数值不跳 8888,请尝试把名字改为 UART1_UART2_IRQHandler*/void UART1_IRQHandler(void) {if (UART_GetITStatus(CW_UART1, UART_IT_RC) != RESET) {if(CO2_Val == 0) CO2_Val = 8888; // 保持 8888 标记,确认中断活着uint8_t data = UART_ReceiveData(CW_UART1);//收够 14 个就解析一次RxStack[StackPtr++] = data;if (StackPtr >= 14) {TVOC_Val = (RxStack[3] << 8) | RxStack[2];HCHO_Val = (RxStack[5] << 8) | RxStack[4];CO2_Val = (RxStack[7] << 8) | RxStack[6];Temp_Val = RxStack[10] + (RxStack[9] / 10.0f);AQI_Val = RxStack[8];Hum_Val = RxStack[12] + (RxStack[11] / 10.0f);StackPtr = 0;}UART_ClearITPendingBit(CW_UART1, UART_IT_RC);}}void assert_failed(uint8_t *file, uint32_t line) { while(1); }
四、实验现象:
五、最后总结注意事项:
初次上电使用建议需预热5-10分钟以上进行测试。请避免震动和跌落,以及严禁液体流入传感器内部。请勿将该模块应用于涉及人身安全的系统中。请勿将该模块长时间置于高浓度有机气体中。请勿将模块安装在强空气对流环境下使用。CO2及HCHO数值为TVOC检测通过软件运算模拟等效数值,仅供参考。
扫码加入QQ群3群| 610403240
188