前言本实验用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/13.校验位可选4.停止位拉高电平表示「这一个字节发完了」串口通讯原则1.TX 接 RXRX 接 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. 引脚配置显式初始化PA03 GPIO_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 i0; i100000; 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检测通过软件运算模拟等效数值仅供参考。
CW32L012的六合一空气质量检测案例分享
前言本实验用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/13.校验位可选4.停止位拉高电平表示「这一个字节发完了」串口通讯原则1.TX 接 RXRX 接 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. 引脚配置显式初始化PA03 GPIO_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 i0; i100000; 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检测通过软件运算模拟等效数值仅供参考。