目录
一、介绍
二、传感器原理
1.工作原理介绍
2.串口数据流格式
三、程序设计
main.c文件
usart3.h文件
usart3.c文件
四、实验效果
五、资料获取
项目分享
一、介绍
JW01-CO2检测模块是一种用于检测空气中二氧化碳浓度的传感器模块。它可以广泛应用于室内空气质量检测、智能家居、温室气体监测等领域。模块采用非分散红外(NDIR)技术进行测量,可以测量空气中的CO2浓度范围从350到2000ppm,具有高精度和快速响应的特点。模块采用串口通信方式,可以与单片机或其他设备进行通信。
以下是JW01二氧化碳传感器的参数:
型号 | JW01-CO2-V2.2 |
工作电压 | 5.0±0.2VDC |
工作电流 | ≤80mA |
量程 | 350-2000PPM |
工作温度 | -10~40℃ |
探测气体 | 二氧化碳 |
预热时间 | 60s |
哔哩哔哩视频链接:
JW01二氧化碳传感器(串行通信 STM32)
(资料分享见文末)
二、传感器原理
1.工作原理介绍
特别说明:
本模块是用TVOC类型传感器经过软件换算的二氧化碳模拟数值,对于其它气体不具有抗干扰性,选择使用时,请留意本说明事项。
2.串口数据流格式
B1的内容2Ch是模块定地址。
校验和(B6)=unit_8(B1+B2+B3+B4+B5)
C02气体浓度值(PPM)=(C0z浓度高(B2)*256+C0z浓度低(B3))
数据范例:
例如读到值是2Ch,0lh,90h,03h,0FFh,BFh,则得出如下结果:
校验和:BFh=2Ch+01h+90h+03h+0FFh
C02数值:B2*256+B3=01h*256+90h=400ppm
三、程序设计
1.使用STM32F103C8T6读取JW01二氧化碳传感器采集的数据,通过串口发送至电脑
2.将读取得到信息数据同时在OLED上显示
JW01_A | PB10 |
JW01_B | PB11 |
OLED_SCL | PB1 |
OLED_SDA | PB0 |
串口 | 串口1 |
注意:初次上电使用建议需预热 5-10 分钟以上进行测试
main.c文件
#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "usart3.h"
/*****************辰哥单片机设计******************
STM32
* 项目 : JW01二氧化碳传感器实验
* 版本 : V1.0
* 日期 : 2024.9.14
* MCU : STM32F103C8T6
* 接口 : 参看usart3.h
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
uint16_t co2;
u8 buff[30];
int main(void)
{
SystemInit();//配置系统时钟为72M
delay_init(72);
LED_Init();
LED_On();
USART1_Config();
USART3_Config();
OLED_Init();
printf("Start \n");
delay_ms(1000);
//显示“二氧化碳:”
OLED_ShowChinese(0,0,0,16,1);
OLED_ShowChinese(16,0,1,16,1);
OLED_ShowChinese(32,0,2,16,1);
OLED_ShowChinese(48,0,3,16,1);
OLED_ShowChar(64,0,':',16,1);
while (1)
{
LED_Toggle();
CO2GetData(&co2);
sprintf((char*)buff,"%dppm ",co2);
//
printf("二氧化碳浓度: %dppm\r\n",co2);
OLED_ShowString(50,30,buff,16,1);
delay_ms(500);
}
}
usart3.h文件
#ifndef __USART1_H
#define __USART1_H
#include "stm32f10x.h"
#include <stdio.h>
void USART1_Config(void);
int fputc(int ch, FILE *f);
void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...);
#endif /* __USART1_H */
usart3.c文件
#include "usart3.h"
/*****************辰哥单片机设计******************
STM32
* 项目 : JW01二氧化碳传感器实验
* 版本 : V1.0
* 日期 : 2024.9.14
* MCU : STM32F103C8T6
* 接口 : 串口3
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
uint8_t Usart3_RxPacket[6]; //定义接收数据包数组
uint8_t Usart3_RxFlag; //定义接收数据包标志位
void USART3_Config(void){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能USART3,GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB时钟
//USART3_TX GPIOB.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.10
//USART3_RX GPIOB.11初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.11
//Usart3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; //子优先级4
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = 9600;//串口波特率
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(USART3, &USART_InitStructure); //初始化串口3
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART3, ENABLE); //使能串口3
}
void USART3_IRQHandler(void) //串口3中断服务程序
{
uint8_t Res;
static uint8_t RxState = 0; //当前状态机状态
static uint8_t pRxPacket = 0; //当前接收数据位置
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART3); //读取接收到的数据
switch (RxState)
{
case 0:
if (Res == 0x2C)
{
Usart3_RxPacket[pRxPacket] = Res; //将数据存入数组
pRxPacket++;
RxState = 1;
}
else
{
pRxPacket = 0;
RxState = 0;
}
break;
case 1:
Usart3_RxPacket[pRxPacket] = Res; //将数据存入数组
pRxPacket++;
if(pRxPacket >= 6)
{
pRxPacket = 0;
RxState = 2;
}
break;
case 2:
if (Usart3_RxPacket[5] == (uint8_t)(Usart3_RxPacket[0] + Usart3_RxPacket[1] //验证接收到的数据是否正确
+ Usart3_RxPacket[2] + Usart3_RxPacket[3] + Usart3_RxPacket[4]))
{
RxState = 0;
pRxPacket = 0;
Usart3_RxFlag = 1; //接收数据包标志位置1,成功接收一个数据包
}
else
{
pRxPacket = 0;
RxState = 0;
}
break;
}
USART_ClearITPendingBit(USART3, USART_IT_RXNE); //清除标志位
}
}
void CO2GetData(uint16_t *data)
{
if (Usart3_RxFlag == 1)
{
Usart3_RxFlag = 0;
*data = Usart3_RxPacket[1] * 256 + Usart3_RxPacket[2];
}
}