使用TM4C123G单片机和51单片机分别读取MQ-7一氧化碳传感器值并实现报警功能
一、传感器简单介绍
-
MQ-7属于电阻式传感器,内置二氧化锡气敏材料,可有效感应一氧化碳等有效气体,其中对一氧化碳的浓度感应灵敏度最高,但也可作为广谱的可燃气体传感器进行使用。
-
MQ-7传感器读取方式为AD读取,也可利用数字方式读取。本文采用模拟量读取。
-
资料显示,MQ-7传感器在使用前必须经过一分钟的加热过程(接通电源即可自动加热)
-
MQ-7内部原件构造如图:
-
输出电压-浓度图像如图所示:
二、传感器的连接
TM4C:
单片机管脚 | 传感器管脚 |
---|---|
VBUS | VCC |
GND | GND |
PE3 | AO |
N/A | DO |
普中科技51单片机:
单片机管脚 | 传感器管脚 |
---|---|
VCC | VCC |
GND | GND |
IN3 | AO |
N/A | DO |
三、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绘制曲线