找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2254|回复: 1
打印 上一主题 下一主题
收起左侧

基于89C52RC单片机烟雾加温度加火焰程序

[复制链接]
跳转到指定楼层
楼主
ID:258823 发表于 2017-12-20 23:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
基于89C52RC单片机烟雾加温度加火焰的程序是我在制作传感器课题设计时留下的宝贵资料

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char                // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int                // 以后unsigned int 就可以用uint 代替

  5. sfr ISP_DATA  = 0xe2;                        // 数据寄存器
  6. sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;                        // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;                        // 命令触发寄存器
  10. sfr ISP_CONTR = 0xe7;                        // 命令寄存器

  11. sbit Fire_P   = P1^0;                        // 火焰传感器引脚
  12. sbit DQ       = P1^1;                        // 温度传感器的引脚
  13. sbit ADC_CS   = P1^2;                         // ADC0832的CS引脚
  14. sbit ADC_CLK  = P1^3;                         // ADC0832的CLK引脚
  15. sbit ADC_DAT  = P1^4;                 // ADC0832的DI/DO引脚
  16. sbit LcdRs_P  = P2^7;                     // 1602液晶的RS管脚      
  17. sbit LcdRw_P  = P2^6;                     // 1602液晶的RW管脚
  18. sbit LcdEn_P  = P2^5;                     // 1602液晶的EN管脚
  19. sbit Key1_P   = P3^2;                        // 设置按键
  20. sbit Key2_P   = P3^3;                        // 减按键
  21. sbit Key3_P   = P3^4;                        // 加按键
  22. sbit Buzzer_P = P2^0;                        // 蜂鸣器
  23. sbit Led1_P   = P2^3;                        // 报警灯1,火焰报警
  24. sbit Led2_P   = P2^2;                        // 报警灯2,温度报警
  25. sbit Led3_P   = P2^1;                        // 报警灯3,烟雾报警

  26. uchar gMqAlarm;                                // 烟雾报警值
  27. int   gTempAlarm;                                // 温度报警值

  28. /*********************************************************/
  29. // 单片机内部EEPROM不使能
  30. /*********************************************************/
  31. void ISP_Disable()
  32. {
  33.         ISP_CONTR = 0;
  34.         ISP_ADDRH = 0;
  35.         ISP_ADDRL = 0;
  36. }

  37. /*********************************************************/
  38. // 从单片机内部EEPROM读一个字节,从0x2000地址开始
  39. /*********************************************************/
  40. unsigned char EEPROM_Read(unsigned int add)
  41. {
  42.         ISP_DATA  = 0x00;
  43.         ISP_CONTR = 0x83;
  44.         ISP_CMD   = 0x01;
  45.         ISP_ADDRH = (unsigned char)(add>>8);
  46.         ISP_ADDRL = (unsigned char)(add&0xff);
  47.         // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
  48.         ISP_TRIG  = 0x46;          
  49.         ISP_TRIG  = 0xB9;
  50.         _nop_();
  51.         ISP_Disable();
  52.         return (ISP_DATA);
  53. }

  54. /*********************************************************/
  55. // 往单片机内部EEPROM写一个字节,从0x2000地址开始
  56. /*********************************************************/
  57. void EEPROM_Write(unsigned int add,unsigned char ch)
  58. {
  59.         ISP_CONTR = 0x83;
  60.         ISP_CMD   = 0x02;
  61.         ISP_ADDRH = (unsigned char)(add>>8);
  62.         ISP_ADDRL = (unsigned char)(add&0xff);
  63.         ISP_DATA  = ch;
  64.         ISP_TRIG  = 0x46;
  65.         ISP_TRIG  = 0xB9;
  66.         _nop_();
  67.         ISP_Disable();
  68. }

  69. /*********************************************************/
  70. // 擦除单片机内部EEPROM的一个扇区
  71. // 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
  72. /*********************************************************/
  73. void Sector_Erase(unsigned int add)          
  74. {
  75.         ISP_CONTR = 0x83;
  76.         ISP_CMD   = 0x03;
  77.         ISP_ADDRH = (unsigned char)(add>>8);
  78.         ISP_ADDRL = (unsigned char)(add&0xff);
  79.         ISP_TRIG  = 0x46;
  80.         ISP_TRIG  = 0xB9;
  81.         _nop_();
  82.         ISP_Disable();
  83. }

  84. /*********************************************************/
  85. // 毫秒级的延时函数,time是要延时的毫秒数
  86. /*********************************************************/
  87. void DelayMs(uint time)
  88. {
  89.         uint i,j;
  90.         for(i=0;i<time;i++)
  91.                 for(j=0;j<112;j++);
  92. }

  93. /*********************************************************/
  94. // 延时15微秒
  95. /*********************************************************/
  96. void Delay15us(void)
  97. {
  98.         _nop_();
  99.         _nop_();
  100.         _nop_();
  101.         _nop_();
  102.         _nop_();
  103.         _nop_();
  104.         _nop_();
  105.         _nop_();
  106.         _nop_();
  107.         _nop_();
  108.         _nop_();
  109.         _nop_();
  110.         _nop_();
  111.         _nop_();
  112.         _nop_();
  113. }

  114. /*********************************************************/
  115. // 复位DS18B20(初始化)
  116. /*********************************************************/
  117. void DS18B20_ReSet(void)
  118. {
  119.         uchar i;
  120.         DQ=0;
  121.         i=240;
  122.         while(--i);
  123.         DQ=1;
  124.         i=30;
  125.         while(--i);
  126.         while(~DQ);
  127.         i=4;
  128.         while(--i);
  129. }

  130. /*********************************************************/
  131. // 向DS18B20写入一个字节
  132. /*********************************************************/
  133. void DS18B20_WriteByte(uchar dat)
  134. {
  135.         uchar j;
  136.         uchar btmp;
  137.         for(j=0;j<8;j++)
  138.         {
  139.                 btmp=0x01;
  140.                 btmp=btmp<<j;
  141.                 btmp=btmp&dat;
  142.                
  143.                 if(btmp>0)                // 写1
  144.                 {
  145.                         DQ=0;
  146.                         Delay15us();
  147.                         DQ=1;
  148.                         Delay15us();
  149.                         Delay15us();
  150.                         Delay15us();
  151.                         Delay15us();
  152.                 }
  153.                 else                        // 写0
  154.                 {
  155.                         DQ=0;
  156.                         Delay15us();
  157.                         Delay15us();
  158.                         Delay15us();
  159.                         Delay15us();
  160.                         DQ=1;
  161.                         Delay15us();
  162.                 }
  163.         }
  164. }

  165. /*********************************************************/
  166. // 读取温度值
  167. /*********************************************************/
  168. int DS18B20_ReadTemp(void)
  169. {
  170.         uchar j;
  171.         int b,temp=0;       
  172.         DS18B20_ReSet();                                        // 产生复位脉
  173.         DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
  174.         DS18B20_WriteByte(0x44);                        // 启动温度转换指令
  175.         DS18B20_ReSet();                                        // 产生复位脉
  176.         DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
  177.         DS18B20_WriteByte(0xbe);                        // 读取温度指令
  178.         for(j=0;j<16;j++)                                        // 读取温度数量
  179.         {                                               
  180.                 DQ=0;
  181.                 _nop_();
  182.                 _nop_();
  183.                 DQ=1;       
  184.                 Delay15us();
  185.                 b=DQ;
  186.                 Delay15us();
  187.                 Delay15us();
  188.                 Delay15us();
  189.                 b=b<<j;
  190.                 temp=temp|b;
  191.         }
  192.         temp=temp*0.0625;                                // 合成温度值       
  193.         return (temp);                                                // 返回检测到的温度值

  194. }

  195. /*********************************************************/
  196. // 1602液晶写命令函数,cmd就是要写入的命令
  197. /*********************************************************/
  198. void LcdWriteCmd(uchar cmd)
  199. {
  200.         LcdRs_P = 0;
  201.         LcdRw_P = 0;
  202.         LcdEn_P = 0;
  203.         P0=cmd;
  204.         DelayMs(2);
  205.         LcdEn_P = 1;   
  206.         DelayMs(2);
  207.         LcdEn_P = 0;       
  208. }

  209. /*********************************************************/
  210. // 1602液晶写数据函数,dat就是要写入的数据
  211. /*********************************************************/
  212. void LcdWriteData(uchar dat)
  213. {
  214.         LcdRs_P = 1;
  215.         LcdRw_P = 0;
  216.         LcdEn_P = 0;
  217.         P0=dat;
  218.         DelayMs(2);
  219.         LcdEn_P = 1;   
  220.         DelayMs(2);
  221.         LcdEn_P = 0;
  222. }

  223. /*********************************************************/
  224. // 1602液晶初始化函数
  225. /*********************************************************/
  226. void LcdInit()
  227. {
  228.         LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
  229.         LcdWriteCmd(0x0C);        // 开显示,不显示光标
  230.         LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
  231.         LcdWriteCmd(0x01);        // 清屏
  232. }

  233. /*********************************************************/
  234. // 液晶光标定位函数
  235. /*********************************************************/
  236. void LcdGotoXY(uchar line,uchar column)
  237. {
  238.         // 第一行
  239.         if(line==0)        
  240.                 LcdWriteCmd(0x80+column);
  241.          // 第二行
  242.         if(line==1)        
  243.                 LcdWriteCmd(0x80+0x40+column);
  244. }

  245. /*********************************************************/
  246. // 液晶输出字符串函数
  247. /*********************************************************/
  248. void LcdPrintStr(uchar *str)
  249. {
  250.         while(*str!='\0')
  251.                 LcdWriteData(*str++);
  252. }

  253. /*********************************************************/
  254. // 液晶输出数字
  255. /*********************************************************/
  256. void LcdPrintNum1(uchar num)
  257. {
  258.         LcdWriteData(num/100+48);                        // 百位
  259.         LcdWriteData(num%100/10+48);                // 十位
  260.         LcdWriteData(num%10+48);                         // 个位
  261. }

  262. /*********************************************************/
  263. // 温度值的显示
  264. /*********************************************************/
  265. void LcdPrintNum2(int num)
  266. {
  267.         if(num<0)                                                                        // 显示负号
  268.         {
  269.                 LcdWriteData('-');
  270.                 num=0-num;       
  271.         }
  272.         else                                                                    // 显示百位
  273.         {
  274.                 LcdWriteData(num/100+48);
  275.         }
  276.         LcdWriteData(num%100/10+48);                                // 显示十位
  277.         LcdWriteData(num%10+48);                                        // 显示个位

  278. }

  279. /*********************************************************/
  280. // 液晶显示初始化
  281. /*********************************************************/
  282. void LcdShowInit()
  283. {
  284.         LcdGotoXY(0,0);                                        // 液晶光标定位到第0行
  285.         LcdPrintStr("Gas:            ");                // 液晶第0行显示" Gas:           "
  286.         LcdGotoXY(1,0);                                        // 液晶光标定位到第1行
  287.         LcdPrintStr("Tmp:            ");        // 液晶第1行显示"Temp:           "
  288. }

  289. /*********************************************************/
  290. // ADC0832的时钟脉冲
  291. /*********************************************************/
  292. void WavePlus()
  293. {
  294.         _nop_();
  295.         ADC_CLK = 1;
  296.         _nop_();
  297.         ADC_CLK = 0;
  298. }

  299. /*********************************************************/
  300. // 获取指定通道的A/D转换结果
  301. /*********************************************************/
  302. uchar Get_ADC0832()
  303. {
  304.         uchar i;
  305.         uchar dat1=0;
  306.         uchar dat2=0;
  307.         ADC_CLK = 0;                                // 电平初始化
  308.         ADC_DAT = 1;
  309.         _nop_();
  310.         ADC_CS = 0;
  311.         WavePlus();                                // 起始信号
  312.         ADC_DAT = 1;
  313.         WavePlus();                                // 通道选择的第一位
  314.         ADC_DAT = 0;      
  315.         WavePlus();                                // 通道选择的第二位
  316.         ADC_DAT = 1;
  317.         for(i=0;i<8;i++)                        // 第一次读取
  318.         {
  319.                 dat1<<=1;
  320.                 WavePlus();
  321.                 if(ADC_DAT)
  322.                         dat1=dat1|0x01;
  323.                 else
  324.                         dat1=dat1|0x00;
  325.         }
  326.         for(i=0;i<8;i++)                        // 第二次读取
  327.         {
  328.                 dat2>>= 1;
  329.                 if(ADC_DAT)
  330.                         dat2=dat2|0x80;
  331.                 else
  332.                         dat2=dat2|0x00;
  333.                 WavePlus();
  334.         }
  335.         _nop_();                                        // 结束此次传输
  336.         ADC_DAT = 1;
  337.         ADC_CLK = 1;
  338.         ADC_CS  = 1;   
  339.         if(dat1==dat2)                                // 返回采集结果
  340.                 return dat1;
  341.         else
  342.                 return 0;

  343. }

  344. /*********************************************************/
  345. // 按键扫描
  346. /*********************************************************/
  347. void KeyScanf()
  348. {
  349.         if(Key1_P==0)
  350.         {
  351.                 LcdGotoXY(0,13);
  352.                 LcdWriteCmd(0x0f);                                // 显示光标,并闪烁
  353.                
  354.                 /*****烟雾报警值的设置**********************/
  355.                 DelayMs(10);                                                // 延时去除按键按下的抖动
  356.                 while(!Key1_P);                                        // 等待按键释放
  357.                 DelayMs(10);                                                   // 延时去除按键松开的抖动
  358.                
  359.                 while(Key1_P!=0)                                        // 如果按键1按下,那么跳到下一级设置
  360.                 {
  361.                         if(Key2_P==0)                                        // 如果减按键被按下       
  362.                         {
  363.                                 if(gMqAlarm>1)                        // 只有gMqAlarm大于1才能减1               
  364.                                         gMqAlarm--;                               
  365.                                 LcdGotoXY(0,11);                        // 液晶光标定位到第0行第11列
  366.                                 LcdPrintNum1(gMqAlarm);        // 刷新改变后的报警值
  367.                                 LcdGotoXY(0,13);
  368.                                 DelayMs(250);                                // 延时一下
  369.                         }
  370.                         if(Key3_P==0)                                        // 如果加按键被按下       
  371.                         {
  372.                                 if(gMqAlarm<100)                        // 只有gMqAlarm小于100才能加1
  373.                                         gMqAlarm++;                               
  374.                                 LcdGotoXY(0,11);                        // 液晶光标定位到第0行第11列
  375.                                 LcdPrintNum1(gMqAlarm);        // 刷新改变后的报警值
  376.                                 LcdGotoXY(0,13);
  377.                                 DelayMs(250);                                // 延时一下
  378.                         }
  379.                 }
  380.                
  381.                 /*****温度报警值设置******************/
  382.                 LcdGotoXY(1,13);                                        // 光标定位
  383.                 DelayMs(10);                                                // 延时去除按键按下的抖动
  384.                 while(!Key1_P);                                        // 等待按键释放
  385.                 DelayMs(10);                                                   // 延时去除按键松开的抖动
  386.                 while(Key1_P!=0)                                        // 如果按键1按下,则退出设置模式
  387.                 {
  388.                         if(Key2_P==0)                                        // 如果减按键被按下       
  389.                         {
  390.                                 if(gTempAlarm>-54)                // 只有gTempAlarm大于-54才能减1       
  391.                                         gTempAlarm--;                               
  392.                                 LcdGotoXY(1,11);                        // 液晶光标定位到第1行第11列
  393.                                 LcdPrintNum2(gTempAlarm);        // 刷新改变后的报警值
  394.                                 LcdGotoXY(1,13);
  395.                                 DelayMs(250);                                // 延时一下
  396.                         }
  397.                         if(Key3_P==0)                                        // 如果加按键被按下       
  398.                         {
  399.                                 if(gTempAlarm<125)                // 只有gTempAlarm小于125才能加1
  400.                                         gTempAlarm++;                               
  401.                                 LcdGotoXY(1,11);                        // 液晶光标定位到第0行第11列
  402.                                 LcdPrintNum2(gTempAlarm);        // 刷新改变后的报警值
  403.                                 LcdGotoXY(1,13);
  404.                                 DelayMs(250);                                // 延时一下
  405.                         }                               
  406.                 }
  407.                
  408.                 /*****退出报警值的设置***************/
  409.                 DelayMs(10);                                                // 延时去除按键按下的抖动
  410.                 while(!Key1_P);                                        // 等待按键释放
  411.                 DelayMs(10);                                                   // 延时去除按键松开的抖动
  412.                
  413.                 Sector_Erase(0x2000);                                // 擦除单片机内部EEPROM的数据
  414.                 EEPROM_Write(0x2000,gMqAlarm);                // 将新设置的烟雾报警值写入EEPROM
  415.                 EEPROM_Write(0x2001,gTempAlarm+55);        // 将新设置的温度报警值+55写入
  416.                 LcdWriteCmd(0x0c);                                        // 关闭光标
  417.         }
  418. }

  419. /*********************************************************/
  420. // 报警判断
  421. /*********************************************************/
  422. void AlarmJudge(uchar dat1, int dat2)
  423. {
  424. /*火焰报警判断*/
  425.         if(Fire_P==0)
  426.         {
  427.                 DelayMs(50);
  428.                 if(Fire_P==0)
  429.                 {
  430.                         Led1_P=0;
  431.                 }
  432.         }
  433.         else
  434.         {
  435.                 Led1_P=1;
  436.         }
  437.        
  438.         /*烟雾报警判断*/
  439.         if(dat1>gMqAlarm)
  440.         {
  441.                 Led3_P=0;
  442.         }
  443.         else
  444.         {
  445.                 Led3_P=1;
  446.         }
  447.        
  448.         /*温度报警判断*/
  449.         if(dat2>gTempAlarm)
  450.         {       
  451.                 Led2_P=0;
  452.         }
  453.         else
  454.         {
  455.                 Led2_P=1;
  456.         }

  457.         /*蜂鸣器报警判断*/
  458.         if((Led1_P==0)||(Led2_P==0)||(Led3_P==0))
  459.                 Buzzer_P=0;
  460.         else
  461.                 Buzzer_P=1;
  462. }

  463. ……………………

  464. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
单片机程序.doc (64.5 KB, 下载次数: 27)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:561672 发表于 2019-12-13 13:43 | 只看该作者
有没有程序流程图  大神
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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