🎀 文章作者:二土电子
🌸 关注公众号获取更多资料!
🐸 期待大家一起学习交流!
一、JW01模块简介
首先我们看一下JW01的样子
值得注意的是,本文介绍的是三合一空气质量检测模块,能够检测空气中有机气态物质的浓度,同时也能检测甲醛和二氧化碳的浓度,该模块通过串口输出气体浓度信息,使用起来还是比较简单的。
下面简单看一下它的四个引脚分别是什么功能
引脚 | 功能 |
---|---|
+5 | 电源正极 |
GND | 电源负极 |
A | RXD |
B | TXD |
需要注意的是,使用该模块时必须先等待模块预热大概60s之后才能输出正确的气体浓度信息。
二、数据格式介绍
该模块会通过串口输出TVOC、CH2O和CO2的浓度,有自己的数据格式。该模块一次会输出9个字节的数据,9个字节分别是如下含义
字节 | 含义 |
---|---|
Byte0 | 模块地址 |
Byte1 | 模块地址 |
Byte2 | TVOC高 |
Byte3 | TVOC低 |
Byte4 | CH2O高 |
Byte5 | CH2O低 |
Byte6 | CO2高 |
Byte7 | CO2低 |
Byte8 | 校验和 |
校验和Byte8 = (u8)(前面所有字节的和),一定注意要有一个强制类型转换。其次还需要注意的是,该模块的波特率为9600。
这里的两个模块地址固定为0x2C和0xE4,计算浓度的方法为 气体浓度 = ((高位) * 256 + 低位) * 0.001 m g / m 3 mg/m^3 mg/m3。
三、程序设计
3.1 串口初始化
下面给出一个串口初始化程序,对于串口相关内容的详细介绍可到STM32速成笔记专栏查看
/*
*==============================================================================
*函数名称:uart_init
*函数功能:初始化USART1
*输入参数:bound:波特率
*返回值:无
*备 注:可以修改成输入初始化哪个USART
*==============================================================================
*/
void uart_init(u32 bound)
{
// 相关结构体定义
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能USART1,GPIOA时钟
RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.9
// USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.10
// Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; // 抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器
// USART 初始化设置
USART_InitStructure.USART_BaudRate = bound; // 串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验位
// 无硬件数据流控制
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式
USART_Init(USART1, &USART_InitStructure); // 初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收中断
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 使能空闲中断
USART_Cmd(USART1, ENABLE); // 使能串口1
}
3.2 串口接收中断服务函数
/*
*==============================================================================
*函数名称:USART1_IRQHandler
*函数功能:USART1中断服务函数
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
u32 gReceCount = 0; // 接收计数变量
u32 gClearCount = 0; // 清空接收数组计数变量
u8 gReceFifo[1500]; // 接收数组
u8 gReceEndFlag = 0; // 接收完成标志位
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收到一个字节
{
gReceFifo[gReceCount++] = USART_ReceiveData(USART1);
}
else if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET) //接收到一帧数据
{
USART1->SR; // 先读SR
USART1->DR; // 再读DR
gReceEndFlag = 1; // 接收完成标志置1
}
}
3.3 数据解析函数
数据接收函数设计如下文章来源:https://www.toymoban.com/news/detail-765094.html
/*
*==============================================================================
*函数名称:Uart_Rece_Pares
*函数功能:解析串口接收内容
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void Uart_Rece_Pares(void) // 串口接收内容解析函数
{
float tvoc = 0; // TVOC浓度
float ch2o = 0; // CH2O浓度
u16 co2 = 0; // CO2浓度
if (gReceEndFlag == 1) // 如果接收完成
{
// 解析接收内容
// 需要注意的是必须加一个强制类型转换
if ((u8)(gReceFifo[0] + gReceFifo[1] + gReceFifo[2] + gReceFifo[3] + gReceFifo[4] + gReceFifo[5]
+ gReceFifo[6] + gReceFifo[7]) == gReceFifo[8])
{
printf ("Data Right!\r\n");
// 数据解析
// TV0C浓度(单位是毫克每立方米)
tvoc = (float)((gReceFifo[2] * 256) + gReceFifo[3]) * 0.001;
// CH2O浓度(单位是毫克每立方米)
ch2o = (float)(gReceFifo[4] * 256 + gReceFifo[5]) * 0.001;
// CO2浓度(单位是PPM)
co2 = (u16)(gReceFifo[6] * 256 + gReceFifo[7]);
// 输出计算结果
printf ("\r\n");
printf ("TVOC density: %.3f mg/m^3\r\n",tvoc);
printf ("CH2O density: %.3f mg/m^3\r\n",ch2o);
printf ("CO2 density: %d PPM\r\n",co2);
}
else
{
printf ("Data Error!\r\n");
}
// 清空接收数组
for (gClearCount = 0;gClearCount < gReceCount;gClearCount ++)
{
gReceFifo[gClearCount] = ' ';
}
gReceEndFlag = 0; // 清除接收完成标志位
gReceCount = 0; // 清零接收计数变量
}
}
四、其他
有的同学买到的JW01模块可能长得一样,但是只能检测一种气体浓度,此时我们需要将数据解析函数替换成下面的函数,实际就是在一条数据中少了其他两种气体的浓度信息,其他都一样。文章来源地址https://www.toymoban.com/news/detail-765094.html
/*
*==============================================================================
*函数名称:Uart_Rece_Pares
*函数功能:解析串口接收内容
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void Uart_Rece_Pares(void) // 串口接收内容解析函数
{
float tvoc = 0; // TVOC浓度
float ch2o = 0; // CH2O浓度
u16 co2 = 0; // CO2浓度
if (gReceEndFlag == 1) // 如果接收完成
{
// 解析接收内容
// 需要注意的是必须加一个强制类型转换
if ((u8)(gReceFifo[0] + gReceFifo[1] + gReceFifo[2] + gReceFifo[3] + gReceFifo[4]) == gReceFifo[5])
{
// printf ("\r\n");
printf ("Data Right!\r\n");
// 数据解析
// TV0C浓度(单位是毫克每立方米)
tvoc = (float)((gReceFifo[1] * 256) + gReceFifo[2]) * 0.01;
// 输出计算结果
printf ("\r\n");
printf ("TVOC density: %.3f mg/m^3\r\n",tvoc);
}
else
{
// printf ("\r\n");
printf ("Data Error!\r\n");
}
// 清空接收数组
for (gClearCount = 0;gClearCount < gReceCount;gClearCount ++)
{
gReceFifo[gClearCount] = ' ';
}
gReceEndFlag = 0; // 清除接收完成标志位
gReceCount = 0; // 清零接收计数变量
}
}
到了这里,关于【STM32外设系列】JW01三合一空气质量检测模块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!