找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机的二氧化碳、温湿度检测系统程序与PCB设计

  [复制链接]
跳转到指定楼层
楼主
基于51单片机的二氧化碳、温湿度检测系统设计。采用LCD1602显示,CO2传感器使用MH-Z19B,温湿度传感器使用DHT11,此文件含有代码、原理图、PCB文件。

制作出来的实物图如下:


Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)


单片机源程序如下:
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name        : main.C
  3. * Author                :
  4. * License                : MIT
  5. * Version                : V1.0
  6. * Date                        : 2019/04/12
  7. * Description                : 51温湿度二氧化碳检测
  8. *******************************************************************************/
  9. #include <reg52.h>
  10. #include "1602.h"
  11. #include "dht.h"
  12. #include "2402.h"

  13. #define uchar unsigned char
  14. #define uint  unsigned int
  15. #define ulong unsigned long
  16.        
  17. //定义三个LED灯
  18. sbit Led_qushi = P1^0;                  //去湿灯
  19. sbit Led_jiangwen = P1^1;                //降温灯
  20. sbit led_CO2 = P1^2;        //二氧化碳控制灯
  21. //定义蜂鸣器
  22. sbit fmq = P2^3;        //蜂鸣器
  23. //定义设置键、调整键
  24. sbit Key_TH1 = P3^0;//温度上限值调整按键
  25. sbit Key_TH2 = P3^1;
  26. sbit Key_HH1 = P3^2;//湿度上限值调整按键
  27. sbit Key_HH2 = P3^3;
  28. sbit shezhi  = P2^7;//设置键
  29. sbit Key_CH1 = P2^6;//二氧化碳上限值调整按键
  30. sbit Key_CH2 = P2^5;

  31. //二氧化碳发送指令
  32. uchar  code tab[9]={0xff,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
  33. uchar  date[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

  34. //定义标识
  35. volatile bit FlagStartRH = 0;  //开始温湿度转换标志
  36. volatile bit FlagKeyPress = 0; //有键按下
  37. volatile bit fmqt = 0;
  38. volatile bit fmqh = 0;
  39. volatile bit fmqc = 0;
  40. //定义温湿度传感器用外部变量
  41. extern U8  U8FLAG,k;
  42. extern U8  U8count,U8temp;
  43. extern U8  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
  44. extern U8  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
  45. extern U8  U8comdata;
  46. extern U8  count, count_r;
  47. U16 temp;
  48. S16 temperature, humidity;
  49. S16 idata TH, HH, ch;  //温度上限和湿度上限//二氧化碳上限值
  50. char * pSave;
  51. U8 keyvalue, keyTH1, keyTH2, keyHH1, keyHH2, keyCH1, keyCH2;
  52. unsigned char moshi=0;
  53. //定义变量
  54. U16 RHCounter;

  55. /************************************
  56.     延时子程序
  57.         延时时间(xms*1)ms
  58. *************************************/
  59. void delayms(uint xms)
  60. {
  61.         uint x,y;
  62.         for(x=xms;x>0;x--)
  63.                 for(y=110;y>0;y--);
  64. }
  65. /*******************************************************************************
  66. *  功    能          :  串口发送
  67. *  注意事项          :  
  68. *******************************************************************************/
  69. void send(uchar dat)         //发送一字节   
  70. {
  71.   SBUF=dat;
  72.   while(!TI);
  73.   TI=0;
  74. }
  75. /*******************************************************************************
  76. *  功    能          :  数据初始化程序
  77. *  注意事项          :  
  78. *******************************************************************************/
  79. void Data_Init()
  80. {
  81.    RHCounter = 0;
  82.    Led_qushi = 1;
  83.    Led_jiangwen = 1;
  84.    led_CO2 = 1;
  85.    TH = 40;  //温度初始上限值
  86.    HH = 85;  //湿度初始上限限制
  87.          ch = 25;  //二氧化碳初始上限值
  88.    keyvalue = 0;
  89.    keyTH1 = 1;
  90.    keyTH2 = 1;
  91.    keyHH1 = 1;
  92.    keyHH2 = 1;
  93.          keyCH1 = 1;
  94.          keyCH2 = 1;
  95. }

  96. //定时器0初始化
  97. void Timer0_Init()
  98. {
  99.         ET0 = 1;        //允许定时器0中断
  100.         TMOD = 1;       //定时器工作方式选择
  101.         TL0 = 0x06;     
  102.         TH0 = 0xf8;     //定时器赋予初值
  103.         TR0 = 1;        //启动定时器
  104. }

  105. //存入设定值、
  106. void Save_Setting()
  107. {
  108.    pSave =  (char *)&TH;          //地址低位对应低8位,高位对应高8位
  109.    wrteeprom(0, *pSave);          //存温度上限值TH低8位
  110.    DELAY(300);
  111.    pSave ++;
  112.    wrteeprom(1, *pSave);          //存温度上限值TH高8位
  113.    DELAY(300);
  114.    pSave =  (char *)&HH;
  115.    wrteeprom(2, *pSave);          //存湿度上限值RH低8位
  116.    DELAY(300);
  117.    pSave ++;
  118.    wrteeprom(3, *pSave);          //存湿度上限值RH高8位
  119.    DELAY(300);
  120.          pSave =  (char *)&ch;
  121.    wrteeprom(4, *pSave);          //存CO2上限值RH低8位
  122.    DELAY(300);
  123.    pSave ++;
  124.    wrteeprom(5, *pSave);          //存CO2上限值RH高8位
  125.    DELAY(300);
  126. }

  127. //载入设定值、
  128. void Load_Setting()
  129. {
  130.    pSave =  (char *)&TH;
  131.    *pSave++ = rdeeprom(0);
  132.    *pSave = rdeeprom(1);
  133.    pSave = (char *)&HH;
  134.    *pSave++ = rdeeprom(2);
  135.    *pSave = rdeeprom(3);
  136.          pSave = (char *)&ch;
  137.    *pSave++ = rdeeprom(4);
  138.    *pSave = rdeeprom(5);
  139.    if ((TH>99)||(TH<0)) TH = 40;
  140.    if ((HH>99)||(HH<0)) HH = 85;
  141.          if ((ch>50)||(ch<0)) ch = 25;
  142. }
  143. //按键扫描程序
  144. void Key_set_scan()
  145. {
  146.   if(shezhi==0)
  147.           {
  148.            delayms(10);
  149.                 if(shezhi==0)
  150.                 {  
  151.                    while(!shezhi);
  152.                    L1602_init(); //初始化液晶
  153.                    moshi++;
  154.                    if(moshi >= 2)moshi = 0;
  155.                    if(moshi == 0)
  156.                    {
  157.                                 L1602_string(1,1,"Te:   C  ");
  158.                                 L1602_string(1,9,"Hu:   %  ");
  159.                                 L1602_string(2,1,"PPM:   ");            
  160.                    }
  161.                    else if(moshi == 1)
  162.                    {
  163.                                 L1602_string(1,1,"TH:");
  164.                                 L1602_string(1,9,"HH:");
  165.                                 L1602_string(2,1,"CH:");
  166.                                 L1602_string(2,8,"0");  
  167.                                 L1602_string(2,9,"0");
  168.                    }                                            
  169.                 }
  170.         }
  171. }       
  172. //按键加减设定值
  173. void KeyProcess(uint num)
  174. {                       
  175.    switch (num)
  176.    {
  177.       case 1:
  178.              if (TH<99) TH++;
  179.              L1602_char(1, 5, TH/10+48);
  180.              L1602_char(1, 6, TH%10+48);
  181.              break;
  182.           case 2:
  183.              if (TH>1) TH--;
  184.              L1602_char(1, 5, TH/10+48);
  185.              L1602_char(1, 6, TH%10+48);
  186.              break;
  187.           case 3:
  188.              if (HH<99) HH++;
  189.              L1602_char(1, 13, HH/10+48);
  190.              L1602_char(1, 14, HH%10+48);
  191.              break;
  192.           case 4:
  193.              if (HH>1) HH--;
  194.              L1602_char(1, 13, HH/10+48);
  195.              L1602_char(1, 14, HH%10+48);
  196.              break;
  197.          case 5:
  198.              if (ch<50) ch++;
  199.              L1602_char(2, 6, ch/10+48);
  200.              L1602_char(2, 7, ch%10+48);
  201.              break;
  202.          case 6:
  203.              if (ch>1) ch--;
  204.              L1602_char(2, 6, ch/10+48);
  205.              L1602_char(2, 7, ch%10+48);
  206.              break;
  207.           default:
  208.              break;
  209.    }
  210.    Save_Setting();

  211. }

  212. /*******************************************************************************
  213. * 函 数 名         :  main
  214. * 函数功能                     : 主函数
  215. * 输    入         : 无
  216. * 输    出         : 无
  217. *******************************************************************************/
  218. void main()
  219. {
  220.           U16 testnum;
  221.                 uint  tmp;
  222.                 uchar m;
  223.           EA = 0;
  224.                 Timer0_Init();  //定时器0初始化
  225.     Data_Init();
  226.                 EA = 1;

  227.                 TMOD=0x20;         // T1定时方式2
  228.                 SCON=0x40;//串行工作 方式1
  229.                 PCON=0x00; //不加倍
  230.                 TH1=TL1=0xfd; //定时器1赋初值  保证波特率9600
  231.                 TR1=1;                  //开定时器1
  232.                 REN=1;                  //允许串口接收
  233.                 delayms(10);
  234.                 ES=1;                  //打开串口中断
  235.                 EA=1;                  //开总中断

  236.           L1602_init();
  237.           Load_Setting();
  238.         while(1)
  239.         {               
  240.                 for(m=0;m<9;m++)  //向co2传感器发送数据
  241.                 {
  242.                                 send(tab[m]);
  243.                 }
  244.                  delayms(100);  //延时0.1s  刷新测得数据
  245.                  tmp=date[2]*256+date[3];        //计算出co2浓度值
  246.                
  247.        //温湿度转换标志检查
  248.                  if (FlagStartRH == 1)
  249.                  {
  250.                      TR0 = 0;
  251.          testnum = RH();
  252.                          FlagStartRH = 0;
  253.                          TR0 = 1;
  254.              //读出温湿度,只取整数部分
  255.                          humidity = U8RH_data_H;
  256.                          temperature = U8T_data_H;
  257.                 }
  258.                 //温湿度控制
  259.                 if (temperature > TH)
  260.                 {
  261.                 Led_jiangwen = 0;
  262.                 fmqt=1;
  263.                 }
  264.                 else
  265.                 {
  266.                 Led_jiangwen = 1;
  267.                 fmqt=0;
  268.                 }                                //降温
  269.                 if (humidity > HH)
  270.                 {
  271.                 Led_qushi = 0;
  272.                 fmqh=1;
  273.                 }
  274.                 else
  275.                 {
  276.                 Led_qushi = 1;
  277.                 fmqh=0;
  278.                 }                                                //去湿
  279.                 if (tmp/100 > ch)
  280.                 {
  281.                 led_CO2 = 0;
  282.                 fmqc=1;
  283.                 }
  284.                 else
  285.                 {
  286.                 led_CO2 = 1;
  287.                 fmqc=0;
  288.                 }                                                //CO2
  289.                 if((fmqt==1)||(fmqh==1)||(fmqc==1))
  290.                 fmq=0;
  291.                 else
  292.                 fmq=1;
  293.                
  294.                
  295.                 Key_set_scan();//按键扫描
  296.                  if(moshi == 0)          //设置模式切换
  297.                 {
  298.                         delayms(50);
  299.                         L1602_string(1,1,"Te:   C  ");
  300.                         L1602_string(1,9,"Hu:   %  ");
  301.                         L1602_string(2,1,"PPM:   ");   
  302.                         if(tmp>9999)
  303.                         tmp=0;   
  304.                         L1602_int(2,5,tmp);
  305.                         if((tmp/1000)>0)               
  306.                         L1602_int(2,5,tmp/1000);       
  307.                         //显示温湿度
  308.                         L1602_int(1,3, temperature);
  309.                         L1602_int(1,11,humidity);
  310.                 }
  311.                 else if(moshi == 1)        //设置上限模式
  312.                 {
  313.                         L1602_char(1, 5,  TH/10+48);
  314.                         L1602_char(1, 6,  TH%10+48);
  315.                         L1602_char(1, 13, HH/10+48);
  316.                         L1602_char(1, 14, HH%10+48);
  317.                         L1602_char(2, 6,  ch/10+48);
  318.             L1602_char(2, 7,  ch%10+48);
  319.                 }                       
  320.                
  321.     //U8 keyvalue, keyTH1, keyTH2, keyHH1, keyHH2, keyCH1, keyCH2;
  322.                 //键盘查询,在弹起时响应
  323.                 if ((Key_TH1)&&(keyTH1==0)) {FlagKeyPress = 1; keyvalue = 1;}
  324.                         else if ((Key_TH2)&&(keyTH2==0)) {FlagKeyPress = 1; keyvalue = 2;}
  325.                         else if ((Key_HH1)&&(keyHH1==0)) {FlagKeyPress = 1; keyvalue = 3;}
  326.                         else if ((Key_HH2)&&(keyHH2==0)) {FlagKeyPress = 1; keyvalue = 4;}
  327.                         else if ((Key_CH1)&&(keyCH1==0)) {FlagKeyPress = 1; keyvalue = 5;}
  328.                         else if ((Key_CH2)&&(keyCH2==0)) {FlagKeyPress = 1; keyvalue = 6;}
  329.                 if (FlagKeyPress == 1)
  330.                 {
  331.                           KeyProcess(keyvalue);
  332.                           FlagKeyPress = 0;           
  333.                 }
  334.         if (!Key_TH1) keyTH1 = 0;
  335.                 else keyTH1 = 1;
  336.         if (!Key_TH2) keyTH2 = 0;
  337.                 else keyTH2 = 1;
  338.         if (!Key_HH1) keyHH1 = 0;
  339.                 else keyHH1 = 1;
  340.         if (!Key_HH2) keyHH2 = 0;
  341.                 else keyHH2 = 1;
  342.                
  343.                     if (!Key_CH1) keyCH1 = 0;
  344.                 else keyCH1 = 1;
  345.         if (!Key_CH2) keyCH2 = 0;
  346.                 else keyCH2 = 1;
  347.                  
  348.         }       
  349. }
  350. //定时器0中断
  351. void Timer0_ISR (void) interrupt 1
  352. {
  353.         TL0 = 0x06;
  354.         TH0 = 0xf8;     //定时器赋予初值

  355.         //每2秒钟启动一次温湿度转换
  356.     RHCounter ++;
  357.     if (RHCounter >= 1000)
  358.     {
  359.        FlagStartRH = 1;
  360.              RHCounter = 0;
  361.     }
  362. }

  363. //串口中断服务函数
  364. void serial()interrupt 4               
  365. {
  366.                 static uchar j;
  367.                 ES=0;                         //禁止中断
  368.                 if(!RI);
  369.                 RI=0;                    //清楚接收完毕标志
  370.                 date[j]=SBUF;
  371.                 if(date[0]==0xff)  //判断接收到的第一位为传感器所发数据
  372.                 j++;
  373.                 else
  374.                 j=0;
  375.                 if(j==9)                   //接收传感器所发数据9字节
  376.                 j=0;
  377.                 ES=1;                  //允许串口中断
  378. }
复制代码

所有资料51hei提供下载:
51单片机二氧化碳_温湿度检测C程序+原理图+PCB.zip (1.85 MB, 下载次数: 256)




评分

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

查看全部评分

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

使用道具 举报

沙发
ID:328014 发表于 2019-6-11 02:17 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:682420 发表于 2020-1-6 20:08 | 只看该作者
感谢楼主的资料
回复

使用道具 举报

地板
ID:110278 发表于 2020-1-6 20:45 | 只看该作者
很多的资料,顶一个。
回复

使用道具 举报

5#
ID:684775 发表于 2020-1-10 19:08 | 只看该作者
感谢楼主分享
回复

使用道具 举报

6#
ID:699436 发表于 2020-3-15 10:28 | 只看该作者

感谢楼主分享
回复

使用道具 举报

7#
ID:695384 发表于 2020-3-15 17:44 | 只看该作者
谢谢楼主分享哦
回复

使用道具 举报

8#
ID:710428 发表于 2020-3-18 17:18 | 只看该作者

感谢楼主
回复

使用道具 举报

9#
ID:712126 发表于 2020-3-23 11:08 | 只看该作者
MH-Z19B proteus里没有该从那找
回复

使用道具 举报

10#
ID:719833 发表于 2020-4-1 11:19 | 只看该作者
很好的资料,顶
回复

使用道具 举报

11#
ID:555499 发表于 2020-4-1 15:52 | 只看该作者
资料很好,感谢楼主,感谢网站!
回复

使用道具 举报

12#
ID:594633 发表于 2020-4-1 17:28 来自手机 | 只看该作者
收藏了,感谢楼主分享。
回复

使用道具 举报

13#
ID:57810 发表于 2020-4-5 23:38 | 只看该作者
顶一个。
回复

使用道具 举报

14#
ID:727740 发表于 2020-6-14 19:32 | 只看该作者
感谢楼主的分享
回复

使用道具 举报

15#
ID:727740 发表于 2020-6-15 08:32 | 只看该作者
图中用的好像不是lcd1602吧....
回复

使用道具 举报

16#
ID:420249 发表于 2020-9-22 21:48 | 只看该作者
读不了CO2浓度,求指教

2c507551e91bc40957f0e1cb5f979fc.jpg (158.72 KB, 下载次数: 24)

读不了CO2浓度啊

读不了CO2浓度啊
回复

使用道具 举报

17#
ID:420249 发表于 2020-9-23 08:04 | 只看该作者
co2不管用哟,求指教。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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