基于51单片机的温度、烟雾、火焰检测设计

基于51单片机的火灾检测设计

(仿真+程序+原理图+设计报告)

功能介绍

具体功能:

1.使用MQ-2烟雾采集,使用ADC0832将传感器输出的模拟信号转化为数字信号,再传给单片机。

2.使用DS18B20采集温度。

4.火焰检测使用火焰检测模块,最终输出高低电平信号给单片机。

5.显示设备使用LCD1602,实时显示温度、烟雾值,温度烟雾报警阈值。

6.使用蜂鸣器和LED灯构成报警模块,三个LED灯对应着温度、烟雾、火焰。

7.三个按键可以设置温度、烟雾报警阈值。

​演示视频:

基于51单片机的温度烟雾火焰检测设计 

#include <reg52.h>
#include <intrins.h>#define uchar unsigned char		// 以后unsigned char就可以用uchar代替
#define uint  unsigned int		// 以后unsigned int 就可以用uint 代替sfr ISP_DATA  = 0xe2;					// 数据寄存器
sfr ISP_ADDRH = 0xe3;					// 地址寄存器高八位
sfr ISP_ADDRL = 0xe4;					// 地址寄存器低八位
sfr ISP_CMD   = 0xe5;					// 命令寄存器
sfr ISP_TRIG  = 0xe6;					// 命令触发寄存器
sfr ISP_CONTR = 0xe7;					// 命令寄存器sbit Fire_P   = P1^0;					// 火焰传感器引脚
sbit DQ       = P1^1;					// 温度传感器的引脚
sbit ADC_CS   = P1^2; 				// ADC0832的CS引脚
sbit ADC_CLK  = P1^3; 				// ADC0832的CLK引脚
sbit ADC_DAT  = P1^4; 				// ADC0832的DI/DO引脚
sbit LcdRs_P  = P2^7;     		// 1602液晶的RS管脚       
sbit LcdRw_P  = P2^6;     		// 1602液晶的RW管脚 
sbit LcdEn_P  = P2^5;     		// 1602液晶的EN管脚
sbit Key1_P   = P3^2;					// 设置按键
sbit Key2_P   = P3^3;					// 减按键
sbit Key3_P   = P3^4;					// 加按键
sbit Buzzer_P = P2^0;					// 蜂鸣器
sbit Led1_P   = P2^3;					// 报警灯1,火焰报警
sbit Led2_P   = P2^2;					// 报警灯2,温度报警
sbit Led3_P   = P2^1;					// 报警灯3,烟雾报警uchar gMqAlarm;								// 烟雾报警值
int   gTempAlarm;							// 温度报警值/*********************************************************/
// 单片机内部EEPROM不使能
/*********************************************************/
void ISP_Disable()
{ISP_CONTR = 0;ISP_ADDRH = 0;ISP_ADDRL = 0;
}/*********************************************************/
// 从单片机内部EEPROM读一个字节,从0x2000地址开始
/*********************************************************/
unsigned char EEPROM_Read(unsigned int add)
{ISP_DATA  = 0x00;ISP_CONTR = 0x83;ISP_CMD   = 0x01;ISP_ADDRH = (unsigned char)(add>>8);ISP_ADDRL = (unsigned char)(add&0xff);// 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效ISP_TRIG  = 0x46;	   ISP_TRIG  = 0xB9;_nop_();ISP_Disable();return (ISP_DATA);
}/*********************************************************/
// 往单片机内部EEPROM写一个字节,从0x2000地址开始
/*********************************************************/
void EEPROM_Write(unsigned int add,unsigned char ch)
{ISP_CONTR = 0x83;ISP_CMD   = 0x02;ISP_ADDRH = (unsigned char)(add>>8);ISP_ADDRL = (unsigned char)(add&0xff);ISP_DATA  = ch;ISP_TRIG  = 0x46;ISP_TRIG  = 0xB9;_nop_();ISP_Disable();
}/*********************************************************/
// 擦除单片机内部EEPROM的一个扇区
// 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
/*********************************************************/
void Sector_Erase(unsigned int add)	  
{ISP_CONTR = 0x83;ISP_CMD   = 0x03;ISP_ADDRH = (unsigned char)(add>>8);ISP_ADDRL = (unsigned char)(add&0xff);ISP_TRIG  = 0x46;ISP_TRIG  = 0xB9;_nop_();ISP_Disable();
}/*********************************************************/
// 毫秒级的延时函数,time是要延时的毫秒数
/*********************************************************/
void DelayMs(uint time)
{uint i,j;for(i=0;i<time;i++)for(j=0;j<112;j++);
}/*********************************************************/
// 延时15微秒
/*********************************************************/
void Delay15us(void)
{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}/*********************************************************/
// 复位DS18B20(初始化)
/*********************************************************/
void DS18B20_ReSet(void)
{uchar i;DQ=0;i=240;while(--i);DQ=1;i=30;while(--i);while(~DQ);i=4;while(--i);
}/*********************************************************/
// 向DS18B20写入一个字节
/*********************************************************/
void DS18B20_WriteByte(uchar dat)
{uchar j;uchar btmp;for(j=0;j<8;j++){btmp=0x01;btmp=btmp<<j;btmp=btmp&dat;if(btmp>0)		// 写1{DQ=0;Delay15us();DQ=1;Delay15us();Delay15us();Delay15us();Delay15us();}else			// 写0{DQ=0;Delay15us();Delay15us();Delay15us();Delay15us();DQ=1;Delay15us();}}
}/*********************************************************/
// 读取温度值
/*********************************************************/
int DS18B20_ReadTemp(void)
{uchar j;int b,temp=0;	DS18B20_ReSet();							// 产生复位脉DS18B20_WriteByte(0xcc);			// 忽略ROM指令DS18B20_WriteByte(0x44);			// 启动温度转换指令DS18B20_ReSet();							// 产生复位脉DS18B20_WriteByte(0xcc);			// 忽略ROM指令DS18B20_WriteByte(0xbe);			// 读取温度指令for(j=0;j<16;j++)							// 读取温度数量{						DQ=0;_nop_();_nop_();DQ=1;	Delay15us();b=DQ;Delay15us();Delay15us();Delay15us();b=b<<j;temp=temp|b;}temp=temp*0.0625;							// 合成温度值	return (temp);								// 返回检测到的温度值
}/*********************************************************/
// 1602液晶写命令函数,cmd就是要写入的命令
/*********************************************************/
void LcdWriteCmd(uchar cmd)
{ LcdRs_P = 0;LcdRw_P = 0;LcdEn_P = 0;P0=cmd;DelayMs(2);LcdEn_P = 1;    DelayMs(2);LcdEn_P = 0;	
}/*********************************************************/
// 1602液晶写数据函数,dat就是要写入的数据
/*********************************************************/
void LcdWriteData(uchar dat)
{LcdRs_P = 1; LcdRw_P = 0;LcdEn_P = 0;P0=dat;DelayMs(2);LcdEn_P = 1;    DelayMs(2);LcdEn_P = 0;
}/*********************************************************/
// 1602液晶初始化函数
/*********************************************************/
void LcdInit()
{LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口LcdWriteCmd(0x0C);        // 开显示,不显示光标LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移LcdWriteCmd(0x01);        // 清屏
}/*********************************************************/
// 液晶光标定位函数
/*********************************************************/
void LcdGotoXY(uchar line,uchar column)
{// 第一行if(line==0)        LcdWriteCmd(0x80+column); // 第二行if(line==1)        LcdWriteCmd(0x80+0x40+column); 
}/*********************************************************/
// 液晶输出字符串函数
/*********************************************************/
void LcdPrintStr(uchar *str)
{while(*str!='\0')LcdWriteData(*str++);
}/*********************************************************/
// 液晶输出数字
/*********************************************************/
void LcdPrintNum1(uchar num)
{LcdWriteData(num/100+48);			// 百位LcdWriteData(num%100/10+48);	// 十位LcdWriteData(num%10+48); 			// 个位
}/*********************************************************/
// 温度值的显示
/*********************************************************/
void LcdPrintNum2(int num)
{if(num<0)														// 显示负号{LcdWriteData('-');num=0-num;	}else            										// 显示百位{LcdWriteData(num/100+48);}LcdWriteData(num%100/10+48);				// 显示十位LcdWriteData(num%10+48);						// 显示个位
}/*********************************************************/
// 液晶显示初始化
/*********************************************************/
void LcdShowInit()
{LcdGotoXY(0,0);											// 液晶光标定位到第0行LcdPrintStr("Gas:            ");		// 液晶第0行显示" Gas:           "LcdGotoXY(1,0);											// 液晶光标定位到第1行LcdPrintStr("Tmp:            ");		// 液晶第1行显示"Temp:           "
}/*********************************************************/
// ADC0832的时钟脉冲
/*********************************************************/
void WavePlus()
{_nop_();ADC_CLK = 1;_nop_();ADC_CLK = 0;
}/*********************************************************/
// 获取指定通道的A/D转换结果
/*********************************************************/
uchar Get_ADC0832()
{ uchar i;uchar dat1=0;uchar dat2=0;ADC_CLK = 0;				// 电平初始化ADC_DAT = 1;_nop_();ADC_CS = 0;WavePlus();					// 起始信号 ADC_DAT = 1;WavePlus();					// 通道选择的第一位ADC_DAT = 0;      WavePlus();					// 通道选择的第二位ADC_DAT = 1;for(i=0;i<8;i++)		// 第一次读取{dat1<<=1;WavePlus();if(ADC_DAT)dat1=dat1|0x01;elsedat1=dat1|0x00;}for(i=0;i<8;i++)		// 第二次读取{dat2>>= 1;if(ADC_DAT)dat2=dat2|0x80;elsedat2=dat2|0x00;WavePlus();}_nop_();						// 结束此次传输ADC_DAT = 1;ADC_CLK = 1;ADC_CS  = 1;   if(dat1==dat2)			// 返回采集结果return dat1;elsereturn 0;
} /*********************************************************/
// 按键扫描
/*********************************************************/
void KeyScanf()
{if(Key1_P==0){LcdGotoXY(0,13);LcdWriteCmd(0x0f);		// 显示光标,并闪烁/*****烟雾报警值的设置******************************************------------------------------------------------------------*/DelayMs(10);					// 延时去除按键按下的抖动while(!Key1_P);				// 等待按键释放DelayMs(10);		   		// 延时去除按键松开的抖动while(Key1_P!=0)									// 如果按键1按下,那么跳到下一级设置,否则是烟雾报警值的大小设置{if(Key2_P==0)										// 如果减按键被按下	{if(gMqAlarm>1)								// 只有gMqAlarm大于1才能减1								gMqAlarm--;				LcdGotoXY(0,11);							// 液晶光标定位到第0行第11列LcdPrintNum1(gMqAlarm);				// 刷新改变后的报警值LcdGotoXY(0,13);DelayMs(250);									// 延时一下}if(Key3_P==0)										// 如果加按键被按下	{if(gMqAlarm<100)							// 只有gMqAlarm小于100才能加1gMqAlarm++;				LcdGotoXY(0,11);							// 液晶光标定位到第0行第11列LcdPrintNum1(gMqAlarm);				// 刷新改变后的报警值LcdGotoXY(0,13);DelayMs(250);									// 延时一下}}/*****温度报警值设置******************************************------------------------------------------------------------*/LcdGotoXY(1,13);			// 光标定位DelayMs(10);					// 延时去除按键按下的抖动while(!Key1_P);				// 等待按键释放DelayMs(10);		   		// 延时去除按键松开的抖动while(Key1_P!=0)						// 如果按键1按下,则退出设置模式,否则是温度报警值的大小设置{if(Key2_P==0)										// 如果减按键被按下	{if(gTempAlarm>-54)						// 只有gTempAlarm大于-54才能减1								gTempAlarm--;				LcdGotoXY(1,11);							// 液晶光标定位到第1行第11列LcdPrintNum2(gTempAlarm);			// 刷新改变后的报警值LcdGotoXY(1,13);DelayMs(250);									// 延时一下}if(Key3_P==0)										// 如果加按键被按下	{if(gTempAlarm<125)						// 只有gTempAlarm小于125才能加1gTempAlarm++;				LcdGotoXY(1,11);							// 液晶光标定位到第0行第11列LcdPrintNum2(gTempAlarm);			// 刷新改变后的报警值LcdGotoXY(1,13);DelayMs(250);									// 延时一下}				}/*****退出报警值的设置******************************************------------------------------------------------------------*/DelayMs(10);					// 延时去除按键按下的抖动while(!Key1_P);				// 等待按键释放DelayMs(10);		   		// 延时去除按键松开的抖动Sector_Erase(0x2000);										// 擦除单片机内部EEPROM的数据EEPROM_Write(0x2000,gMqAlarm);					// 将新设置的烟雾报警值写入EEPROM的0x2000这个地址EEPROM_Write(0x2001,gTempAlarm+55);			// 将新设置的温度报警值+55写入EEPROM的0x2001这个地址LcdWriteCmd(0x0c);											// 关闭光标}
}/*********************************************************/
// 报警判断
/*********************************************************/
void AlarmJudge(uchar dat1, int dat2)
{
/*火焰报警判断*/if(Fire_P==0){DelayMs(50);if(Fire_P==0){Led1_P=0;}}else{Led1_P=1;}/*烟雾报警判断*/if(dat1>gMqAlarm){Led3_P=0;}else{Led3_P=1;}/*温度报警判断*/if(dat2>gTempAlarm){	Led2_P=0;}else{Led2_P=1;}/*蜂鸣器报警判断*/if((Led1_P==0)||(Led2_P==0)||(Led3_P==0))Buzzer_P=0;elseBuzzer_P=1;
}

硬件设计

使用元器件:

单片机:STC89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

单片机座子;12M晶振;

30pF独石电容;电解电容10uF;

电阻1K;电阻4.7K;电阻10K;

排阻10K;轻触开关;

1602液晶;1602液晶座子;

10K电位器;ADC0832;

ADC0832座子;红led;

MQ-2;MQ-2座子;

有源蜂鸣器;9*15洞洞板;

S8550(PNP)三极管;

电源开关;电源座;

温度传感器DS18B20;

温度传感器座子;

火焰传感器;

3Pin 排针;3Pin 杜邦线;

导线:若干;

流程图:

设计资料

01 仿真图

本设计使用proteus7.8和proteus8.9两个版本设计,向下兼容,无需担心!具体如图!

02 原理图

本系统原理图采用Altium Designer19设计,具体如图!

03 程序

本设计使用软件keil4和keil5两个版本编程设计,无需担心!具体如图!

04 设计报告

两万一千字设计报告,具体如下!

05 设计资料

        资料获取请关注同名公众号,全部资料包括仿真源文件 、程序(含注释)、AD原理图、参考论文、流程图元件清单等。具体内容如下,全网最全! !

资料获取请观看前面演示视频!

点赞分享一起学习成长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/301183.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux中shell脚本的学习第一天,编写脚本的规范,脚本注释、变量,特殊变量的使用等,包含面试题

4月7日没参加体侧的我自学shell的第一天 Shebang 计算机程序中&#xff0c;shebang指的是出现在文本文件的第一行前两个字符 #&#xff01; 1)以#!/bin/sh 开头的文件&#xff0c;程序在执行的时候会调用/bin/sh, 也就是bash解释器 2)以#!/usr/bin/python 开头的文件&#…

动态代理

动态代理 动态代理和静态代理角色一致。 代理类是动态生成的,不是我们直接写好的。 动态代理分为俩大类:基于接口的动态代理、基于类的动态代理 基于接口:JDK动态代理(以下示例就是这个) 基于类:cglib java字节码实现:javasist JDK动态代理 InvocationHandler Proxy …

记一次Cannot deploy POJO class [xxx$$EnhancerBySpringCGLIB$$xxx]的错误

最近项目上需要使用websocket做服务端&#xff0c;那好说啊&#xff0c;直接springboot集成的websocket 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><versi…

Qt 实现简易的视频播放器,功能选择视频,播放,暂停,前进,后退,进度条拖拉,视频时长显示

1.效果图 2.代码实现 2.1 .pro文件 QT core gui multimedia multimediawidgets 2.2 .h文件 #ifndef VIDEOPLAYING_H #define VIDEOPLAYING_H#include <QWidget> #include<QFileDialog>#include<QMediaPlayer> #include<QMediaRecorder> #in…

第十四届蓝桥杯C/C++大学B组题解(一)

1、日期统计 #include <bits/stdc.h> using namespace std; int main() {int array[100] {5, 6, 8, 6, 9, 1, 6, 1, 2, 4, 9, 1, 9, 8, 2, 3, 6, 4, 7, 7,5, 9, 5, 0, 3, 8, 7, 5, 8, 1, 5, 8, 6, 1, 8, 3, 0, 3, 7, 9,2, 7, 0, 5, 8, 8, 5, 7, 0, 9, 9, 1, 9, 4, 4, 6,…

manga-ocr漫画日文ocr

github 下载 解压 anaconda新建环境 conda create -n manga_ocr python3.8 激活环境 conda activate manga_ocr cd到解压目录 cd /d manga-ocr-master 安装依赖包 pip install -r requirements.txt pip3 install manga-ocr 下载离线model huggingface 123云盘 解压到一个目录…

实践笔记-03 docker buildx 使用

docker buildx 使用 1.启用docker buildx2.启用 binfmt_misc3.从默认的构建器切换到多平台构建器3.1创建buildkitd.toml文件&#xff08;私有仓库是http没有证书的情况下&#xff0c;需要配置&#xff09;3.2创建构建器并使用新创建的构建器 4.构建多架构镜像并推送至harbor仓库…

在虚拟机尝试一次用启动盘重装系统

在虚拟机尝试一次用启动盘重装系统 没有自己重装过系统&#xff0c;也不敢对自己的笔记本下手&#xff0c;用虚拟机重装玩玩试试。 先设置成u盘启动 从boot中选择相应的创建的硬盘即可&#xff08;刚刚突然发现图片不能上传了&#xff0c;经过乱七八糟的尝试后&#xff0c;开一…

管廊ar实景可视化巡检提升安全性

在科技日新月异的今天&#xff0c;智慧工地ar远程巡检交互系统应运而生&#xff0c;它是ar开发公司深圳华锐视点综合运用了AR增强现实、5G通信、人工智能、物联网以及GPS北斗定位等前沿技术&#xff0c;为企业打造了一套全新的数字化巡检解决方案。不仅解放了巡检人员的双手&am…

学习周报:文献阅读+Fluent案例+水力学理论学习

目录 摘要 Abstract 文献阅读&#xff1a;物理信息的神经网络与湍流传质的非封闭机制模型相结合 文献摘要 提出问题 提出方案 实验设置 所需方程介绍 雷诺时均方程&#xff08;RANS&#xff09; K-epsilon两方程模型 神经网络框架 DNN部分 损失函数定义 PINN部分…

笔记 | 编译原理L1

重点关注过程式程序设计语言编译程序的构造原理和技术 1 程序设计语言 1.1 依据不同范型 过程式(Procedural programming languages–imperative)函数式(Functional programming languages–declarative)逻辑式(Logical programming languages–declarative)对象式(Object-or…

C语言——顺序表

文章目录 一、线性表二、顺序表顺序表和数组的区别顺序表的分类1.静态顺序表2.动态顺序表 三、动态顺序表的实现1.动态顺序表头文件2.动态顺序表源文件3.测试源文件 一、线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。线性表是⼀种…

在Excel中把打印内容打印在一页上的5种方法,总有一种适合你

序言 如果你经常通过在Microsoft Excel中打印不必要的单元格区域而用完打印机纸张,那么可以按照本Excel教程中提到的经过尝试和测试的方法,学习如何在一页上打印Excel工作表。 由于Excel工作表不像Microsoft Word那样显示单页布局,因此在打印这些电子表格时,你经常会感到…

HBuilder开发者必备!Windows上传IPA文件的软件分享

摘要&#xff1a;HBuilder是目前市场上最受欢迎的移动应用开发框架&#xff0c;但是我们很多人在使用的时候&#xff0c;由于没有mac电脑&#xff0c;无法使用xcode或者application loader上传ipa文件到App Store。本篇博客介绍了一种通过网页平台上传ipa文件的方法&#xff0c…

蓝桥杯 经验技巧篇

1. 注意事项 &#x1f468;‍&#x1f3eb; 官方通知 &#x1f468;‍&#x1f3eb; 资料文档 时间&#xff1a;4月13日 9:00~13:00 &#xff08;时长 4小时&#xff09;物品 准考证&#xff08;赛前一周开放下载&#xff0c;自行打印&#xff09;学生证身份证笔、水、外套&a…

Java学习之原子性操作(Atomic)

CAS&#xff08;compare and swap&#xff09;&#xff1a; public static void main(String[] args) throws InterruptedException {// AtomicInteger是一个提供原子操作的Integer类&#xff0c;通过CAS思想实现AtomicInteger a new AtomicInteger(0);System.out.println(a.…

KnowLog:基于知识增强的日志预训练语言模型|顶会ICSE 2024论文

徐波 东华大学副教授 东华大学计算机学院信息技术系副系主任&#xff0c;复旦大学知识工场实验室副主任&#xff0c;智能运维方向负责人。入选“上海市青年科技英才扬帆计划”。研究成果发表在IJCAI、ICDE、ICSE、ISSRE、ICWS、CIKM、COLING等国际会议上&#xff0c;曾获中国数…

MySQL的基本查询

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;MySQL &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容介绍了mysql的基本查询部分的知识&#xff0c;包括Crea…

记录一次官网访问很慢的情况

客户查看云监控,带宽未超限,客户取的是1分钟的原生值,也就是1分钟也是个平均值。 但是客户的原始值&#xff0c;其实就是1分钟内的平均值。所以客户的瞬时超限&#xff0c;其实是看不出来的。但是后端同事从实时监控里面可以看到超限的情况。 客户升带宽后&#xff0c; 发现还…

【InternLM 实战营第二期笔记】使用茴香豆搭建你的RAG智能助理

RAG RAG是什么 RAG&#xff08;Retrieval Augmented Generation&#xff09;技术&#xff0c;通过检索与用户输入相关的信息片段&#xff0c;并结合外部知识库来生成更准确、更丰富的回答。解决 LLMs 在处理知识密集型任务时可能遇到的挑战, 如幻觉、知识过时和缺乏透明、可追…