本文主要记录利用STM32的USART2串口采集CO2传感器数据,并通过USART1串口利用串口调试助手显示CO2数值。
一、实验器材
正点原子STM32MINI开发板,炜盛科技CO2(MH-Z19C)传感器。
二、硬件连接
STM32的USART1(PA9-TX,PA10-RX)通过CH340芯片与电脑连接,USART2的接收端PA3-RX连接MH-Z19C的发送端TX,USART2的发送端PA2-TX连接MH-Z19C的接收端RX。尤其注意你所使用的串口与其他功能不冲突,若冲突会导致串口接收数据错误。
三、CO2传感器控制原理
首先通过STM32主控芯片向Sensor发送读取气体浓度指令:FF 01 86 00 00 00 00 00 79,
传感器接收到指令后返回值为:FF 86 HIGH LOW — — — — 校验和。
USART2中断函数主要负责传感器返回数据的存储与处理。
四、USART2.C程序

#include "sys.h"
#include "usart.h"
//
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                 //ucos 使用
#endif//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{ int handle; }; FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{ x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{      while(((USART1->SR&0X40)==0)|((USART2->SR&0X40)==0));//循环发送,直到发送完毕   USART1->DR = (u8) ch;  USART2->DR = (u8) ch;        return ch;
}
#endif #if EN_USART1_RX| EN_USART2_RX|EN_UART5_RX  //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0,   接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记
u16 PM25;
u16 CO2;void uart_init(u32 bound)   //初始化串口1和串口2,函数的参数是波特率
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;//串口1设置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟//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_Cmd(USART1, ENABLE);                    //使能串口1 串口2设置--用于USART2采集炜盛PM2.5(ZH03B)传感器
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);   //使能USART2,
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能GPIOA时钟// //USART2_TX   GPIOA.2
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   //复用推挽输出
//  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2//    //USART2_RX     GPIOA.3初始化
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA.3
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
//  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3  //  //Usart2 NVIC 配置
//  NVIC_InitStructure.NVIC_IRQChannel = USART2_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(USART2, &USART_InitStructure); //初始化串口2
//  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
//  USART_Cmd(USART2, ENABLE);                    //使能串口2 //串口2设置--用于USART2采集炜盛MH-Z19C二氧化碳传感器(我用的正点原子STM32MINI开发板,其他串口被占用)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);   //使能USART2,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能GPIOA时钟//USART2_TX   GPIOA.2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2//USART2_RX     GPIOA.3初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA.3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3  //Usart2 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART2_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(USART2, &USART_InitStructure); //初始化串口2USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART2, ENABLE);                    //使能串口2 } void USART1_IRQHandler(void)   //串口1中断服务程序{u8 Res;
#if SYSTEM_SUPPORT_OS       //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntEnter();
#endifif(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾){Res =USART_ReceiveData(USART1); //读取接收到的数据if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始else USART_RX_STA|=0x8000;  //接收完成了 }else //还没收到0X0D{   if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收   }      }}          }
#if SYSTEM_SUPPORT_OS   //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntExit();
#endif
}//该段代码作用是采集并处理炜盛PM2.5(ZH03B)传感器数据//void USART2_IRQHandler(void)                    //串口2中断服务程序
//    {//    u8 Res;
//
//#if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
//  OSIntEnter();
//#endif
//    static char start=0;
//    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断
//        {//            Res =USART_ReceiveData(USART2); //读取接收到的数据
//            //USART_SendData(USART1,Res);
//            if(Res == 0x42) //如果接收的第一位数据是0X42(这个是查看传感器的手册得知的)
//            {//                USART_RX_STA = 0;     //让数组索引值从0开始
//                start = 1;  //这个变量是来确定第二位是否接收到了0X4D(这个也是查看传感器的手册得知的)
//            }//            if(start == 1)
//            {//                USART_RX_BUF[USART_RX_STA] = Res ; //把接收到的数据存到数组里面
//                USART_RX_STA++;
//                if(USART_RX_STA >= 24 && (USART_RX_BUF[1]==0x4d))
//                    {//                        //USART_SendData(USART1,USART_RX_BUF[12]*256+USART_RX_BUF[13]);
//                      PM25=USART_RX_BUF[12]*256+USART_RX_BUF[13];
//                        printf("PM2.5:%d\n",PM25);
//                        start  = 0;
//                        USART_RX_STA=0;//重新开始接收
//                        USART_RX_BUF[0] = 0;
//                    }
//                }
//        }
//
//#if SYSTEM_SUPPORT_OS     //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
//  OSIntExit();
//#endif
//      //  } //该段代码作用是采集并处理炜盛MH-Z19C二氧化碳传感器数据void USART2_IRQHandler(void)                    //串口2中断服务程序{u8 Res;#if SYSTEM_SUPPORT_OS      //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntEnter();
#endifstatic char start=0;if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断{Res =USART_ReceiveData(USART2); //读取接收到的数据//USART_SendData(USART1,Res);if(Res == 0xFF) //如果接收的第一位数据是0XFF(这个是查看传感器的手册得知的){USART_RX_STA = 0;     //让数组索引值从0开始start = 1;  //这个变量是来确定第二位是否接收到了0X86(这个也是查看传感器的手册得知的)}if(start == 1){USART_RX_BUF[USART_RX_STA] = Res ; //把接收到的数据存到数组里面USART_RX_STA++;if(USART_RX_STA >= 9 && (USART_RX_BUF[1]==0x86)){//USART_SendData(USART1,USART_RX_BUF[12]*256+USART_RX_BUF[13]);CO2=USART_RX_BUF[2]*256+USART_RX_BUF[3];printf("CO2:%dppm\n",CO2);start  = 0;USART_RX_STA=0;//重新开始接收   USART_RX_BUF[0] = 0;}}                   }#if SYSTEM_SUPPORT_OS    //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntExit();
#endif} #endif   五 USART2.h程序#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h" #define USART_REC_LEN            200     //定义最大接收字节数 200
#define EN_USART1_RX            1       //使能(1)/禁止(0)串口1接收
#define EN_USART2_RX            1       //使能(1)/禁止(0)串口2接收extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA; //接收状态标记   //如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);
#endif六 CO2.c程序```c
#include "CO2.h"
//发送读取指令
//const u16  CO2_SPAN_SET[9]={0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0x8F};//此处为设置CO2量程,参考MH-Z19B数据手册,而MH-Z19C手册里并没有设置量程的指令,该处代码慎用。
const u16  CO2_WORK_CMD[9]={0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};//void CO2_SPAN(void)
//{//  int i;
//  for(i = 0; i < 9; i++)
//   {
//          USART_ClearFlag(USART2,USART_FLAG_TC);
//          USART_SendData(USART2,CO2_SPAN_SET[i]);
//          while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
//   }
//
//}
void CO2_WORK(void)
{int i;for(i = 0; i < 9; i++) { USART_ClearFlag(USART2,USART_FLAG_TC);USART_SendData(USART2,CO2_WORK_CMD[i]);  while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);  } }七、CO2.h程序、```c
#ifndef __CO2_H
#define __CO2_H#include "stdio.h"
#include "sys.h"
#include "usart.h"//extern void CO2_SPAN(void);
extern void CO2_WORK(void);#endif八、main.c程序(功能:当检测到CO2>1500ppm时,LED1点亮,否则LED1熄灭,LED0只是个闪烁灯而已)```c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "stdio.h"
#include "CO2.h"
extern u16 CO2;
int main(void){ delay_init();            //延时函数初始化  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2     uart_init(9600);       //串口初始化为9600LED_Init();             //初始化与LED连接的硬件接口while(1){//      CO2_SPAN();CO2_WORK();if(CO2>1500){LED1=0;}else{LED1=1;}LED0=!LED0;delay_ms(250); }
}
九、实验结果![在这里插入图片描述](https://img-blog.csdnimg.cn/20201222235531335.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUzNjM3NTg2,size_16,color_FFFFFF,t_70#pic_center)十、楼主是一名单片机爱好者,欢迎大家留言交流。走钢丝的猴书于2020.12.22晚23:42

基于STM32采集CO2(MH-Z19C)传感器数据相关推荐

  1. 基于stm32实现片内flash读取数据及音乐播放(不完整)

    基于stm32实现片内flash读取数据及音乐播放(不完整) FLASN 一.片内flash 三.flash数据读取 1.工程建立 2.修改代码 3.烧录运行与结果 四.flash实现提示音播放 1. ...

  2. 基于STM32的无刷直流电机无传感器调速系统代码和原理图

    说明:有代码和原理图 项目代码很全(是两个大项目,两个项目的区别是一个有传感器一个没有,其余实现功能都相同) 无感方波有 有传感器(霍尔元件)的编程也有 1: 基于STM32的无刷直流电机无传感器调速 ...

  3. 基于STM32采集PM2.5(ZH03B)传感器数据实验

    本文主要记录利用STM32的USART2串口采集PM2.5传感器数据,并通过USART1串口利用串口调试助手显示PM2.5数值. 一.实验器材 正点原子STM32MINI开发板,炜盛科技PM2.5(Z ...

  4. 如何使用STM32和BLE收集SHT85传感器数据?

    简述 这是一个简单的BLE项目.现在,它常常被设计用于智能家居的中. 下面文章展示了如何使用 javascript 获取连接到 STM32 Nucleo-144 的SHT85湿度温度传感器数据. 我们 ...

  5. matlab获取手机传感器,分享采集Android内置传感器数据到MATLAB的方法

    本方法能够实现安卓手机内置的加速度传感器.陀螺仪.磁场数据.角速度传感器及GPS数据采集到MATLAB. 1.硬件准备:安卓手机,电脑,且在同一局域网中: 2.软件准备:安卓手机安装MATLABmob ...

  6. 基于物联网网关的水电表传感器数据采集系统

    水表.电表以及各种不同类型的传感器在工业生产中十分常见,成为物联网远程监控的重点.需要将用水量.用电量.温湿度.压力等数据采集上来,集中监控生产环境信息并产生预警通知,有助于保障安全稳定的生产环境,能 ...

  7. 【AllJoyn专题】基于AllJoyn和Yeelink的传感器数据上传与指令下行的研究

    接触高通物联网框架AllJoyn不太久,但确是被深深地吸引了.在我看来,促进我深入学习的原因有三点:一.AllJoyn开源,对开源的软硬件总会有种莫名的喜爱,虽然或许不会都深入下去:二.顺应潮流,物联 ...

  8. STM32读取SHT3x系列温湿度传感器,标准库和HAL库

    STM32读取SHT3x系列(SHT30.SHT31.SHT35)温湿度传感器的数据并显示在0.96寸OLED屏上. 我下面提供两份代码,一份是标准库使用硬件I2C的,另一份是HAL库使用软件模拟II ...

  9. 85、基于STM32单片机烟雾温度报警器设计火灾防火检测可燃气体监测系统设计

    毕设帮助.开题指导.技术解答(有偿)见文末. 目录 摘要 一.硬件方案 二.设计功能 三.实物图 四.原理图 五.程序源码 六.资料包括 摘要 本设计采用使用STM32F103作为控制器件,MQ-2型 ...

最新文章

  1. 捅破窗户纸:如何从过程到对象—For金色的海洋以及所有为面向对象而困惑的Tx...
  2. 2021年春季学期-信号与系统-第八次作业参考答案-第八小题
  3. js 显示当前时间(年月日时分秒)——getYear()与getFullYear()
  4. 简单理解bash和常规操作
  5. 无码系列-3-代码架构约束
  6. maven编译报程序包不存在_宝马730i空调不制冷,报冷却剂压缩机当前存在故障
  7. BZOJ2049[SDOI2008] 洞穴勘测
  8. Spring Cloud Alibaba之服务治理Nacos
  9. ESN(Electronic Serial Number,电子序列号)简介
  10. 【联机对战】一张图看懂联机对战服务
  11. 操作系统实验ucore_lab5实验报告
  12. nginx之allow、deny
  13. 当数据中心碰上云计算
  14. Java知识点--类变量
  15. cmake学习笔记 二
  16. nacos 配置Sentinel 熔断规则
  17. ReactNative学习笔记(七)——ref属性的用法和可点击组件
  18. 嘉兴经开区第四届创新创业大赛总决赛成功举办
  19. 记录ORBSLAM2稠密点云在线搭建过程(虽然我的目标是二维,方便之后导航用)
  20. Java面向对象三大特性(封装、继承、多态)

热门文章

  1. 本地滑块识别DLL/本地通用验证码识别DLL/文字点选/图标点选/本地识别DLL
  2. python使用mysql实例教程_Python操作Mysql实例代码教程(查询手册)
  3. 微信小程序 从某个页面直接返回首页
  4. 【苦练基本功】代码整洁之道 pt3(第7章-第9章)
  5. Altium Designer 18中的Violations Associated with Documents
  6. 送你一个励志故事—掌握这些你也可能拿到腾讯offer
  7. SQL PLUS命令使用大全(转,特有用)
  8. flutter 人脸识别_使用flutter和tensorflow lite进行人脸识别认证
  9. day07面向对象复习+课后练习
  10. JFFS2文件系统挂载过程(5)