KQM6600空气传感器原理图

STM32F103ZET6-KQM6600空气质量传感器_IT

相关知识详细介绍

传感器:

数字型传感器:数字信号

关注:接口(UART,单总线,IIC,SPI...)

单总线比如:DHT11(DOUT接口)

模拟型传感器:模拟信号(电压,电流)

电压:ADC,

如果电压太大就需要硬件电路缩小

如果电压太小,就需要硬件电路放大

电流:(4--10mA)串联高精度的采样电阻,把电流转化成电压,然后再通过ADC采集

各种电平:

TTL   232  485   USB

TTL  232  485本质上都是串口电平,但是电平规范不一样

TTL:单片机的串口,ESP8266,KQM6600这些串口接口一般都是TTL电平

电脑收TTL电平的数据

232:232芯片,将TTL电平转化为232电平

STM32F103ZET6-KQM6600空气质量传感器_IT_02

485电平:TTL通过485芯片,转换成485电平

STM32F103ZET6-KQM6600空气质量传感器_#include_03

USB电平:TTL通过CH340将TTL电平转换成USB电平

获取模块数据手册的途径:

1.       官网

2.       立创商城

3.       淘宝客服要

4.       供应商要

5.       百度

KQM6600简介

看手册关注的点:

(1)供电电压

(2)通信接口(TTL  232  485)

(3)如何获取数据

波特率、输入电压

STM32F103ZET6-KQM6600空气质量传感器_数据_04

数据格式

STM32F103ZET6-KQM6600空气质量传感器_数据_05

预热阶段:设备刚开机,可能测的不准,稳定一段时间之后,才准确(一般采集气体的传感器都是如此)

休眠控制(有低功耗需求时用到)

STM32F103ZET6-KQM6600空气质量传感器_#include_06

KQM6600硬件层

型号与引脚描述

STM32F103ZET6-KQM6600空气质量传感器_#include_07

使用电路连接示意图

STM32F103ZET6-KQM6600空气质量传感器_#include_08

数据格式

STM32F103ZET6-KQM6600空气质量传感器_#include_09

校验和:保证双方数据数据传输的准确:

自己计算的校验和要和对方传递的校验和一致,表示数据没有问题

KQM6600.C

#include "kqm6600.h"
#include "stm32f10x.h"                  // Device header
#include "stdio.h"
#include "string.h"
KQM Kqm;//定义KQM6600相关的变量
SENSOR Sensor;//传感器参数
/*

串口
PA2  TX 复用推挽输出 确定牧师1看官方例程  2参考手册8.1.11
PA3  RX
*/
void KQM6600_Config(void)
{
	//1.开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//2.定义结构体
	GPIO_InitTypeDef My_TX2={0};
	//3.定功能-------KQM6600只需要接收数据不需要发送  
	My_TX2.GPIO_Mode=GPIO_Mode_AF_PP;
	My_TX2.GPIO_Pin=GPIO_Pin_2;
	My_TX2.GPIO_Speed=GPIO_Speed_50MHz;
	//4.传地址
	GPIO_Init(GPIOA,&My_TX2);
	My_TX2.GPIO_Mode = GPIO_Mode_IN_FLOATING;//工作模式  (1)参考官方例程  (2)参考手册8.1.11
	My_TX2.GPIO_Pin = GPIO_Pin_3;  //引脚	
	GPIO_Init(GPIOA,&My_TX2);	
	//5.开USART2时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	//6.定义串口结构体
	USART_InitTypeDef My_Uart2={0};
	//7.定功能
	My_Uart2.USART_BaudRate=9600;//波特率
	My_Uart2.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	My_Uart2.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//发送模式--接收功能
	My_Uart2.USART_Parity=USART_Parity_No;
	My_Uart2.USART_StopBits=USART_StopBits_1;
	My_Uart2.USART_WordLength=USART_WordLength_8b;
	//8.传地址
	USART_Init(USART2,&My_Uart2);
	//9.使USART1使能
  USART_Cmd(USART2,ENABLE);
//	 UART1_NVIC_Config();

	
	//10定义结构体
	NVIC_InitTypeDef NVIC_InitStruct={0};

	//11.给结构体赋值
	
	NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;  //中断通道
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;   //使能对应的中断
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //次级优先级   两个优先级的参数要和分组函数NVIC_PriorityGroupConfig保持一致
	NVIC_Init(&NVIC_InitStruct);
	
	//12开启需要的中断
	//void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState); stm32fo1x_usart.h 371行
	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启接收中断
	USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);//开启空闲中断
}

void USART2_IRQHandler(void)
{
	uint8_t date=0;
	//ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
	//void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);stm32f10x_usart.h  392行
	//1.判断中断是否触发
	if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)
	{
		//2.编写中断服务函数执行内容
		date=USART_ReceiveData(USART2);//读到的内容
		Kqm.R_Buff[Kqm.R_Length++]=date;
		if(Kqm.R_Length>=100)
		Kqm.R_Length=0;//避免数组越界
		//3.清除中断标志位
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);
	}
	if(USART_GetITStatus(USART2,USART_IT_IDLE)==SET)//空闲情况
	{
		//参考手册25.6.4位4的介绍 软件序列清除 先读USART_SR寄存器再读USART_DR寄存器
		date=USART_ReceiveData(USART2);
		Kqm.R_Idle=1;//检测到数据位为1,表示接收完毕
	}
}
//数据接收完成,调用处理函数
void KQM_Handle(void)
{
	uint8_t temp_date=0;//存放校验和
	if(Kqm.R_Idle==1)
	{
		//触发空闲,数据接收完成
		Kqm.R_Idle=0;
		if(Kqm.R_Buff[0]==0x5F)
		{
			//说明帧头(地址码)正确
			temp_date=Kqm.R_Buff[0]+Kqm.R_Buff[1]+Kqm.R_Buff[2]+Kqm.R_Buff[3]+Kqm.R_Buff[4]+Kqm.R_Buff[5]+Kqm.R_Buff[6];
			if(temp_date==Kqm.R_Buff[7])//地址码加数据位等于校验值
			{
				//校验通过
				Sensor.voc=((Kqm.R_Buff[1]<<8)+Kqm.R_Buff[2])*0.1;
				Sensor.ch20=((Kqm.R_Buff[3]<<8)+Kqm.R_Buff[4])*0.01;
				Sensor.co2=((Kqm.R_Buff[5]<<8)+Kqm.R_Buff[6])*0.01;
				printf("voc=%.2f ch20=%.2f co2=%d\r\n",Sensor.voc,Sensor.ch20,Sensor.co2);
			}
		}
		memset(Kqm.R_Buff,0,sizeof(Kqm.R_Buff));//收集完要清理数据,下次从头接收
		Kqm.R_Length=0;//这两条数据需要成对使用
	}
}

KQM6600.H

#ifndef __KQM6600_H_
#define __KQM6600_H_
#include "stm32f10x.h"
#define KQM_R_Buff_Length  10
void KQM6600_Config(void);
void USART2_IRQHandler(void);
void KQM_Handle(void);
typedef struct 
{
	uint8_t R_Buff[10];//接收缓冲区
	uint8_t R_Length;//接收长度
	uint8_t R_Idle;//接收空闲标志位
}KQM;

typedef struct 
{
	float voc;
	float ch20;
	uint16_t co2;
}SENSOR;
extern SENSOR Sensor;
#endif

main.c

#include "stm32f10x.h"
#include "BEEP.h"
#include "TIME6.h"
#include "Delay.h"
#include "uart1.h"
#include "stdio.h"
#include "exti.h"
#include "string.h"
#include "kqm6600.h"
int main(void)
{
	//中断优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组  分组决定了NVIC结构体和抢占、次级选择的数
	KQM6600_Config();
	UART1_Config();//因为用的printf函数在此函数内定义
	printf("程序进入主循环\n");
	BEEP_Config();
	while(1)
	{
		if(Sensor.voc>3)
		{
			BEEP_ON();//当采集到的空气数据大于相关设定值就报警
		}
		KQM_Handle();
	}
}

完结撒花