找回密码
 立即注册

QQ登录

只需一步,快速开始

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

MQ-7一氧化碳传感器检测如何加入到这个单片机程序中?

[复制链接]
跳转到指定楼层
楼主
100黑币
目前能实现的功能是显示温湿度 然后按键能设置上下限并报警。
求个大佬修改一下 把MQ-7一氧化碳传感器加进去  就是在第一页Temp&Humi那里显示CO浓度  然后能设置CO上限      感激不尽。

求分享一个检测温湿度与CO浓度并报警的程序

单片机源程序如下:
  1. #include <reg52.h>                                   // 头文件包含
  2. #include <intrins.h>

  3. #define uchar unsigned char        
  4. #define uint  unsigned int        

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

  11. sbit Buzzer_P  = P1^0;    // 蜂鸣器
  12. sbit DHT11_P   = P1^1;                 // 温湿度传感器DHT11数据接入
  13. sbit LcdRs_P   = P2^5;    // 1602液晶的RS管脚      
  14. sbit LcdRw_P   = P2^6;    // 1602液晶的RW管脚
  15. sbit LcdEn_P   = P2^7;    // 1602液晶的EN管脚
  16. sbit KeySet_P  = P1^2;                // “设置”按键的管脚
  17. sbit KeyDown_P = P1^4;                // “减”按键的管脚
  18. sbit KeyUp_P   = P1^3;                // “加”按键的管脚
  19. sbit LedL  = P1^5;                // 过低报警指示灯
  20. sbit LedH  = P1^6;                // 过高报警指示灯


  21. uchar temp;                                        // 保存温度
  22. uchar humi;                                        // 保存湿度

  23. uchar AlarmTL;                        // 温度下限报警值
  24. uchar AlarmTH;                        // 温度上限报警值
  25. uchar AlarmHL;                        // 湿度下限报警值
  26. uchar AlarmHH;                        // 湿度上限报警值



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


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


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


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


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


  92. /*********************************************************/
  93. // 1602液晶写命令函数,cmd就是要写入的命令
  94. /*********************************************************/
  95. void LcdWriteCmd(uchar cmd)
  96. {
  97.         LcdRs_P = 0;
  98.         LcdRw_P = 0;
  99.         LcdEn_P = 0;
  100.         P0=cmd;
  101.         DelayMs(2);
  102.         LcdEn_P = 1;   
  103.         DelayMs(2);
  104.         LcdEn_P = 0;        
  105. }


  106. /*********************************************************/
  107. // 1602液晶写数据函数,dat就是要写入的数据
  108. /*********************************************************/
  109. void LcdWriteData(uchar dat)
  110. {
  111.         LcdRs_P = 1;
  112.         LcdRw_P = 0;
  113.         LcdEn_P = 0;
  114.         P0=dat;
  115.         DelayMs(2);
  116.         LcdEn_P = 1;   
  117.         DelayMs(2);
  118.         LcdEn_P = 0;
  119. }


  120. /*********************************************************/
  121. // 1602液晶初始化函数
  122. /*********************************************************/
  123. void LcdInit()
  124. {
  125.         LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
  126.         LcdWriteCmd(0x0C);        // 开显示,不显示光标
  127.         LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
  128.         LcdWriteCmd(0x01);        // 清屏
  129. }


  130. /*********************************************************/
  131. // 液晶光标定位函数
  132. /*********************************************************/
  133. void LcdGotoXY(uchar line,uchar column)
  134. {
  135.         // 第一行
  136.         if(line==0)        
  137.                 LcdWriteCmd(0x80+column);
  138.         // 第二行
  139.         if(line==1)        
  140.                 LcdWriteCmd(0x80+0x40+column);
  141. }


  142. /*********************************************************/
  143. // 液晶输出字符串函数
  144. /*********************************************************/
  145. void LcdPrintStr(uchar *str)
  146. {
  147.         while(*str!='\0')                         // 判断是否到字符串的尽头了
  148.                 LcdWriteData(*str++);
  149. }


  150. /*********************************************************/
  151. // 液晶输出数字
  152. /*********************************************************/
  153. void LcdPrintNum(uchar num)
  154. {
  155.         LcdWriteData(num/10+48);        // 十位
  156.         LcdWriteData(num%10+48);         // 个位
  157. }


  158. /*********************************************************/
  159. // 液晶显示内容的初始化
  160. /*********************************************************/
  161. void LcdShowInit()
  162. {
  163.         LcdGotoXY(0,0);                                                                // 第0行的显示内容
  164.         LcdPrintStr("   TemPP&HHumi  ");
  165.         LcdGotoXY(1,0);                                                           // 第1行的显示内容
  166.         LcdPrintStr("T:   C     H:    %RH");
  167.         LcdGotoXY(1,4);                                                                // 温度单位摄氏度上面的圆圈符号
  168.         LcdWriteData(0xdf);        
  169. }



  170. /*********************************************************/
  171. // 10us级延时程序
  172. /*********************************************************/
  173. void Delay10us()
  174. {
  175.         _nop_();        // 执行一条指令,延时1微秒
  176.         _nop_();
  177.         _nop_();
  178.         _nop_();
  179.         _nop_();
  180.         _nop_();
  181.         _nop_();
  182.         _nop_();
  183.         _nop_();
  184.         _nop_();
  185. }


  186. /*********************************************************/
  187. // 读取DHT11单总线上的一个字节
  188. /*********************************************************/
  189. uchar DhtReadByte(void)
  190. {   
  191.         bit bit_i;
  192.         uchar j;
  193.         uchar dat=0;

  194.         for(j=0;j<8;j++)   
  195.         {
  196.                 while(!DHT11_P);        // 等待低电平结束        
  197.                 Delay10us();                        // 延时
  198.                 Delay10us();
  199.                 Delay10us();
  200.                 if(DHT11_P==1)                // 判断数据线是高电平还是低电平
  201.                 {
  202.                         bit_i=1;
  203.                         while(DHT11_P);
  204.                 }
  205.                 else
  206.                 {
  207.                         bit_i=0;
  208.                 }
  209.                 dat<<=1;                                   // 将该位移位保存到dat变量中
  210.                 dat|=bit_i;   
  211.         }
  212.         return(dat);  
  213. }


  214. /*********************************************************/
  215. // 读取DHT11的一帧数据,湿高、湿低(0)、温高、温低(0)、校验码
  216. /*********************************************************/
  217. void ReadDhtData()
  218. {            
  219.         uchar HumiHig;                // 湿度高检测值
  220.         uchar HumiLow;                // 湿度低检测值
  221.         uchar TemHig;                        // 温度高检测值
  222.         uchar TemLow;                        // 温度低检测值
  223.         uchar check;                        // 校验字节
  224.         
  225.         DHT11_P=0;                                // 主机拉低
  226.         DelayMs(20);                        // 保持20毫秒
  227.         DHT11_P=1;                                // DATA总线由上拉电阻拉高

  228.         Delay10us();                         // 延时等待30us
  229.         Delay10us();
  230.         Delay10us();

  231.         while(!DHT11_P);        // 等待DHT的低电平结束
  232.         while(DHT11_P);                // 等待DHT的高电平结束

  233.         //进入数据接收状态
  234.         HumiHig = DhtReadByte();         // 湿度高8位
  235.         HumiLow = DhtReadByte();         // 湿度低8为,总为0
  236.         TemHig  = DhtReadByte();         // 温度高8位
  237.         TemLow  = DhtReadByte();         // 温度低8为,总为0
  238.         check   = DhtReadByte();        // 8位校验码,其值等于读出的四个字节相加之和的低8位

  239.         DHT11_P=1;                                // 拉高总线

  240.         if(check==HumiHig + HumiLow + TemHig + TemLow)                 // 如果收到的数据无误
  241.         {
  242.                 temp=TemHig;                         // 将温度的检测结果赋值给全局变量temp
  243.                 humi=HumiHig;                        // 将湿度的检测结果赋值给全局变量humi
  244.         }
  245. }


  246. /*********************************************************/
  247. // 是否需要报警判断
  248. /*********************************************************/

  249. void AlarmJudge(void)    //报警处理
  250. {
  251.         uchar i;

  252.     if(temp>AlarmTH||humi>AlarmHH)     //检测温度或者湿度高于设定上限值 降温湿
  253.     {
  254.         LedH=0;
  255.         LedL=1;
  256.     }
  257.     if(temp<AlarmTL||humi<AlarmHL)    //检测温度或者湿度低于设定下限值  升温湿
  258.     {
  259.         LedH=1;
  260.                 LedL=0;//升高温湿指示灯
  261.     }
  262.     if((temp>=AlarmTL&&temp<=AlarmTH)&&(humi>=AlarmHL&&humi<=AlarmHH))
  263.     {
  264.         LedL=1;
  265.         LedH=1;   
  266.     }
  267.          if((LedH==0)||(LedL==0))         // 蜂鸣器判断,只要至少1个报警灯亮,蜂鸣器就报警
  268.         {
  269.                 for(i=0;i<2;i++)
  270.                 {
  271.                         Buzzer_P=0;
  272.                                                 DelayMs(100);
  273.                         DelayMs(500);
  274.                         Buzzer_P=1;
  275.                         DelayMs(500);
  276.                 }
  277.         }
  278. }

  279. /*********************************************************/
  280. // 按键扫描,用于设置温湿度报警范围
  281. /*********************************************************/
  282. void KeyScanf()
  283. {
  284.         if(KeySet_P==0)                // 判断设置按键是否被按下
  285.         {
  286.                 /*将液晶显示改为设置页面的*******************************************************/

  287.                 LcdWriteCmd(0x01);                                // 设置界面的显示框架
  288.                 LcdGotoXY(0,0);
  289.                 LcdPrintStr("Temp: 20-40");
  290.                 LcdGotoXY(1,0);
  291.                 LcdPrintStr("Humi: 20-30");
  292.                
  293.                 LcdGotoXY(0,6);                                                 // 在液晶上填充温度的下限值        
  294.                 LcdPrintNum(AlarmTL);        
  295.                 LcdGotoXY(0,9);                                                 // 在液晶上填充温度的上限值
  296.                 LcdPrintNum(AlarmTH);

  297.                 LcdGotoXY(1,6);                                                 // 在液晶上填充湿度的下限值
  298.                 LcdPrintNum(AlarmHL);        
  299.                 LcdGotoXY(1,9);                                                  // 在液晶上填充湿度的上限值
  300.                 LcdPrintNum(AlarmHH);

  301.                 LcdGotoXY(0,7);                                                 // 光标定位到第0行第7列
  302.                 LcdWriteCmd(0x0F);                                // 光标闪烁
  303.                
  304.                 DelayMs(10);                                                  // 去除按键按下的抖动
  305.                 while(!KeySet_P);                                         // 等待按键释放
  306.                 DelayMs(10);                                                  // 去除按键松开的抖动

  307.                 /*设置温度的下限值****************************************************************/

  308.                 while(KeySet_P)                                                // “设置键”没有被按下,则一直处于温度下限的设置
  309.                 {
  310.                         if(KeyDown_P==0)                                // 判断 “减按键“ 是否被按下               
  311.                         {
  312.                                 if(AlarmTL>0)                                        // 只有当温度下限值大于0时,才能减1
  313.                                         AlarmTL--;
  314.                                 LcdGotoXY(0,6);                                 // 重新刷新显示更改后的温度下限值        
  315.                                 LcdPrintNum(AlarmTL);                  
  316.                                 LcdGotoXY(0,7);                                // 重新定位闪烁的光标位置
  317.                                 DelayMs(350);                                        // 延时
  318.                         }
  319.                         if(KeyUp_P==0)                                  // 判断 “加按键“ 是否被按下
  320.                         {
  321.                                 if(AlarmTL<99)                          // 只有当温度下限值小于99时,才能加1
  322.                                         AlarmTL++;
  323.                                 LcdGotoXY(0,6);                                  // 重新刷新显示更改后的温度下限值
  324.                                 LcdPrintNum(AlarmTL);
  325.                                 LcdGotoXY(0,7);                                // 重新定位闪烁的光标位置
  326.                                 DelayMs(350);                                        // 延时
  327.                         }        
  328.                 }

  329.                 LcdGotoXY(0,10);
  330.                 DelayMs(10);                                                  // 去除按键按下的抖动
  331.                 while(!KeySet_P);                                         // 等待按键释放
  332.                 DelayMs(10);                                                  // 去除按键松开的抖动

  333.                 /*设置温度的上限值****************************************************************/
  334.                                 
  335.                 while(KeySet_P)                                          // “设置键”没有被按下,则一直处于温度上限的设置
  336.                 {
  337.                         if(KeyDown_P==0)                                // 判断 “减按键“ 是否被按下
  338.                         {
  339.                                 if(AlarmTH>0)                                  // 只有当温度上限值大于0时,才能减1                        
  340.                                         AlarmTH--;
  341.                                 LcdGotoXY(0,9);                           // 重新刷新显示更改后的温度上限值
  342.                                 LcdPrintNum(AlarmTH);
  343.                                 LcdGotoXY(0,10);                        // 重新定位闪烁的光标位置
  344.                                 DelayMs(350);                                        // 延时
  345.                         }
  346.                         if(KeyUp_P==0)                                   // 判断 “加按键“ 是否被按下
  347.                         {
  348.                                 if(AlarmTH<99)                                 // 只有当温度上限值小于99时,才能加1
  349.                                         AlarmTH++;
  350.                                 LcdGotoXY(0,9);                                // 重新刷新显示更改后的温度上限值         
  351.                                 LcdPrintNum(AlarmTH);
  352.                                 LcdGotoXY(0,10);                        // 重新定位闪烁的光标位置
  353.                                 DelayMs(350);                                        // 延时
  354.                         }                                                                 
  355.                 }

  356.                 LcdGotoXY(1,7);
  357.                 DelayMs(10);                                                  // 去除按键按下的抖动
  358.                 while(!KeySet_P);                                         // 等待按键释放
  359.                 DelayMs(10);                                                  // 去除按键松开的抖动
  360.                
  361.                 /*设置湿度的下限值****************************************************************/

  362.                 while(KeySet_P)                                                 // “设置键”没有被按下,则一直处于湿度下限的设置
  363.                 {
  364.                         if(KeyDown_P==0)                                // 判断 “减按键“ 是否被按下
  365.                         {
  366.                                 if(AlarmHL>0)                                         // 只有当湿度下限值大于0时,才能减1
  367.                                         AlarmHL--;
  368.                                 LcdGotoXY(1,6);                                // 重新刷新显示更改后的湿度下限值         
  369.                                 LcdPrintNum(AlarmHL);
  370.                                 LcdGotoXY(1,7);                                // 重新定位闪烁的光标位置
  371.                                 DelayMs(350);
  372.                         }
  373.                         if(KeyUp_P==0)                                         // 判断 “加按键“ 是否被按下
  374.                         {
  375.                                 if(AlarmHL<99)                          // 只有当湿度下限值小于99时,才能加1
  376.                                         AlarmHL++;
  377.                                 LcdGotoXY(1,6);                                  // 重新刷新显示更改后的湿度下限值
  378.                                 LcdPrintNum(AlarmHL);
  379.                                 LcdGotoXY(1,7);                          // 重新定位闪烁的光标位置
  380.                                 DelayMs(350);                                        // 延时
  381.                         }        
  382.                 }

  383.                 LcdGotoXY(1,10);
  384.                 DelayMs(10);                                                  // 去除按键按下的抖动
  385.                 while(!KeySet_P);                                         // 等待按键释放
  386.                 DelayMs(10);                                                  // 去除按键松开的抖动
  387.                
  388.                 /*设置湿度的上限值****************************************************************/

  389.                 while(KeySet_P)                                                 // “设置键”没有被按下,则一直处于湿度上限的设置
  390.                 {
  391.                         if(KeyDown_P==0)                                 // 判断 “减按键“ 是否被按下
  392.                         {
  393.                                 if(AlarmHH>0)                                  // 只有当湿度上限值大于0时,才能减1
  394.                                         AlarmHH--;
  395.                                 LcdGotoXY(1,9);                                  // 重新刷新显示更改后的湿度上限值
  396.                                 LcdPrintNum(AlarmHH);
  397.                                 LcdGotoXY(1,10);                        // 重新定位闪烁的光标位置
  398.                                 DelayMs(350);
  399.                         }
  400.                         if(KeyUp_P==0)                                         // 判断 “加按键“ 是否被按下
  401.                         {
  402.                                 if(AlarmHH<99)                                // 只有当湿度上限值小于99时,才能加1
  403.                                         AlarmHH++;
  404.                                 LcdGotoXY(1,9);                                 // 重新刷新显示更改后的湿度上限值        
  405.                                 LcdPrintNum(AlarmHH);
  406.                                 LcdGotoXY(1,10);                         // 重新定位闪烁的光标位置
  407.                                 DelayMs(350);                                        // 延时
  408.                         }        
  409.                 }

  410.                 LcdWriteCmd(0x0C);                          // 取消光标闪烁
  411.                 LcdShowInit();                                                // 液晶显示为检测界面的

  412.                 DelayMs(10);                                                  // 去除按键按下的抖动
  413.                 while(!KeySet_P);                                         // 等待按键释放
  414.                 DelayMs(10);                                                  // 去除按键松开的抖动

  415.                 Sector_Erase(0x2000);                                                 // 存储之前必须先擦除
  416.                 EEPROM_Write(0x2000,AlarmTL);                // 把温度下限存入到EEPROM的0x2000这个地址
  417.                 EEPROM_Write(0x2001,AlarmTH);                // 把温度上限存入到EEPROM的0x2001这个地址
  418.                 EEPROM_Write(0x2002,AlarmHL);                // 把湿度下限存入到EEPROM的0x2002这个地址
  419.                 EEPROM_Write(0x2003,AlarmHH);                // 把湿度上限存入到EEPROM的0x2003这个地址
  420.         }        
  421. }


  422. /*********************************************************/
  423. // 主函数
  424. /*********************************************************/
  425. void main()
  426. {
  427.         uchar i;

  428.         LcdInit();                                                        // 液晶功能的初始化                        
  429.         LcdShowInit();                                         // 液晶显示的初始化

  430.         AlarmTL=EEPROM_Read(0x2000);        // 从EEPROM的0x2000这个地址读取温度的报警下限
  431.         AlarmTH=EEPROM_Read(0x2001);        // 从EEPROM的0x2001这个地址读取温度的报警上限
  432.         AlarmHL=EEPROM_Read(0x2002);        // 从EEPROM的0x2002这个地址读取湿度的报警下限        
  433.         AlarmHH=EEPROM_Read(0x2003);        // 从EEPROM的0x2003这个地址读取湿度的报警上限

  434.         if((AlarmTL==0)||(AlarmTL>100))        // 如果温度下限报警值读出来异常(等于0或大于100),则重新赋值
  435.                 AlarmTL=20;
  436.         if((AlarmTH==0)||(AlarmTH>100))        // 如果温度上限报警值读出来异常(等于0或大于100),则重新赋值
  437.                 AlarmTH=28;
  438.         if((AlarmHL==0)||(AlarmHL>100))        // 如果温度下限报警值读出来异常(等于0或大于100),则重新赋值
  439.                 AlarmHL=40;
  440.         if((AlarmHH==0)||(AlarmHH>100))        // 如果温度上限报警值读出来异常(等于0或大于100),则重新赋值
  441.                 AlarmHH=70;
  442.                
  443.         
  444.         while(1)
  445.         {
  446.                 ReadDhtData();                                 // 检测温湿度数据

  447.                 LcdGotoXY(1,2);                                 // 定位到要显示温度的地方
  448.                 LcdPrintNum(temp);                // 显示温度值
  449.                 LcdGotoXY(1,11);                        // 定位到要显示湿度的地方
  450.                 LcdPrintNum(humi);                // 显示湿度值
  451.                
  452.                 AlarmJudge();                                        // 判断并根据需要报警

  453.                 for(i=0;i<25;i++)
  454.                 {
  455.                         KeyScanf();                                        // 按键扫描
  456.                         DelayMs(20);                                // 延时        
  457.                 }
  458.         }
  459. }
复制代码



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

使用道具 举报

沙发
ID:543049 发表于 2019-5-30 10:03 | 只看该作者
电路图什么样子啊
回复

使用道具 举报

板凳
ID:555338 发表于 2019-6-5 10:21 | 只看该作者
这个是用STM32 的吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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