1,查资料,查模块的通信接口(单片机和模块之间采用什么方式通信)硬件接口,驱动方式(串口驱动用串口发送接收PC10,PC11)
只用了三个脚:VCC GND TX,
RX和F没有用
传输数据,本项目中不要用串口3,串口3是留给wifi的,在硬件上已经固定了, 所以其他的任选一个用串口4传输数据,
KQM.c
#include "kqm.h"
#include "string.h"
//自己能写代码并理解
//voc PPM ,甲醛mg/m3, co2PPM
KQM kqm = {0};
//1.IO初始化
//2.外设初始化
//3.中断初始化
void KQM_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure = {0};//定义结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//推挽
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空
GPIO_Init(GPIOC, &GPIO_InitStructure);
//2.外设初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
USART_InitTypeDef USART_InitStructure = {0};
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_Tx | USART_Mode_Rx;
USART_Init(UART4, &USART_InitStructure);
USART_Cmd(UART4, ENABLE);
//3.中断初始化
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;// 0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//0-3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//4,中断源
USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);//开启串口 接收中断
USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);//串口空闲中断
}
//模块是主动传输数据,不需要写数据发送函数,用中断接收数据,所以也不需要写接收函数
//中断服务函数
void UART4_IRQHandler(void)
{
if(USART_GetITStatus(UART4,USART_IT_RXNE) == SET)
{
kqm.rxbuff[kqm.rxlen] = USART_ReceiveData(UART4);
kqm.rxlen++;
USART_ClearITPendingBit(UART4,USART_IT_RXNE);
}
//空闲中断在UART一段时间没有接收到数据时触发,表示接收完成或空闲状态
if(USART_GetITStatus(UART4,USART_IT_IDLE) == SET)
{
uint8_t data = USART_ReceiveData(UART4);//接收数据
//UART4的接收缓冲区已经处理完毕或达到空闲状态
kqm.rxflag=1;
}
}
//解析接收的数据
// 1.判断数据接收完成
// 2.判断数据的正确性(校验)
// 3.开始解析数据
#include "led.h"
#include "stdio.h"
void KQMDataAnaly(void)
{
if(kqm.rxflag == 1)
{
//在预热阶段模块传送所有数据的高位以及低位字节为0xff,当接收到此数据时可视为预热数据,不予处理
//判断是否是预热阶段
if(kqm.rxbuff[1]== 0xff && kqm.rxbuff[2]== 0xff && kqm.rxbuff[3]== 0xff && kqm.rxbuff[4]== 0xff && kqm.rxbuff[5]== 0xff && kqm.rxbuff[6]== 0xff)
{
memset(kqm.rxbuff,0,10);
kqm.rxlen=0;
kqm.rxflag=0;
return ;
}
uint8_t checkval =(uint8_t)(kqm.rxbuff[0]+kqm.rxbuff[1]+kqm.rxbuff[2]+kqm.rxbuff[3]+kqm.rxbuff[4]+kqm.rxbuff[5]+kqm.rxbuff[6]);
if(checkval == kqm.rxbuff[7]) //校验
{
kqm.voc = (kqm.rxbuff[1]<<8|kqm.rxbuff[2])*0.1;//ppm
kqm.hcho = (kqm.rxbuff[3]<<8|kqm.rxbuff[4])*0.01;//mg/m3
kqm.co2 = (kqm.rxbuff[5]<<8|kqm.rxbuff[6])*0.1;//ppm
//例如:rxbuff[1]:0000 0011
// rxbuff[2]: 1011 1001
//rxbuff[1]<<8得到rxbuff[1]:0000 0011 0000 0000
//rxbuff[1]<<8|rxbuff[2]得voc:0000 0011 1011 1001
memset(kqm.rxbuff,0,10);
kqm.rxlen=0;
kqm.rxflag=0;
printf("voc:%.1f,hcho:%.2f,co2:%.1f\r\n",kqm.voc,kqm.hcho,kqm.co2);
}
else//校验失败
{
memset(kqm.rxbuff,0,10);
kqm.rxlen=0;
kqm.rxflag=0;
}
}
}
kQm.h
#ifndef _KQM_H_
#define _KQM_H_
#include "stm32f10x.h"
typedef struct
{
uint8_t rxbuff[10]; //rxbuff[1]一个数占8位
uint8_t rxlen;
uint8_t rxflag;
float voc;
float hcho;
float co2;
}KQM;
extern KQM kqm;
void KQM_Init(void);
void KQMDataAnaly(void);
#endif