【STM32外设系列】JW01三合一空气质量检测模块

🎀 文章作者:二土电子

🌸 关注公众号获取更多资料!

🐸 期待大家一起学习交流!


文章目录

  • 一、JW01模块简介
  • 二、数据格式介绍
  • 三、程序设计
    • 3.1 串口初始化
    • 3.2 串口接收中断服务函数
    • 3.3 数据解析函数
  • 四、其他

一、JW01模块简介

  首先我们看一下JW01的样子

JW01
  值得注意的是,本文介绍的是三合一空气质量检测模块,能够检测空气中有机气态物质的浓度,同时也能检测甲醛和二氧化碳的浓度,该模块通过串口输出气体浓度信息,使用起来还是比较简单的。

  下面简单看一下它的四个引脚分别是什么功能

引脚功能
+5电源正极
GND电源负极
ARXD
BTXD

  需要注意的是,使用该模块时必须先等待模块预热大概60s之后才能输出正确的气体浓度信息。

二、数据格式介绍

  该模块会通过串口输出TVOC、CH2O和CO2的浓度,有自己的数据格式。该模块一次会输出9个字节的数据,9个字节分别是如下含义

字节含义
Byte0模块地址
Byte1模块地址
Byte2TVOC高
Byte3TVOC低
Byte4CH2O高
Byte5CH2O低
Byte6CO2高
Byte7CO2低
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.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;   // PA.9GPIO_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;   // PA10GPIO_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 ;   // 抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;   // 子优先级3NVIC_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);   // 初始化串口1USART_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;   // 先读SRUSART1->DR;   // 再读DRgReceEndFlag = 1;   // 接收完成标志置1 } 
}

3.3 数据解析函数

  数据接收函数设计如下

/**==============================================================================*函数名称: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模块可能长得一样,但是只能检测一种气体浓度,此时我们需要将数据解析函数替换成下面的函数,实际就是在一条数据中少了其他两种气体的浓度信息,其他都一样。

/**==============================================================================*函数名称: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;   // 清零接收计数变量}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/205986.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sublime Text 3运行 Python文件出现中文打印乱码的解决方式

很多小伙伴在下载安装好sublime这个编辑器后发现&#xff0c;它虽然能够用来打开python脚本和创建文件编写代码&#xff0c;但是却不能够来运行python代码和程序。所以下面这一篇文章就是会来分享一下&#xff0c;sublime编辑器无法运行python的解决方法&#xff0c;感兴趣的话…

数据库数据恢复—MongoDB数据库文件拷贝出现错误的数据恢复案例

MongoDB数据库数据恢复环境&#xff1a; 一台Windows Server操作系统的虚拟机&#xff0c;虚拟机上部署有MongoDB数据库。 MongoDB数据库故障&检测&#xff1a; 在未关闭MongoDB服务的情况下&#xff0c;工作人员将MongoDB数据库文件拷贝到其他分区&#xff0c;然后将原数…

谷歌Freshness新鲜度算法:如何利用它提升网站排名?

今天我们就来深入了解下Google Freshness算法核心&#xff0c;结合案例研究和实用技巧&#xff0c;为我们自己的网站优化提供一些思路。 Google新鲜度算法和QDF Google的新鲜度算法和查询需求的新鲜度&#xff08;Query Deserves Freshness, QDF&#xff09;模型是为了改善特…

DLL文件的使用

DLL文件就是动态库文件&#xff0c;搞个例子就懂了&#xff0c;搞两个工程&#xff0c;一个工程生成DLL&#xff0c;一个工程调用DLL。 生成DLL工程 打开Visual Studio 2019&#xff0c;版本高了可能不行&#xff0c;创建新项目。 搜索DLL&#xff0c;动态链接库。 给项目起个…

如何用CHAT写励志文章?

问CHAT&#xff1a;写一篇以《过了60岁要积极面对身体疾病的坎儿》为题目&#xff0c;写一篇300字励志文章 CHAT回复&#xff1a; 标题&#xff1a;《过了60岁要积极面对身体疾病的坎儿》 人生&#xff0c;有时会像一趟不期而遇的旅程&#xff0c;各自带着乐观或悲观、阳光或…

SPSS系统聚类

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

OpenAI再次与Altman谈判;ChatGPT Voice正式上线

11月22日&#xff0c;金融时报消息&#xff0c;OpenAI迫于超过700名员工联名信的压力&#xff0c;再次启动了与Sam Altman的谈判&#xff0c;希望他回归董事会。 在Sam确定加入微软后&#xff0c;OpenAI超700名员工签署了一封联名信&#xff0c;要求Sam和Greg Brockman&#x…

什么是邮件签名证书?

邮件签名证书是一种证书&#xff0c;可以证明发送者的身份&#xff0c;并提供数据完整性和不可否认性的保障。接下来&#xff0c;我们将详细讨论这种证书的特点和用途。 概念 邮件签名证书是一种特殊类型的数字证书&#xff0c;允许发送者在电子邮件上签名和加密&#xff0c;…

Redis集群主备切换原因排查

背景 线上redis部署的是三主三集群&#xff0c;昨天中午&#xff0c;线上各服务接连告警&#xff0c;提示服务已下线&#xff0c;过一段时间又上线了&#xff08;springboot-admin企业微信服务下线、上线告警&#xff09;&#xff0c;赶紧放下手中外卖排查。 排查 1. 查看各…

原来RocketMQ消息会重复消费是无奈的”Bug“

消息发送异常时重复发送 首先&#xff0c;我们来瞅瞅RocketMQ发送消息和消费消息的基本原理。 如图&#xff0c;简单说一下上图中的概念&#xff1a; Broker&#xff0c;就是RocketMQ的服务端&#xff0c;如上图就有两个服务实例Topic就是一类消息集合的名字Queue就是Topic的…

伦敦银涨1%内银涨多少才能持平

伦敦银的价格走势是全球白银市场的价格指标&#xff0c;世界上其他主要的白银市场的价格走势&#xff0c;都是以它作为标杆并紧密的跟随。如果排除汇率的因素&#xff0c;伦敦银价格上涨百分之一&#xff0c;国内的白银价格理论上也会上涨接近的水平。 但不同市场上的白银价格&…

向上转型 向下转型 重写 多态 ---java

目录 一. 向上转型 1.1 概念 1.2 语法格式 1.3 动态绑定引入 1.4 重写的引入 1.5向上转型的使用方式 方式一: 直接赋值 方式二: 通过传参,进行向上转型(多态引入) 方法三:通过返回值, 进行向上转型 二. 重写 2.1 概念 2.2 重写的格式 2.3 重写的规则 【重写和重…