单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:2325|回复:2
打印上一主题下一主题

修改好的单片机PM2.5+DHT11温湿度传感程序

[复制链接]
跳转到指定楼层
楼主
ID:377166发表于 2021-5-14 15:09|只看该作者|只看大图回帖奖励
  1. #include< reg52.h>  //头文件
  2. #include "1602.h"
  3. #include "DHT11.h"
  4. #include< adc0832.h>
  5. #include< intrins.h>
  6. #include "eeprom52.h"
  7. #define uchar unsigned char  //定义字符类型
  8. #define uint  unsigned int

  9. typedef bit BOOL  ;
  10. sbit DQ=P1^5;   //DTH11
  11. sbit beep = P1^7; //蜂鸣器
  12. sbit LED = P1^6;  //粉尘传感器内部LED控制

  13. uchar FlagStart = 0;         //标志位        
  14. uint Counter;
  15. uint DUST_SET;             //固体颗粒的阈值
  16. uchar ADC_Get[10]={0};       //定义AD采样数组
  17. uchar num=0;     //定义的变量,采集一段时间内的值
  18. uchar time1=0;     //定义的时间变量,用于温湿度处理显示
  19. uchar time2=0;     //定义的时间变量,开机报警功能等待温度湿度PM2.5数据处理完成再启动,避免蜂鸣器开机就乱叫。
  20. uint DUST;     //定义的PM2.5的值
  21. uint   DUST_Value;   //定义的PM2.5的值
  22. uchar GetADVal(uchar);
  23. uchar RH,TH;
  24. uint num1,num2,Temp_H,Temp_L,Humi_H,Humi_L,s_dengji;  //定义的报警值,参数具有断电保存功能,仅支持STC单片机
  25. uchar yemian=0;  //定义的页面标志
  26. uchar flat=1;     //定义的判断标志


  27. sbit K1=P3^2;  //按键定义
  28. sbit K2=P3^3;
  29. sbit K3=P3^4;

  30. void  Delay_10us(void)
  31. {
  32.   uchar i;
  33.    i--;
  34.    i--;
  35.    i--;
  36.    i--;
  37.    i--;
  38. }

  39. /***********************1ms延时函数*****************************/
  40. void delay_1ms(uint q)
  41. {
  42.      uint i,j;
  43.      for(i=0;i<q;i++)
  44.          for(j=0;j<120;j++);
  45. }

  46. /******************把数据保存到单片机内部eeprom中******************/
  47. void write_eeprom()
  48. {
  49.   num1=s_dengji/256;  //因为eeprom每个区间最大存放256个字节,当大于要分开存储
  50.      num2=s_dengji%256;
  51.      SectorErase(0x2000);
  52.      byte_write(0x2001,  num1);
  53.      byte_write(0x2002,  num2);
  54.      byte_write(0x2003,  Temp_H);
  55.      byte_write(0x2004,  Temp_L);
  56.      byte_write(0x2005,  Humi_H);
  57.      byte_write(0x2006,  Humi_L);
  58.     
  59.      byte_write(0x2060, a_a);    
  60. }

  61. /******************把数据从单片机内部eeprom中读出来*****************/
  62. void read_eeprom()
  63. {
  64.      num1   = byte_read(0x2001);
  65.      num2   = byte_read(0x2002);
  66.      Temp_H   = byte_read(0x2003);
  67.      Temp_L  = byte_read(0x2004);
  68.      Humi_H   = byte_read(0x2005);
  69.      Humi_L   = byte_read(0x2006);
  70.      a_a   = byte_read(0x2060);

  71.      s_dengji= num1*256+num2;
  72. }

  73. /**************开机自检eeprom初始化*****************/
  74. void init_eeprom()
  75. {
  76.      read_eeprom();         //先读
  77.      if(a_a != 2)         //新的单片机初始单片机内问eeprom
  78.      {
  79.            num1=200/256;
  80.      num2=200%256;
  81.          Temp_H   = 35;
  82.        Temp_L  = 5;
  83.        Humi_H   = 80;
  84.        Humi_L   = 10;
  85.          a_a = 2;
  86.          write_eeprom();
  87.      }    
  88. }
  89.      //**************************延时函数
  90. void delay_ms2(uint z)
  91. {
  92. uint x,y;
  93. for(x=z;x>0;x--)
  94.   for(y=114;y>0;y--);
  95. }

  96. //**************************初始化DTH11***********************/
  97. bit Init_DTH11()
  98. {
  99. bit flag;
  100. uchar num;
  101. DQ=0;
  102. delay_ms2(19);   // >18ms
  103. DQ=1;
  104. for(num=0;num<10;num++);   // 20-40us   34.7us
  105. for(num=0;num<12;num++);
  106. flag=DQ;
  107. for(num=0;num<11;num++); //DTH响应80us
  108. for(num=0;num<24;num++);   //DTH拉高80us
  109. return flag;
  110. }
  111. //****************************读DTH11数据
  112. uchar DTH11_RD_CHAR()
  113. {
  114. uchar byte=0;
  115. uchar num;
  116. uchar num1;
  117. while(DQ==1);
  118. for(num1=0;num1<8;num1++)
  119. {
  120.   while(DQ==0);
  121.   byte<<=1;     //高位在前
  122.   for(num=0;DQ==1;num++);
  123.   if(num<10)
  124.    byte|=0x00;
  125.   else
  126.    byte|=0x01;
  127. }
  128. return byte;
  129. }
  130. //******************************读取DTH11温度和湿度
  131. void  DTH11_DUSHU()
  132. {
  133. uchar num;
  134. if(Init_DTH11()==0)
  135. {
  136.   RH=DTH11_RD_CHAR();   //
  137.   DTH11_RD_CHAR();
  138.   TH=DTH11_RD_CHAR();
  139.   DTH11_RD_CHAR();
  140.   DTH11_RD_CHAR();
  141.   for(num=0;num<17;num++);  //最后BIT输出后拉低总线50us
  142.   DQ=1;
  143. }
  144. }
  145. ///////////////////////////////////////////////////////////////////////////

  146. //DS---185页  定时器初始化 定时10ms
  147. void Timer0_Init()
  148. {
  149.     
  150. //AUXR=0x80; //Time work in 1T mode    
  151.      TMOD= 0x01;    
  152.      TL0 = (65536-30000)/256;    
  153.      TH0 = (65536-30000)%256;  
  154.      TR0 = 1;
  155.      ET0 = 1;  
  156.   
  157.      EX0 = 1;  //开外部中断0
  158.      IT0 = 0;  //电平触发    
  159.      EA = 1;    
  160. }

  161. //定时器0中断
  162. void Timer0_ISR (void) interrupt 1 using 0
  163. {
  164.   uint i,j;    
  165.      TL0 = (65536-30000)/256;    
  166.      TH0 = (65536-30000)%256;  
  167.       
  168.        LED=0;                   //开启传感器的LED
  169.        for (j=0;j<30;j++);  //0.28ms  //延时0.28ms
  170.    ADC_Get[num]=Get_AD_Result();       //开启ADC采集
  171.       
  172.        num++;
  173.      if(num>10)
  174.      {
  175.        FlagStart=1;
  176.        num=0;
  177.        TR0 = 0;   //先关闭定时器0

  178.      }                           //采集10次,关闭定时器0,进行数据处理
  179.     
  180.                                //关闭传感器LED
  181.      LED=1;
  182.     
  183. }







  184. //中值滤波
  185. //算法:先进行排序,然后将数组的中间值作为当前值返回。
  186. uchar Error_Correct(uchar *str,uchar num)
  187. {
  188.    unsigned char i=0;
  189.    unsigned char j=0;
  190.    uchar Temp=0;
  191.   
  192.    //排序
  193.    for(i=0;i<num-1;i++)
  194.      {
  195.        for(j=i+1;j<num;j++)
  196.        {
  197.          if(str[i]<str[j])
  198.            {
  199.            Temp=str[i];
  200.            str[i]=str[j];
  201.            str[j]=Temp;
  202.         
  203.          }
  204.       
  205.        }
  206.      }
  207.    //去除误差,取中间值
  208.    return str[num/2];

  209. }

  210. void wenshidu()  //温湿度处理函数
  211. {  
  212.    time1++;
  213.    if(time1>=5)  //避免液晶快速刷新显示
  214.        {          
  215.        EA=0;
  216.          time1=0;
  217.    DTH11_DUSHU();
  218.          DTH11_DUSHU();
  219.        EA=1;
  220.        LCD_Show2(2,1,TH);  //温度实时显示
  221.        LCD_Show2(11,1,RH);  //湿度实时显示
  222.          LCD_Show3(6,0,DUST); //PM2.5的值实时显示
  223.        }

  224. }

  225. void voice() //按键提示音
  226. {
  227.   beep = 0;  //打开蜂鸣器
  228.      delay_1ms(30);  //短暂延时
  229.      beep = 1;  //关闭蜂鸣器
  230. }


  231. void Outside_Int1(void) interrupt 0     using 1   //打开外部中断处理函数  优点,进入设置界面可以快速响应,避免长时间等待
  232. {
  233.        if(K1==0&& K2==1&& K3==1 )
  234.            {  
  235.                delay_1ms(20);
  236.                if(K1==0&& K2==1&& K3==1)
  237.                {  
  238.                      while(K1==0&& K2==1&& K3==1)
  239.                      ;
  240.                            num=11;
  241.          yemian++;
  242.                             
  243.          if(yemian>=6) { yemian=0; flat=1;}  
  244.          voice(); //提示音
  245.          }
  246.            }
  247. }

  248. void key()  //对里面的数值进行修改
  249. {
  250.      if(K1==0&& K2==1&& K3==1 )
  251.            {  
  252.                delay_1ms(20);
  253.                if(K1==0&& K2==1&& K3==1)
  254.                {  
  255.                      while(K1==0&& K2==1&& K3==1)
  256.                      ;
  257.                            TR0 = 0;  
  258.          yemian++;
  259.          if(yemian>=6) { yemian=0; flat=1;}  
  260.                            voice(); //提示音
  261.          }
  262.            }
  263.               
  264.              if(K1==1&& K2==0&& K3==0) //长按5秒,K2和K3按键,系统设置值恢复初始值
  265.            {  
  266.                delay_1ms(20);
  267.                if(K1==1&& K2==0&& K3==0)
  268.                {  
  269.                      while(K1==1&& K2==0&& K3==0)
  270.                      ;
  271.                s_dengji = 200;
  272.                Temp_H   = 35;
  273.            Temp_L  = 5;
  274.            Humi_H   = 80;
  275.            Humi_L   = 10;
  276.          write_eeprom();
  277.                      beep = 0;
  278.            delay_1ms(200);
  279.            beep = 1;
  280.          }
  281.            }
  282.         
  283. }

  284. void shezhi()       //独立按键程序
  285. {
  286. if(!K2)           //
  287.            {
  288.                delay_1ms(100);
  289.                  if(!K2)
  290.                  {
  291.        ;
  292.                      if(yemian==1)  
  293.                      {
  294.          if(s_dengji<999 ) { s_dengji++;}  //加1
  295.          LCD_Show3(5,1,s_dengji);
  296.        }
  297.                     
  298.                      if(yemian==2)  
  299.                      {
  300.          if(Temp_H<99 ) { Temp_H++;}  //加1
  301.          LCD_Show2(7,1,Temp_H);
  302.        }
  303.                     
  304.                      if(yemian==3)  
  305.                      {
  306.          if(Temp_L<99 ) { Temp_L ++;}  //加1
  307.          LCD_Show2(7,1,Temp_L);
  308.        }
  309.                     
  310.                      if(yemian==4)  
  311.                      {
  312.          if(Humi_H<99 ) { Humi_H ++;}  //加1
  313.          LCD_Show2(7,1,Humi_H);
  314.        }
  315.                     
  316.                      if(yemian==5)  
  317.                      {
  318.          if(Humi_L<99 ) { Humi_L ++;}  //加1
  319.          LCD_Show2(7,1,Humi_L);
  320.                         
  321.        }
  322.                   
  323.            write_eeprom();     //保存数据
  324.        voice(); //提示音                    
  325.                  }
  326.              }
  327.             
  328. if(!K3)           //
  329.            {
  330.                delay_1ms(100);
  331.                  if(!K3)
  332.                  {
  333.        ;
  334.                     
  335.                  if(yemian==1)
  336.                  {                    
  337.                  if(s_dengji>1)  {  s_dengji--; }     //浓度设置数减1
  338.          LCD_Show3(5,1,s_dengji);
  339.        }
  340.                 
  341.                  if(yemian==2)
  342.                  {                    
  343.                  if(Temp_H>1)  {  Temp_H--; }     //浓度设置数减1
  344.        LCD_Show2(7,1,Temp_H);
  345.        }
  346.                 
  347.                  if(yemian==3)
  348.                  {                    
  349.                  if(Temp_L>1)  { Temp_L--; }     //浓度设置数减1
  350.          LCD_Show2(7,1,Temp_L);
  351.        }
  352.                 
  353.                  if(yemian==4)
  354.                  {                    
  355.                  if(Humi_H>1)  {  Humi_H--; }     //浓度设置数减1
  356.        LCD_Show2(7,1,Humi_H);
  357.        }
  358.                 
  359.                  if(yemian==5)
  360.                  {                    
  361.                  if(Humi_L>1)  {  Humi_L--; }     //浓度设置数减1
  362.        LCD_Show2(7,1,Humi_L);
  363.        }
  364.          write_eeprom();     //保存数据
  365.        voice(); //提示音                
  366.              }
  367.    }            
  368. }

  369. //****************报警函数*************
  370. void baojing()
  371. {
  372.     
  373. if(DUST >= s_dengji || TH>=Temp_H || TH<=Temp_L || RH>=Humi_H || RH<=Humi_L )         //报警
  374.      {
  375.    beep = ~beep;       //蜂鸣器报警
  376.      }
  377.     
  378.      else
  379.      {
  380.        beep = 1;
  381.   }
  382. }


  383. void chengxu()  //主界面处理程序
  384. {
  385.   if(FlagStart==1)     //10次采集完成
  386.        {
  387.             
  388.      DUST=Error_Correct(ADC_Get,10);         //求取10次AD采样的值
  389.        DUST_Value=(DUST/256.0)*5000-200;         //
  390.        DUST_Value=DUST_Value*0.32;
  391.        if(DUST_Value<0)         DUST_Value=0;
  392.        if(DUST_Value>999)       DUST_Value=999;     //限位
  393.        DUST=(uint)DUST_Value;                       //
  394.      time2++;
  395.            if(time2>5) //开机后程序运行5次再启动蜂鸣器功能
  396.                      //开机报警功能等待温度湿度PM2.5数据处理完成再启动,避免蜂鸣器开机就乱叫。
  397.            {
  398.                time2=6;
  399.                baojing();
  400.      }
  401.         
  402.      wenshidu();
  403.          if(yemian==0)
  404.          {            
  405.    Delay_10us();  
  406.        TL0 = (65536-30000)/256;    
  407.        TH0 = (65536-30000)%256;
  408.        TR0 = 1;   //开启定时器0
  409.    FlagStart=0;
  410.          }
  411.        }

  412. }





  413. void main()
  414. {  
  415.        init_eeprom();
  416.    LCD_Init();     //液晶初始化
  417.    LCD_Clear();//清屏
  418.    LCD_Write_String(4,0,"Welcome");
  419.    delay_ms(2000);
  420.    Timer0_Init();   //定时器0初始化
  421.   
  422. while(1)
  423.    {
  424.           
  425.            key();       //独立按键程序
  426.   //====================yemian==0时 进入工作状态=================================
  427.                if(yemian==0)  
  428.              {
  429.                 
  430.                  if(flat==1)
  431.                    {
  432.        flat=2;
  433.        LCD_Clear();//清屏
  434.        LCD_Write_String(0,0,"PM2.5:   ug/m3 ");
  435.        LCD_Write_String(0,1,"T:   C   H:  %RH");
  436.        LCD_Write_Char(4,1,0xdf);
  437.                     
  438.                      TL0 = (65536-30000)/256;    
  439.            TH0 = (65536-30000)%256;
  440.            TR0 = 1;   //开启定时器0
  441.            EA = 1;
  442.        }

  443.                    chengxu();//主界面处理程序
  444.       
  445.      }    
  446.       
  447. //====================yemian==1时 ======PM2.5报警值========================
  448.                if(yemian==1)  
  449.              {
  450.                  if(flat==2)
  451.                    {
  452.        flat=3;
  453.        beep = 1;
  454.                      TR0 = 0;   //
  455.                      EA=0;
  456.                    LCD_Clear();//清屏
  457.        LCD_Write_String(0,0,"   Set PM2.5   ");
  458.        LCD_Write_String(0,1,"       ug/m3   ");
  459.        }
  460.                  shezhi() ;
  461.                    LCD_Show3(5,1,s_dengji);
  462.                 
  463.      }        
  464.               
  465. //====================yemian==2时 温度上限==============================
  466.                if(yemian==2)  
  467.              {
  468.                  if(flat==3)
  469.                    {
  470.        flat=4;
  471.        beep = 1;
  472.                      TR0 = 0;   //
  473.                      EA=0;
  474.                    LCD_Clear();//清屏
  475.        LCD_Write_String(0,0,"   Set Temp_H   ");
  476.        LCD_Write_String(0,1,"       C     ");
  477.                      LCD_Write_Char(9,1,0xdf);
  478.        }
  479.                  shezhi() ;
  480.                    LCD_Show2(7,1,Temp_H);
  481.                 
  482.      }        
  483.       
  484. //====================yemian==3时 温度下限==============================
  485.                if(yemian==3)  
  486.              {
  487.                  if(flat==4)
  488.                    {
  489.        flat=5;
  490.        beep = 1;
  491.                      TR0 = 0;   //
  492.                      EA=0;
  493.                    LCD_Clear();//清屏
  494.        LCD_Write_String(0,0,"   Set Temp_L   ");
  495.        LCD_Write_String(0,1,"       C     ");
  496.                      LCD_Write_Char(9,1,0xdf);
  497.        }
  498.                  shezhi() ;
  499.                    LCD_Show2(7,1,Temp_L);
  500.                 
  501.      }    

  502. //====================yemian==4时 湿度上限==============================
  503.                if(yemian==4)  
  504.              {
  505.                  if(flat==5)
  506.                    {
  507.        flat=6;
  508.        beep = 1;
  509.                        TR0 = 0;   //
  510.                      EA=0;
  511.                    LCD_Clear();//清屏
  512.        LCD_Write_String(0,0,"   Set Humi_H   ");
  513.        LCD_Write_String(0,1,"       %     ");
  514.                 
  515.        }
  516.                  shezhi() ;
  517.                    LCD_Show2(7,1,Humi_H);
  518.                 
  519.      }              

  520. //====================yemian==5时 湿度下限==============================
  521.                if(yemian==5)  
  522.              {
  523.                  if(flat==6)
  524.                    {
  525.        flat=1;
  526.        beep = 1;
  527.                      TR0 = 0;   //
  528.                      EA=0;
  529.                    LCD_Clear();//清屏
  530.        LCD_Write_String(0,0,"   Set Humi_L   ");
  531.        LCD_Write_String(0,1,"       %     ");
  532.        }
  533.                  shezhi() ;
  534.                    LCD_Show2(7,1,Humi_L);
  535.      }        
  536.   
  537.   }
  538.   
  539. }
复制代码



以上代码下载: PM2.5+温湿度程序.rar(86.7 KB, 下载次数: 43)

评分

黑币 +50
收起理由
+ 50
共享资料的黑币奖励!

查看全部评分

沙发
ID:1012237发表于 2022-3-26 16:42|只看该作者
大佬有原理图吗?想看看
板凳
ID:1112270发表于 2024-4-25 15:36|只看该作者
您好我想请问一下,我的温湿度没有问题,但是PM没有显示是为什么呢

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

Powered by 单片机教程网