单片机读取MQ-7一氧化碳传感器值

使用TM4C123G单片机和51单片机分别读取MQ-7一氧化碳传感器值并实现报警功能

一、传感器简单介绍

  1. MQ-7属于电阻式传感器,内置二氧化锡气敏材料,可有效感应一氧化碳等有效气体,其中对一氧化碳的浓度感应灵敏度最高,但也可作为广谱的可燃气体传感器进行使用。

  2. MQ-7传感器读取方式为AD读取,也可利用数字方式读取。本文采用模拟量读取。

  3. 资料显示,MQ-7传感器在使用前必须经过一分钟的加热过程(接通电源即可自动加热)

  4. MQ-7内部原件构造如图:内部构造

  5. 输出电压-浓度图像如图所示:
    浓度-电压图

二、传感器的连接

TM4C:

单片机管脚传感器管脚
VBUSVCC
GNDGND
PE3AO
N/ADO

普中科技51单片机:

单片机管脚传感器管脚
VCCVCC
GNDGND
IN3AO
N/ADO

三、TM4C单片机程序模块分析

ADC模块初始化
void ADC_Init(void)//ADC初始化配置   
{    
  SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);// Enable the ADC0 module.
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0));// Wait for the ADC0 module to be ready.	
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);    //Enable GPIO port E
  GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);		//Enable PE3
  ADCSequenceConfigure(ADC0_BASE,0,ADC_TRIGGER_PROCESSOR, 0); 
	ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH4	|ADC_CTL_END | ADC_CTL_IE);
	ADCIntClear(ADC0_BASE, 0);
	ADCSequenceEnable(ADC0_BASE, 0);    
  ADCIntEnable(ADC0_BASE, 0); 
	ADCIntEnableEx(ADC0_BASE,ADC_INT_SS0);
	IntEnable(INT_ADC0SS0);
	ADCIntRegister(ADC0_BASE,0,ADC0IntHandler);
	IntPrioritySet(INT_ADC0SS0, USER_INT7);
}//采用中断式ADC采集
串口0初始化(printf函数用)
void ConfigureUART0(void)//串口0初始化
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);//使能GPIO外设		
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);//使能UART外设
  GPIOPinConfigure(GPIO_PA0_U0RX);//GPIO模式配置 PA0--RX PA1--TX 
  GPIOPinConfigure(GPIO_PA1_U0TX);
  GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);//GPIO的UART模式配置
  UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
  UARTStdioConfig(0, 115200, 16000000);
}
滴答定时器初始化(加热过程计时用)
void initTime(void) 
{
  	SysTickPeriodSet(SysCtlClockGet() / 500UL);//2ms
	SysTickIntRegister(SycTickHandler);
  	SysTickIntEnable();
  	SysTickEnable();
	systick_period=SysTickPeriodGet();
}
ADC中断
void ADC0IntHandler(void)
{
	Test_Period(&ADC_Delta);
	ADCIntClear(ADC0_BASE, 0);// 清除ADC中断标志。
	ADCSequenceDataGet(ADC0_BASE, 0, adc_value);// 读取ADC值
	value=(float)adc_value[0]*3.3/4096*100;//扩大100倍精度
	if(queuei==99)
	{
		dataSum+=value;
		printf("%f\n",dataSum/100);//取平均稳定数据
		if((dataSum/100)<=2500) printf("CO concentration safe\n");//以低于50ppm为安全值(由上文Vl-PPM图粗略看出)
		//网上写的一般警告值是35ppm,但是我们的传感器没有这么精准
		else printf("Danger, open your window and evacuate\n");
		queuei=0;
		dataSum=0;
	}
	else 
	{
		dataSum+=value;
		queuei++;
	}
}
主函数
#include <stdint.h>
#include <stdbool.h>
#include "hw_types.h"
#include "interrupt.h"
#include "sysctl.h"
#include "u_DMA.h"
#include "UART0.h"
#include "usart.h"
#include "Headfile.h"
int heat_flag=0;
int heattimeCounter=0;
int main()
{
	HardWave_Init();
	printf("初始化完成");
	while(1)
	{
		if(heat_flag!=2)
		{
			if(heat_flag==0)
			{
				printf("Initiate heating process ,please wait for 1 minute\n");
				heat_flag=1;
				delay_ms(1000);
				heattimeCounter++;
			}
			else if(heat_flag==1&&heattimeCounter!=60)
			{
				printf("time remains:%d\n",60-heattimeCounter);
				delay_ms(1000);
				heattimeCounter++;
			}
			else
			{
				heat_flag=2;
				printf("Heating process complete\n");
			}
		}
		else 
		{
			ADC_Sample_Trigger();
			delay_ms(1);
		}
	}
}

四、51单片机程序模块分析

XPT2046驱动(读取AD值,SPI协议)
#include"XPT2046.h"
/****************************************************************************
*函数名:TSPI_Start
*输  入:无
*输  出:无
*功  能:初始化触摸SPI
****************************************************************************/

void SPI_Start(void)
{
	CLK = 0;
	CS  = 1;
	DIN = 1;
	CLK = 1;
	CS  = 0;		
}
/****************************************************************************
*函数名:SPI_Write
*输  入:dat:写入数据
*输  出:无
*功  能:使用SPI写入数据
****************************************************************************/

void SPI_Write(uchar dat)
{
	uchar i;
	CLK = 0;
	for(i=0; i<8; i++)
	{
		DIN = dat >> 7;  	//放置最高位
		dat <<= 1;
		CLK = 0;			//上升沿放置数据

		CLK = 1;

	}
}
/****************************************************************************
*函数名:SPI_Read
*输  入:无
*输  出:dat:读取 到的数据
*功  能:使用SPI读取数据
****************************************************************************/

uint SPI_Read(void)
{
	uint i, dat=0;
	CLK = 0;
	for(i=0; i<12; i++)		//接收12位数据
	{
		dat <<= 1;

		CLK = 1;
		CLK = 0;

		dat |= DOUT;

	}
	return dat;	
}

/****************************************************************************
*函数名:Read_AD_Data
*输  入:cmd:读取的X或者Y
*输  出:endValue:最终信号处理后返回的值
*功  能:读取触摸数据
****************************************************************************/
uint Read_AD_Data(uchar cmd)
{
	uchar i;
	uint AD_Value;
	CLK = 0;
	CS  = 0;
	SPI_Write(cmd);
	for(i=6; i>0; i--); 	//延时等待转换结果
	CLK = 1;	  //发送一个时钟周期,清除BUSY
	_nop_();
	_nop_();
	CLK = 0;
	_nop_();
	_nop_();
	AD_Value=SPI_Read();
	CS = 1;
	return AD_Value;	
}
主函数
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include"XPT2046.h"	

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

sbit LED=P2^0;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

u8 disp[4];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

/*******************************************************************************
* 函 数 名         : delay
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}

/*******************************************************************************
* 函数名         :datapros()
* 函数功能		 :数据处理函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void datapros()
{
	u16 temp;
	static u8 i;
	if(i==50)
	{
		i=0;
		temp = Read_AD_Data(0xE4);		//   AIN3 外部输入
	}
	i++;
	disp[0]=smgduan[temp/1000];//千位
	disp[1]=smgduan[temp%1000/100];//百位
	disp[2]=smgduan[temp%1000%100/10];//个位
	disp[3]=smgduan[temp%1000%100%10];		
	if(temp>=2500)			//报警功能:闪烁灯
	{
		LED=1;
		delay(1000);
		LED=0;
	}
}


/*******************************************************************************
* 函数名         :DigDisplay()
* 函数功能		 :数码管显示函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void DigDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=1;LSB=1;LSC=1; break;//显示第0位
			case(1):
				LSA=0;LSB=1;LSC=1; break;//显示第1位
			case(2):
				LSA=1;LSB=0;LSC=1; break;//显示第2位
			case(3):
				LSA=0;LSB=0;LSC=1; break;//显示第3位	
		}
		P0=disp[i];//发送数据
		delay(100); //间隔一段时间扫描	
		P0=0x00;//消隐
	}		
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	while(1)
	{
		datapros();	 //数据处理函数
		DigDisplay();//数码管显示函数		
	}		
}

五、程序效果

TM4C123G

1、加热启动过程
加热驱动
2、测量电压Vl值

TM4C

利用打火机模拟可燃气体源
利用打火机模拟可燃气体源
SerialChart绘制曲线
SerialChart绘制曲线

51单片机

51单片机

  • 12
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: stm32 单片机MQ-2 烟雾传感器模块的代码实现,其实比较简单,只需要通过 ADC(模数转换器)来读取传感器输出的模拟信号,并转换为数字信号进行处理即可。 具体步骤如下: 1. 初始化 ADC 首先,需要在 stm32 单片机上初始化 ADC,并设置其通道和转化时间等参数,例如: ```c void init_ADC(void){ RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //开启 ADC1 时钟 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //开启 GPIOA 时钟 GPIOA->MODER |= GPIO_MODER_MODE0; //配置 PA0 为模拟输入模式 ADC1->SQR3 |= 0x00; //转换第1个通道,即PA0 ADC1->SMPR2 |= ADC_SMPR2_SMP0_0 | ADC_SMPR2_SMP0_1 | ADC_SMPR2_SMP0_2; //设置采样时间为 480 个时钟周期 ADC1->CR2 |= ADC_CR2_ADON; //开启 ADC } ``` 2. 读取传感器信号 然后,需要通过 ADC 读取 MQ-2 烟雾传感器模块的输出信号,即烟雾浓度,例如: ```c int read_smoke_sensor(void){ int sensor_value = 0; ADC1->CR2 |= ADC_CR2_SWSTART; //启动转换 while(!(ADC1->SR & ADC_SR_EOC)); //等待转换结束 sensor_value = ADC1->DR; //获取转换结果 return sensor_value; } ``` 3. 处理传感器信号 最后,需要对读取到的传感器信号进行处理,例如判断是否有烟雾浓度超过预设阈,并执行相应操作,例如: ```c void smoke_detection(void){ int sensor_value = read_smoke_sensor(); //读取烟雾浓度 if(sensor_value > SMOKE_THRESHOLD){ //判断是否超过阈 //执行相应操作,例如开启报警器等 } } ``` 综上所述,通过 ADC 读取 MQ-2 烟雾传感器模块的输出信号,并进行相应的处理,可以实现 stm32 单片机MQ-2 烟雾传感器模块的代码。 ### 回答2: MQ-2烟雾传感器模块是一种基于化学传感原理的气敏元件,它可以检测空气中的不同气体(包括有毒和可燃气体)的浓度,并将检测到的气体浓度转换成电信号输出。STM32单片机可以通过接口和程序控制该烟雾传感器模块。 烟雾传感器模块的接线是非常简单的,需要将其信号引脚与单片机的输入引脚相连。在使用该模块之前,需要对其进行预热,以保证其正常工作。具体来说,程序在初始化时需要设置传感器引脚为输入模式,并使用定时器来控制传感器模块的预热。 程序的主要逻辑是,读取传感器的电压,并将其转换成与浓度成正比的数。然后,根据检测到的烟雾浓度,通过串口将结果输出到显示终端上。程序也可以通过设置阈来报警,当浓度超过预设阈后,会触发预设警报动作。 在编写该烟雾传感器模块的代码时,需要考虑到传感器的特性和工作原理,理解传感器模块的输出结果,以及如何将其与单片机交互。同时,需要注意程序的效率和稳定性,避免过分依赖硬件定时器或占用过多的处理器资源。 因此,编写stm32单片机mq-2烟雾传感器模块代码时,需要熟悉单片机的KEIL编程环境和GPIO口的使用,同时理解烟雾传感器模块的特性和工作原理。同时,还需要考虑如何在代码中处理传感器模块的噪声和误差,提高检测精度和稳定性。好的代码应该可以实现简单、高效和可靠的烟雾检测,并提供有效的预警功能,以确保严格的安全性和可靠性标准。 ### 回答3: 首先,需要了解MQ-2烟雾传感器模块的工作原理:它利用化学反应检测空气中的可燃气体(如一氧化碳、甲烷等)和烟雾,输出相应的电信号,通过单片机采集、处理,最终显示或触发响应措施。 根据MQ-2模块的引脚分布,一般需要连接到单片机的模拟输入引脚和数字输入/输出引脚(需要分别接上电阻和LED等元器件)。下面以STM32单片机为例,给出相应的代码: 1. 配置模拟输入引脚(以PA0为例): ``` GPIO_InitTypeDef GPIO_InitStruct; ADC_InitTypeDef ADC_InitStruct; /* 使能GPIOA时钟 */ __HAL_RCC_GPIOA_CLK_ENABLE(); /* 配置GPIOA0为模拟输入 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* 配置ADC1 */ __HAL_RCC_ADC1_CLK_ENABLE(); ADC_InitStruct.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; ADC_InitStruct.Resolution = ADC_RESOLUTION_12B; ADC_InitStruct.DataAlign = ADC_DATAALIGN_RIGHT; ADC_InitStruct.ContinuousConvMode = DISABLE; ADC_InitStruct.ScanConvMode = DISABLE; ADC_InitStruct.NbrOfConversion = 1; ADC_InitStruct.DiscontinuousConvMode = DISABLE; ADC_InitStruct.EOCSelection = ADC_EOC_SINGLE_CONV; HAL_ADC_Init(&hadc1); /* 配置ADC通道0 */ ADC_ChannelConfTypeDef sConfig; sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; HAL_ADC_ConfigChannel(&hadc1, &sConfig); ``` 2. 读取模拟输入信号并判断烟雾/可燃气体浓度是否超过设定(以PA0为例): ``` ADC_HandleTypeDef hadc1; uint16_t adc_value; /* 启动ADC转换 */ HAL_ADC_Start(&hadc1); /* 等待转化结束 */ if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) { adc_value = HAL_ADC_GetValue(&hadc1); if (adc_value > threshold) { // 烟雾/可燃气体浓度超过设定,触发响应措施 HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); // ... } } ``` 其中的`threshold`可以根据实际情况设置。另外,为了方便测试,可以在程序中加入串口打印等调试功能。需要注意的是,STM32单片机的编译环境、库文件等可能需要进行相应的配置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值