找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7808|回复: 7
收起左侧

单片机火灾报警器电路及程序设计 温度和气体检测

  [复制链接]
ID:243469 发表于 2017-10-27 17:02 | 显示全部楼层 |阅读模式
51单片机的火灾报警器课设,温度和气体检测
电路原理图:
0.png

主程序流程图
0.png 0.png

单片机源程序如下:
  1. //程序头函数
  2. #include <reg52.h>
  3. //宏定义
  4. #define uint unsigned int
  5. #define uchar unsigned char
  6. //显示函数
  7. #include <display.h>        //显示函数display.h在工程里        也可鼠标选中左边右键open document <display.h>
  8. #include <intrins.h>
  9. #include "eeprom52.h"

  10. #define Data_ADC0809 P1                 //定义P1口为Data_ADC0809 (之后的程序里Data_ADC0809即代表P1口)

  11. //管脚声明
  12. sbit LED_wendu= P2^2;                 //温度报警灯
  13. sbit LED_yanwu= P2^1;                 //烟雾报警灯
  14. sbit baojing= P2^5;                         //蜂鸣器接口
  15. sbit DQ = P2^0;                                 //ds18b20的数据引脚
  16. //ADC0809
  17. sbit ST=P3^3;
  18. sbit EOC=P3^6;
  19. sbit OE=P3^2;
  20. //按键
  21. sbit Key1=P2^6;                                 //设置键
  22. sbit Key2=P2^7;                                 //加按键
  23. sbit Key3=P3^7;                                 //减按键

  24. signed char w;                                     //温度值全局变量
  25. uint c;                                         //温度值全局变量
  26. //酒精含量变量
  27. uchar temp;                                         //用于读取ADC数据
  28. uchar yushe_wendu=5;                 //温度预设值
  29. uchar yushe_yanwu=45;                 //烟雾预设值
  30. //按钮模式|  
  31. uchar Mode=0;                                 //=1是设置温度阀值  =2是设置烟雾阀值

  32. //函数声明
  33. extern uchar ADC0809();
  34. extern void Key();

  35. /*void delay(uint z)                  //延时函数大约延时z ms
  36. {
  37.         uint i,j;
  38.         for(i=0;i<z;i++)
  39.         for(j=0;j<121;j++);
  40. }                 */

  41. /******************把数据保存到单片机内部eeprom中******************/
  42. void write_eeprom()
  43. {
  44.         SectorErase(0x2000);
  45.         byte_write(0x2000, yushe_wendu);
  46.         byte_write(0x2001, yushe_yanwu);
  47.         byte_write(0x2060, a_a);       
  48. }

  49. /******************把数据从单片机内部eeprom中读出来*****************/
  50. void read_eeprom()
  51. {
  52.         yushe_wendu   = byte_read(0x2000);
  53.         yushe_yanwu   = byte_read(0x2001);
  54.         a_a      = byte_read(0x2060);
  55. }

  56. /**************开机自检eeprom初始化*****************/
  57. void init_eeprom()
  58. {
  59.         read_eeprom();                //先读
  60.         if(a_a != 1)                //新的单片机初始单片机内问eeprom
  61.         {
  62.                 yushe_wendu=50;
  63.                 yushe_yanwu=45;
  64.                 a_a = 1;
  65.                 write_eeprom();           //保存数据
  66.         }       
  67. }

  68. /*****延时子程序:该延时主要用于ds18b20延时*****/
  69. void Delay_DS18B20(int num)
  70. {
  71.   while(num--) ;
  72. }
  73. /*****初始化DS18B20*****/
  74. void Init_DS18B20(void)
  75. {
  76.   unsigned char x=0;
  77.   DQ = 1;         //DQ复位
  78.   Delay_DS18B20(8);    //稍做延时
  79.   DQ = 0;         //单片机将DQ拉低
  80.   Delay_DS18B20(80);   //精确延时,大于480us
  81.   DQ = 1;         //拉高总线
  82.   Delay_DS18B20(14);
  83.   x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  84.   Delay_DS18B20(20);
  85. }
  86. /*****读一个字节*****/
  87. unsigned char ReadOneChar(void)
  88. {
  89.   unsigned char i=0;
  90.   unsigned char dat = 0;
  91.   for (i=8;i>0;i--)
  92.   {
  93.     DQ = 0;     // 给脉冲信号
  94.     dat>>=1;
  95.     DQ = 1;     // 给脉冲信号
  96.     if(DQ)
  97.     dat|=0x80;
  98.     Delay_DS18B20(4);
  99.   }
  100.   return(dat);
  101. }
  102. /*****写一个字节*****/
  103. void WriteOneChar(unsigned char dat)
  104. {
  105.   unsigned char i=0;
  106.   for (i=8; i>0; i--)
  107.   {
  108.     DQ = 0;
  109.     DQ = dat&0x01;
  110.     Delay_DS18B20(5);
  111.     DQ = 1;
  112.     dat>>=1;
  113.   }
  114. }
  115. /*****读取温度*****/
  116. unsigned int ReadTemperature(void)
  117. {
  118.   unsigned char a=0;
  119.   unsigned char b=0;
  120.   unsigned int t=0;
  121.   float tt=0;
  122.   Init_DS18B20();
  123.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  124.   WriteOneChar(0x44);  //启动温度转换
  125.   Init_DS18B20();
  126.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  127.   WriteOneChar(0xBE);  //读取温度寄存器
  128.   a=ReadOneChar();     //读低8位
  129.   b=ReadOneChar();    //读高8位
  130.   t=b;
  131.   t<<=8;
  132.   t=t|a;
  133.   tt=t*0.0625;
  134.   t= tt*10+0.5;     //放大10倍输出并四舍五入
  135.   return(t);
  136. }
  137. //=====================================================================================
  138. //=====================================================================================
  139. //=====================================================================================


  140. /*****读取温度*****/
  141. void check_wendu(void)
  142. {
  143.         c=ReadTemperature()-5;                          //获取温度值并减去DS18B20的温漂误差
  144.         if(c<0) c=0;
  145.         if(c>=999) c=999;
  146. }

  147. //ADC0809读取信息
  148. uchar ADC0809()
  149. {
  150.         uchar temp_=0x00;
  151.         //初始化高阻太

  152.         OE=0;
  153.         //转化初始化
  154.         ST=0;
  155.         //开始转换
  156.         ST=1;
  157.         ST=0;
  158.         //外部中断等待AD转换结束
  159.         while(EOC==0)
  160.         //读取转换的AD值
  161.         OE=1;
  162.         temp_=Data_ADC0809;
  163.         OE=0;
  164.         return temp_;
  165. }

  166. void Key()
  167. {
  168.         //模式选择
  169.         if(Key1==0)          //设置按键
  170.         {
  171.                 while(Key1==0);
  172.                 if(Mode>=3) Mode=0;
  173.                 else
  174.                 {
  175. //                           write_com(0x38);//屏幕初始化
  176.                            write_com(0x0f);//打开显示 无光标 光标闪烁
  177. //                           write_com(0x06);//当读或写一个字符是指针后一一位
  178.                         Mode++;                        //模式加一
  179.                         switch(Mode)        //判断模式的值
  180.                         {
  181.                                 case 1:
  182.                                 {
  183.                                         write_com(0x80+7);//为1时 温度阀值的位置闪烁
  184.                                         break;                          //执行后跳出switch
  185.                                 }
  186.                                 case 2:
  187.                                 {
  188.                                         write_com(0x80+15);//为2时 烟雾阀值的位置闪烁
  189.                                         break;
  190.                                 }
  191.                                 case 3:                                        //当模式加到3时
  192.                                 {
  193. //                                        write_com(0x38);//屏幕初始化
  194.                                         write_com(0x0c);//打开显示 无光标 无光标闪烁
  195.                                         Mode=0;                        //模式清零
  196.                                         break;
  197.                                 }
  198.                         }
  199.                 }
  200.         }
  201.         if(Key2==0&&Mode!=0)         //加按键只有在模式不等于0时有效
  202.         {
  203.                 while(Key2==0);
  204.                 switch(Mode)                 //加按键按下时 判断当前模式
  205.                 {
  206.                         case 1:                         //模式为1时
  207.                         {
  208.                                 yushe_wendu++;                                         //预设温度值(阀值)加1
  209.                                 if(yushe_wendu>=99)                                 //当阀值加到大于等于99时
  210.                                 yushe_wendu=99;                                         //阀值固定为99
  211.                                 write_com(0x80+6);                                 //选中阀值在1602上显示的位置
  212.                                 write_data(0x30+yushe_wendu/10); //将阀值数据分解开送入液晶显示
  213.                                 write_data(0x30+yushe_wendu%10);
  214.                                 write_com(0x80+7);
  215.                                 write_eeprom();                           //保存数据
  216.                                 break;
  217.                         }
  218.                         case 2:
  219.                         {
  220.                                 yushe_yanwu++;                                           //同温度阀值设置
  221.                                 if(yushe_yanwu>=255)
  222.                                 yushe_yanwu=255;
  223.                                 write_com(0x80+13);
  224.                                 write_data(0x30+yushe_yanwu/100);
  225.                                 write_data(0x30+yushe_yanwu%100/10);
  226.                                 write_data(0x30+yushe_yanwu%10);
  227.                                 write_com(0x80+15);
  228.                                 write_eeprom();                           //保存数据
  229.                                 break;                               
  230.                         }
  231.                 }
  232.         }
  233.         if(Key3==0&&Mode!=0)
  234.         {
  235.                 while(Key3==0);
  236.                 switch(Mode)
  237.                 {
  238.                         case 1:
  239.                         {
  240.                                 yushe_wendu--;                                                   //同上
  241.                                 if(yushe_wendu<=0)
  242.                                 yushe_wendu=0;
  243.                                 write_com(0x80+6);
  244.                                 write_data(0x30+yushe_wendu/10);
  245.                                 write_data(0x30+yushe_wendu%10);
  246.                                 write_com(0x80+7);
  247.                                 write_eeprom();                           //保存数据
  248.                                 break;
  249.                         }
  250.                         case 2:
  251.                         {
  252.                                 yushe_yanwu--;                                                          //同上
  253.                                 if(yushe_yanwu<=0)
  254.                                 yushe_yanwu=0;
  255.                                 write_com(0x80+13);
  256.                                 write_data(0x30+yushe_yanwu/100);
  257.                                 write_data(0x30+yushe_yanwu%100/10);
  258.                                 write_data(0x30+yushe_yanwu%10);
  259.                                 write_com(0x80+15);
  260.                                 write_eeprom();                           //保存数据
  261.                                 break;                               
  262.                         }
  263.                 }
  264.         }
  265. //        delay(200);                                                                                           //延时
  266. //        write_com(0x38);//屏幕初始化
  267. //        write_com(0x0c);//打开显示 无光标 无光标闪烁
  268. }
  269. /*****主函数*****/
  270. void main()
  271. {
  272.         check_wendu();                  //初始化时调用温度读取函数 防止开机85°C
  273.         check_wendu();
  274.         init_eeprom();  //开始初始化保存的数据
  275.         Init1602();                          //调用初始化显示函数
  276.         while(1)                          //进入循环
  277.         {
  278.                 temp=ADC0809();          //读取烟雾值
  279.                 check_wendu();          //读取温度值
  280.                 Key();                          //调用按键函数  扫描按键

  281.                 if(Mode==0)                  //只有当模式为0时才会执行以下的阀值判断部分
  282.                 {
  283.                         Display_1602(yushe_wendu,yushe_yanwu,c,temp);  //显示预设温度,预设烟雾,温度值,烟雾值
  284.                         if(temp>=yushe_yanwu)          //烟雾值大于等于预设值时
  285.                         {
  286.                                 LED_yanwu=0;                  //烟雾指示灯亮
  287.                                 baojing=0;                          //蜂鸣器报警
  288.                         }
  289.                         else                                          //烟雾值小于预设值时
  290.                         {
  291.                                 LED_yanwu=1;                  //关掉报警灯
  292.                         }
  293.                         if(c>=(yushe_wendu*10))          //温度大于等于预设温度值时(为什么是大于预设值*10:因为我们要显示的温度是有小数点后一位,是一个3位数,25.9°C时实际读的数是259,所以判断预设值时将预设值*10)
  294.                         {
  295.                                 baojing=0;                          //打开蜂鸣器报警
  296.                                 LED_wendu=0;                  //打开温度报警灯
  297.                         }
  298.                         else                                          //温度值小于预设值时
  299.                         {
  300.                                 LED_wendu=1;                  //关闭报警灯
  301.                         }
  302.                         if((temp<yushe_yanwu)&&(c<(yushe_wendu*10)))          //当烟雾小于预设值并且温度也小于预设值时 (&&:逻辑与,左右两边的表达式都成立(都为真,也就是1)时,该if语句才成立)
  303.                         {
  304.                                 baojing=1;                          //停止报警
  305.                         }
  306.                 …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

0.png

所有资料51hei提供下载:
1-c程序 注释.rar (279.68 KB, 下载次数: 291)
回复

使用道具 举报

ID:229527 发表于 2017-11-16 10:00 | 显示全部楼层
很强势 谢谢了
回复

使用道具 举报

ID:250360 发表于 2017-11-17 12:19 | 显示全部楼层
好东西 谢谢了
回复

使用道具 举报

ID:351978 发表于 2018-6-20 15:21 | 显示全部楼层
因为我们要显示的温度是有小数点后一位,是一个3位数,25.9°C时实际读的数是259,所以判断预设值时将预设值*10
回复

使用道具 举报

ID:204228 发表于 2018-9-30 10:51 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:413568 发表于 2018-11-14 19:41 | 显示全部楼层
挺好的
回复

使用道具 举报

ID:445343 发表于 2018-12-13 21:16 | 显示全部楼层
怎么没有dsk文件啊
回复

使用道具 举报

ID:306995 发表于 2019-3-13 17:28 | 显示全部楼层
请问如果要加水泵和风扇怎么操作呀
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表