【STM32F103】JW01-CO2-V2.2二氧化碳检测模块(USART)

JW01

网上买的JW01模块,二十六块,买贵了。看到最便宜有九块钱的(运费十块),心疼。。。避雷了兄弟们,看到二十六块的JW01别买。

这个模块它是1秒钟检测一次CO2然后通过串口来传输结果,并且还自带了数据检测,感觉还是不错的,这里记录一下。

商家提供的资料我看了,演示视频不能说是保教包会吧也算得上是聊胜于无了。

唯一有用的就是芯片手册了,不过芯片手册这个文件夹里也就几张图片。

还好JW01本身就简单,通过这几张图片我们也能大概知道是怎么使用。

可以知道JW01是通过UART来传输数据的,波特率9600,数据位8位,停止位1位,无校验,就是最普通的设置。

从上图可以知道JW01发送的串口数据流格式,一共是6个字节。

第一个字节是固定的2C,我们后面通过这个来使得获取的数据位对齐。

第二和第三个字节可以通过公式来得到检测到的CO2浓度。

然后第四和第五个字节好像也是固定的,是0x03和0xFF。

最后一个字节是校验位,也就是前五个字节加起来(要转为8位的数据格式,例如uint8_t)等于第六个字节的时候,我们得到的数据才是正确的。

还有一点要注意的就是JW01的输出口(TXD)是5V的(这个和供电的电压有关,如果给3.3V供电的话那么就不需要考虑这些了),而我们的单片机大概率是3.3V,因此要电平转换。

不过很幸运,我们STM32F103的USART1的RXD是可以接收5V电压的,因此不需要转换。

如上图所示,IO口有标注FT的引脚即是可以接受5V电压的。但是我们STM32F103的USART2就不能接受5V电压的,因此我们就使用USART1这样比较省事。

STM32F103通过JW01获取CO2浓度

所以我们只需要把对应的口接到STM32F103的引脚上就行。

因为JW01需要5V供电,因此我将ST-Link的5V接出来供5V电了,经我实测,STM32F103的3.3V似乎也可以带得动JW01,不过预热速度会比5V稍慢一些。

并且我们只需要接收JW01的信息而不需要给它发送数据,因此我们甚至可以不配置STM32F103的TXD,只需要配置RXD即可,不过代码里我还是配置上了(因为用的是之前配置USART的代码)。

接下来的讲解配合我下面的代码食用。

我们首先先正常配置USART,可以参考我之前的文章。

由于我们是需要接收数据,因此需要打开接收数据的中断,中断优先级随便配一个就行。

因为JW01固定发送的是6字节的数据,因此我们使用容量为6个uint8_t的数组来存放数据。

在中断函数里,我们按照接收的顺序去把收到的数据放入数组里,但是要多一个判断,只有当我们准备存放在数值的第一位并且此时接收的数据为0x2C的时候(参考前文的数据包格式),我们才真正接收此数据,否则我们就一直卡在准备接受第一位数据的状态。

JW01的发送速率是一秒发一次。也就是说正常情况下我们数组里的数据是一秒更新一次。

接收之后我们显示检测的数据,CO2的浓度为数组第二个元素乘上256再加上数值第三个元素,单位为ppm。

并且之前也说了,六个字节的最后一个字节是校验位,前五个字节加起来要等于第六个字节,需要注意的是在比较的时候需要将比较结果转换为8个bit的数据,这样才能正确比较。

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

void JW01_Init(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能外设时钟
    
    GPIO_InitTypeDef GPIO_Init_Struct;
    GPIO_Init_Struct.GPIO_Mode=GPIO_Mode_AF_PP;                      //TXD为复用推挽输出
    GPIO_Init_Struct.GPIO_Pin=GPIO_Pin_9;                            //9号为TXD
    GPIO_Init_Struct.GPIO_Speed=GPIO_Speed_50MHz;                    //这个随意
    GPIO_Init(GPIOA,&GPIO_Init_Struct);
    
    GPIO_Init_Struct.GPIO_Mode=GPIO_Mode_IN_FLOATING;                //RXD为浮空输入
    GPIO_Init_Struct.GPIO_Pin=GPIO_Pin_10;                           //10号为RXD
    GPIO_Init(GPIOA,&GPIO_Init_Struct);                              
    
    USART_InitTypeDef Usart_Init_Struct;
    Usart_Init_Struct.USART_BaudRate=9600;                                      //波特率
    Usart_Init_Struct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //无硬件控制流
    Usart_Init_Struct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                   //收发模式
    Usart_Init_Struct.USART_Parity=USART_Parity_No;                             //无校验
    Usart_Init_Struct.USART_StopBits=USART_StopBits_1;                          //停止位1位
    Usart_Init_Struct.USART_WordLength=USART_WordLength_8b;                     //数据位8位
    USART_Init(USART1,&Usart_Init_Struct);
    
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);                                //开启接收中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                             //NVIC中断配置
    NVIC_InitTypeDef nitd;
    nitd.NVIC_IRQChannel=USART1_IRQn;
    nitd.NVIC_IRQChannelCmd=ENABLE;
    nitd.NVIC_IRQChannelPreemptionPriority=2;
    nitd.NVIC_IRQChannelSubPriority=2;
    NVIC_Init(&nitd);
    
    USART_Cmd(USART1,ENABLE);
}

uint8_t CO2_Data[6];                                        //存放接收到的数据包

void USART1_IRQHandler(void){
    static uint8_t index=0;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
        CO2_Data[index]=USART_ReceiveData(USART1);
        if(index==0&&CO2_Data[index]!=0x2C){                //固定数据包的开头
            return;
        }else{
            if(++index>=6) index=0;
        }
        USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);    //清除数据接收标志位
    }
}

int main(void){
    OLED_Init();
    JW01_Init();
    OLED_ShowString(1,1,"Hello World");
    OLED_ShowString(2,1,"CO2 is ");
    while(1){
        if(CO2_Data[5]==(uint8_t)(CO2_Data[0]+CO2_Data[1]+CO2_Data[2]+CO2_Data[3]+CO2_Data[4])){
            OLED_ShowNum(2,8,CO2_Data[1]*256+CO2_Data[2],5);
        }else{
            OLED_ShowString(2,8,"ERROR");
        }
        OLED_ShowHexNum(3,1,CO2_Data[0],2);
        OLED_ShowHexNum(3,4,CO2_Data[1],2);
        OLED_ShowHexNum(3,7,CO2_Data[2],2);
        OLED_ShowHexNum(4,1,CO2_Data[3],2);
        OLED_ShowHexNum(4,4,CO2_Data[4],2);
        OLED_ShowHexNum(4,7,CO2_Data[5],2);
    }
}

效果演示

上面代码涉及的OLED的驱动代码用的是b站江科大自化协的,没有OLED的小伙伴可以使用串口通信打印到电脑的串口助手上,不过只能用USART2了。因为JW01用了USART1。

接线方面的话就是把JW01的TXD接到GPIOA的10号引脚。

然后ST-Link的5V接出来给JW01供电,JW01的GND也和STM32共地(因为供电源一样)。

  • 39
    点赞
  • 163
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
### 回答1: 基于stm32f103的hc-05程序是用于控制蓝牙模块hc-05与stm32f103单片机之间的通信的程序。下面是一个简单的实现步骤: 1. 首先,需要配置stm32f103的串口通信,将其与hc-05的串口进行连接。可以选择一个可用的串口(例如USART1)进行通信,并配置相关的引脚。 2. 在程序中引入相关的头文件,并定义相关的变量,例如: ``` #include "stm32f10x.h" #include "stm32f10x_usart.h" USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; uint8_t Received_data; ``` 3. 初始化串口的参数,例如波特率等: ``` void USART_Configuration(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); } ``` 4. 编写函数来发送和接收数据,例如: ``` void USART_puts(USART_TypeDef* USARTx, uint8_t data){ while(!(USARTx->SR & 0x00000040)); USART_SendData(USARTx, data); } uint8_t USART_gets(USART_TypeDef* USARTx){ while(!(USARTx->SR & 0x00000020)); return USART_ReceiveData(USARTx); } ``` 通过以上步骤,我们可以实现与hc-05的通信。你可以根据需求进一步完善该程序,例如添加中断处理函数进行数据的处理、加入其他功能等。 ### 回答2: 基于STM32F103的HC-05程序用于控制HC-05蓝牙模块,接收和发送数据。以下是一个简单的示例程序: 首先,需要包括必要的头文件和定义一些常量: #include "stm32f10x.h" #include "stm32f10x_usart.h" #define USART_USART1_IRQn USART1_IRQn 然后,需要初始化串口和蓝牙模块: void USART_Configuration(void) { USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置串口引脚为复用功能 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置串口参数 USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); } 接下来,我们可以通过中断接收和发送数据: void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { // 接收数据 uint8_t data = USART_ReceiveData(USART1); // 处理接收到的数据 // ... // 发送回应数据 USART_SendData(USART1, data); } } 最后,我们在主程序中初始化串口,并可以通过蓝牙模块进行数据通信: int main(void) { USART_Configuration(); while (1) { // 发送数据到HC-05 USART_SendData(USART1, 'A'); delay_ms(1000); } } 这是一个基于STM32F103的HC-05程序的简单示例。你可以根据需要进行修改和扩展,以满足你的具体需求。 ### 回答3: HC-05是一款常用的蓝牙模块,它可以与STM32F103单片机配合使用,实现无线通信功能。下面是一个基于STM32F103的HC-05程序的实现步骤。 首先,我们需要在STM32F103上设置UART通信功能。通过配置串口参数,包括波特率、数据位、停止位和校验位等,来与HC-05进行通信。 其次,需要定义相应的变量和数据结构,用于存储接收到的数据或需要发送的数据。可以使用缓冲区或数组来实现数据的存储和处理。 然后,可以使用STM32F103的GPIO引脚配置来控制HC-05模块的工作状态,如连接状态指示灯或蓝牙模块的复位引脚。 接下来,通过读取 UART 接收数据寄存器,可以获取从HC-05模块接收到的数据。可以使用中断或轮询方式,来检测数据是否到达,并将接收到的数据存储到相应的变量中。 在发送数据时,可以通过将数据写入UART发送数据寄存器,将数据发送给HC-05模块。同样可以使用中断或轮询方式,以确保数据成功发送。 最后,还可以添加其他功能,如错误检测、数据处理、响应控制等,以提升程序的健壮性和可用性。 综上所述,基于STM32F103的HC-05程序主要包括UART通信的设置、数据存储与处理、GPIO引脚配置和数据的接收与发送等模块。通过合理的编程实现,可以实现STM32F103与HC-05之间的无线通信功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值