基于单片机(STC89C52)的易燃气体浓度检测报警系统

本文介绍了一款基于STC89C52单片机的易燃气体浓度检测报警系统,使用MQ-5传感器检测气体,ADC0809进行模数转换,LCD1602显示数据,并通过HC-05蓝牙模块将浓度信息传输到手机APP。硬件选择考虑了成本和实用性,系统设计包括硬件选择、原理图设计和代码实现。

一、硬件选择

首先是硬件的选择,本系统是以STC89C52芯片为核心作单片机做小系统,在此基础上进行扩展,选择MQ-5作为烟雾传感器,LCD1602为显示模块,模数转换采用的是ADC0809,利用HC-05蓝牙模块实现将检测到的易燃气体浓度实时传输到手机APP,除此之外还有电源模块、蜂鸣器、按键模块(三个控制按键以及一个复位按键)、发光二极管,可自行选择合适的元器件进行搭配。选择以上硬件的原因如下:

 MQ-5

气敏传感器MQ-5适用于家庭或工业上对液化气,天然气,煤气的监测装置。其具有对液化气、天然气、城市煤气有较好的灵敏度;对乙醇,烟雾几乎不响应,具有优良的抗干扰能力;有快速的响应恢复特性;有长期的使用寿命和可靠的稳定性;测试电路比较简单等优点。

MQ-5气敏元件的结构和外形如图2所示(结构A或B),由微型AL203陶瓷管、Sn02敏感层,测量电极和加热器构成的敏感元件固定在塑料或不锈钢制成的腔体内,加热器为气敏元件提供了必要的工作条件。封装好的气敏元件有6只针状管脚,其中4个用于信号取出,2个用于提供加热电流。

(MQ-5价格便宜,而且在淘宝上可以买到已经集成好的模块,使用方便,所以建议直接采购已集成好的MQ-5模块。)

STC89C52

STC89C52是一种低功耗、高性能CMOS8位微控制器,具有8K字节的系统可编程Flash存储器。使用高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位CPU和在线系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案

STC89C52具有以下标准功能:8k字节Flash,256字节RAM,32位I/0口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,STC89C52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。8位微控制器8K字节在系统可编程Flash。

ADC0809

ADC0809是带有8位A/D转换器、8路多路开关以及微处理机兼容的控制逻辑的CMOS组件。它是逐次逼近式A/D转换器,可以和单片机直接接口。

ADC0809由一个8路模拟开关、一个地址锁存与译码器、一个A/D转换器和一个三态输出锁存器组成。多路开关可选通8个模拟通道,允许8路模拟量分时输入,共用A/D转换器进行转换。三态输出锁器用于锁存A/D转换完的数字量,当OE端为高电平时,才可以从三态输出锁存器取走转换完的数据。

LCD1602显示模块

1602液晶是工业字符型液晶,能够同时显示16*2即32个字符。1602液晶模块内部的字符发生存储器已经存储了160个不同的点阵字符图形,这些字这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码。使用时直接编写软件程序按一定的时序驱动即可。它的特点是显示字迹清楚,价格相对便宜。
与数码管相比LCD1602模块有如下优点: 
         a.位数多,可显示32位,32个数码管体积相当庞大了
         b.显示内容丰富,可显示所有数字和大、小写字母 
         c.程序简单,如果用数码管动态显示,会占用很多时间来刷新显示,而1602自动完成此功能

蓝牙模块

蓝牙是一种设备之间进行无线通信的技术,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换,通信距离从几米到几百米不等。蓝牙串口透传模块让用户更好的开发蓝牙无线传输产品,而不需要关心蓝牙协议栈如何实现。简单,稳定性和可靠性有保证。

HC-05蓝牙模块的特点:

(1)采用CSR主流蓝牙芯片,蓝牙V2.0协议标准;

(2)输入电压:3.6V--6V,禁止超过7V;

(3)波特率为1200,2400,4800,9600,19200,38400,57600,115200用户可设置;

(4)带连接状态指示灯,LED快闪表示没有蓝牙连接;LED慢闪表示进入AT命令模式;

(5)板载3.3V稳压芯片,输入电压直流3.6V-6V;未配对时,电流约30mA(因LED灯闪烁,电流处于变化状态);配对成功后,电流大约10mA。

(6)用于GPS导航系统,水电煤气抄表系统,工业现场采控系统;

(7)可以与蓝牙笔记本电脑、电脑加蓝牙适配器等设备进行无缝连接。

(8)HC-05嵌入式蓝牙串口通讯模块(以下简称模块)具有两种工作模式:命令响应工作模式和自动连接工作模式,在自动连接工作模式下模块又可分为主(Master)、从(Slave)和回环(Loopback)三种工作角色。当模块处于自动连接工作模式时,将自动根据事先设定的方式连接的数据传输;当模块处于命令响应工作模式时能执行下述所有AT命令,用户可向模块发送各种AT指令,为模块设定控制参数或发布控制命令。通过控制模块外部引脚(PIO11)输入电平,可以实现模块工作状态的动态转换。

 

二、原理图设计

原理图的设计无需过多赘述,简而言之,就是在最小系统的基础上连接上各个模块,下面直接上图:

 

三、代码

有了以上的准备,再画好PCB并打板焊接元器件后就可以进行代码的烧录了,代码分为三个文件(main.cdisplay.hreg52.h)下面是我的代码(写得不好,望莫怪):

display.h代码如下:

//宏定义
#define uint unsigned int 
#define uchar unsigned char

//LCD管脚声明 (RW引脚实物直接接地,因为本设计只用到液晶的写操作,RW引脚一直是低电平)
sbit LCDRS = P2^3;
sbit LCDEN= P2^4;

//初始画时显示的内容
uchar code Init1[]="   SET E:000    ";
uchar code Init2[]="   NOW E:000    ";
//LCD延时
void LCDdelay(uint z)		  //该延时大约100us(不精确,液晶操作的延时不要求很精确)
{
  uint x,y;
  for(x=z;x>0;x--)
    for(y=10;y>0;y--);
}

//写命令
void write_com(uchar com)
{
  LCDRS=0;				  
  P0=com;
  LCDdelay(5);
  LCDEN=1;
  LCDdelay(5);
  LCDEN=0;
}
//写数据
void write_data(uchar date)
{
  LCDRS=1;
  P0=date;
  LCDdelay(5);
  LCDEN=1;
  LCDdelay(5);
  LCDEN=0;
}
//1602初始化
void Init1602()
{
  uchar i=0;
  write_com(0x38);//屏幕初始化(功能设定)
  write_com(0x0c);//打开显示 无光标 无光标闪烁(显示开关控制)
  write_com(0x06);//当读或写一个字符是指针后一一位
  write_com(0x01);//清屏
  write_com(0x80);//设置位置

  for(i=0;i<16;i++)
  {
		write_data(Init1[i]);	  //显示数组1的数据
  }
  write_com(0x80+0x40);//设置位置
  for(i=0;i<16;i++)
  {
		write_data(Init2[i]);	  //显示数组2的数据
  }
}

void Display_1602(yushe_yanwu,temp)
{
	//设置烟雾
	write_com(0x80+9);
	write_data(0x30+yushe_yanwu/100);
	write_data(0x30+yushe_yanwu%100/10);
	write_data(0x30+yushe_yanwu%10);

	//时时烟雾
	write_com(0x80+0x40+9);
	write_data(0x30+temp/100);
	write_data(0x30+temp%100/10);
	write_data(0x30+temp%10);
}

reg52.h代码如下:

#ifndef __REG52_H__
#define __REG52_H__

/*  BYTE Registers  */
sfr P0    = 0x80;
sfr P1    = 0x90;
sfr P2    = 0xA0;
sfr P3    = 0xB0;
sfr PSW   = 0xD0;
sfr ACC   = 0xE0;
sfr B     = 0xF0;
sfr SP    = 0x81;
sfr DPL   = 0x82;
sfr DPH   = 0x83;
sfr PCON  = 0x87;
sfr TCON  = 0x88;
sfr TMOD  = 0x89;
sfr TL0   = 0x8A;
sfr TL1   = 0x8B;
sfr TH0   = 0x8C;
sfr TH1   = 0x8D;
sfr IE    = 0xA8;
sfr IP    = 0xB8;
sfr SCON  = 0x98;
sfr SBUF  = 0x99;

/*  8052 Extensions  */
sfr T2CON  = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2    = 0xCC;
sfr TH2    = 0xCD;


/*  BIT Registers  */
/*  PSW  */
sbit CY    = PSW^7;
sbit AC    = PSW^6;
sbit F0    = PSW^5;
sbit RS1   = PSW^4;
sbit RS0   = PSW^3;
sbit OV    = PSW^2;
sbit P     = PSW^0; //8052 only

/*  TCON  */
sbit TF1   = TCON^7;
sbit TR1   = TCON^6;
sbit TF0   = TCON^5;
sbit TR0   = TCON^4;
sbit IE1   = TCON^3;
sbit IT1   = TCON^2;
sbit IE0   = TCON^1;
sbit IT0   = TCON^0;

/*  IE  */
sbit EA    = IE^7;
sbit ET2   = IE^5; //8052 only
sbit ES    = IE^4;
sbit ET1   = IE^3;
sbit EX1   = IE^2;
sbit ET0   = IE^1;
sbit EX0   = IE^0;

/*  IP  */
sbit PT2   = IP^5;
sbit PS    = IP^4;
sbit PT1   = IP^3;
sbit PX1   = IP^2;
sbit PT0   = IP^1;
sbit PX0   = IP^0;

/*  P3  */
sbit RD    = P3^7;
sbit WR    = P3^6;
sbit T1    = P3^5;
sbit T0    = P3^4;
sbit INT1  = P3^3;
sbit INT0  = P3^2;
sbit TXD   = P3^1;
sbit RXD   = P3^0;

/*  SCON  */
sbit SM0   = SCON^7;
sbit SM1   = SCON^6;
sbit SM2   = SCON^5;
sbit REN   = SCON^4;
sbit TB8   = SCON^3;
sbit RB8   = SCON^2;
sbit TI    = SCON^1;
sbit RI    = SCON^0;

/*  P1  */
sbit T2EX  = P1^1; // 8052 only
sbit T2    = P1^0; // 8052 only
             
/*  T2CON  */
sbit TF2    = T2CON^7;
sbit EXF2   = T2CON^6;
sbit RCLK   = T2CON^5;
sbit TCLK   = T2CON^4;
sbit EXEN2  = T2CON^3;
sbit TR2    = T2CON^2;
sbit C_T2   = T2CON^1;
sbit CP_RL2 = T2CON^0;

#endif

 

main.c代码如下:

//程序头函数
#include <reg52.h>
//显示函数
#include <display.h>	//显示函数display.h在工程里	也可鼠标选中左边右键open document <display.h>

//宏定义
#define uint unsigned int 
#define uchar unsigned char
#define Data_ADC0809 P1		 //定义P1口为Data_ADC0809 (之后的程序里Data_ADC0809即代表P1口)
 
//管脚声明
sbit LED_yanwu1= P2^1;		 //烟雾报警灯
sbit LED_yanwu2= P2^2;
sbit baojing= P2^5;			 //蜂鸣器接口
//ADC0809
sbit ST=P3^3;
sbit EOC=P3^6;
sbit OE=P3^2;
//按键
sbit Key1=P2^6;				 //设置键
sbit Key2=P2^7;				 //加按键
sbit Key3=P3^7;				 //减按键

//酒精含量变量
uchar temp,a;					 //用于读取ADC数据
uchar sendStr[6];
uchar yushe_yanwu=45;		 //烟雾预设值
//按钮模式|  
uchar Mode=0;				 //=1是设置温度阀值  =2是设置烟雾阀值

//函数声明
extern uchar ADC0809();
extern void Key();

void Count0Init()
{
	SCON=0X50;		//设置为工作方式1
	TMOD=0X20;		//设置计数器工作方式2	自动重装载
	PCON=0X80;		//波特率加倍
	TH1=0XF3;		//计数器初始值设置,注意波特率是4800的
	TL1=0XF3;
	ES=1;				//打开接收中断
	EA=1;				//打开总中断
	TR1=1;				//打开计数器			
}

void delay(uint i)
{
	while(i--);	
}

//ADC0809读取信息
uchar ADC0809()
{
	uchar temp_=0x00;
	//初始化高阻太

	OE=0;
	//转化初始化
	ST=0;
	//开始转换
	ST=1;
	ST=0;
	//外部中断等待AD转换结束
	while(EOC==0)
	//读取转换的AD值
	OE=1;
	temp_=Data_ADC0809;
	OE=0;
	return temp_;
}

void Key()
{
	//模式选择
	if(Key1==0)	  //设置按键
	{
		while(Key1==0);
		if(Mode>=2) Mode=0;
		else
		{
//	   		write_com(0x38);//屏幕初始化
	   		write_com(0x0f);//打开显示 无光标 光标闪烁
//	   		write_com(0x06);//当读或写一个字符是指针后一一位
			Mode++;			//模式加一
			switch(Mode)	//判断模式的值
			{
				case 1:
				{
					write_com(0x80+7);//为1时 温度阀值的位置闪烁
					break;			  //执行后跳出switch
				}
				case 2:					//当模式加到3时
				{
//					write_com(0x38);//屏幕初始化
					write_com(0x0c);//打开显示 无光标 无光标闪烁
					Mode=0;			//模式清零
					break;
				}
			}
		}
	}
	if(Key2==0&&Mode!=0)	 //加按键只有在模式不等于0时有效
	{
		while(Key2==0);
		yushe_yanwu++;					   //同温度阀值设置
		if(yushe_yanwu>=255)
		yushe_yanwu=255;
		write_com(0x80+13);
		write_data(0x30+yushe_yanwu/100);
		write_data(0x30+yushe_yanwu%100/10);
		write_data(0x30+yushe_yanwu%10);
		write_com(0x80+15);
	}
	if(Key3==0&&Mode!=0)
	{
		while(Key3==0);
		yushe_yanwu--;							  //同上
		if(yushe_yanwu<=0)
		yushe_yanwu=0;
		write_com(0x80+13);
		write_data(0x30+yushe_yanwu/100);
		write_data(0x30+yushe_yanwu%100/10);
		write_data(0x30+yushe_yanwu%10);
		write_com(0x80+15);
	}
}
void send_string(uchar *p) ;
/*****主函数*****/
void main()
{
	Init1602();
	Count0Init();			  //调用初始化显示函数
	while(1)			  //进入循环
	{
		temp=ADC0809();	  //读取烟雾值
		Key();			  //调用按键函数  扫描按键

		if(Mode==0)		  //只有当模式为0时才会执行以下的阀值判断部分
		{
			Display_1602(yushe_yanwu,temp);  //显示预设烟雾,烟雾值
			if(temp>=yushe_yanwu)	  //烟雾值大于等于预设值时
			{
				LED_yanwu1=0;
				LED_yanwu2=0;		  //烟雾指示灯亮
				baojing=0;			  //蜂鸣器报警
			}
			else					  //烟雾值小于预设值时
			{
				LED_yanwu1=1;
				LED_yanwu2=1;		  //关掉报警灯
			}
			if(temp<yushe_yanwu)	  //当烟雾小于预设值并且温度也小于预设值时 (&&:逻辑与,左右两边的表达式都成立(都为真,也就是1)时,该if语句才成立)
			{
				baojing=1;			  //停止报警
			}
		}
		   sendStr[0]=0x30+temp/100;
		   sendStr[1]=0x30+temp%100/10;
		   sendStr[2]=0x30+temp%10;
		   sendStr[3]=' ';
		   sendStr[4]=' ';
		   sendStr[5]=' ';
		   send_string(sendStr);
           delay(50000);
	}
}	

/*发送一个字符*/
void send_byte(uchar by){
	
	SBUF = by;
	while(!TI); //等待发送完毕
	TI = 0;    
}

void send_string(uchar *p){
	
	while(*p!= '\0'){
		
		send_byte(*p);
		p++;
		
	}
}



void ser() interrupt 4
{
	RI=0; //接收到数据后,将 RI 置 0
	a=SBUF; //接收数据
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼睡不醒_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值