zoukankan      html  css  js  c++  java
  • 51单片机(STC89C52RC)读取DHT11模块温度湿度信号采集显示数码管

    51单片机(STC89C52RC)读取DHT11模块温度湿度信号采集显示数码管

    上上周末媳妇问我,家里温度多少,。。。我TM哪知道,租这么个鬼地方,啥也没有,我能猜的出来吗,当然“TM的”的是我现在现在加的。。。^_^,然后就想之前也买了一个树莓派4B也买了一个面包板,再回忆一下大学时曾经所学的知识,算求了,想做个这么个玩意儿,然后,就。。。。。网上一搜,20多块钱就能买一个。。。。但是作为一个程序员,就是这么喜欢折腾。。。也想多赞点儿私房钱。。然后就多要了点儿经费。。O(∩_∩)O哈哈~

    我只是一个单纯的软件开发工程师。。对于硬件仅仅局限于大学那点儿知识而且毕业四五年了,早忘的差不多了,都是靠百度和各位大神的分享来去驱动。。。

    1.成品展示

    左侧温度,右侧湿度   成品和仿真电路有区别,做着过程中发生了变化,就没有再去仿真了,就增加了俩个报警指示灯

    下图:左侧27℃   右侧42%RH

    2.问老婆申请经费(O(∩_∩)O)

    3.下单,购买器件

    (这里真是没想到,买个成品可能20块钱,但是你要做一个,各东西都得买。。前前后后下单了3次,这里只贴一张图吧。。,还买俩个万用表、电烙铁。。。。各种器件。。。线材啥的。。。。。反正很多,反正是要干赔了,还倒贴了不少私房钱。。)

    4.绘制电路图仿真Proteus8.6版本

    (基本百度就完了,各种各样的都有,这个比较简单)左侧温度,右侧湿度

    1.DHT11模块的电路使用 (详细文档到这里一下载

     DHT11模块的时序图

     

     

     

     2.电路设计

    Proteus电路仿真和C语言程序源代码下载

     程序

    #include<reg51.h>
    #include<intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    sbit Data=P3^6;       //定义数据线
    uchar rec_dat[9];   //用于显示的接收数据数组
    //数码管数字 0--9
    uint led[10]={0xc0,0xf9,0xa4, 0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  
    
    
    
    void delay(uint n)
    {  
        uint x,y; 
       for(x=n;x>0;x--) 
           for(y=110;y>0;y--); 
    } 
    
    
    
    void write_com(uchar com)
    {
                               //rs=0时输入指令
            P2=com;
            delay(5);
    
    }
    
    
    
    void DHT11_delay_us(uchar n)
    {
        while(--n);
    }
    
    void DHT11_delay_ms(uint z)
    {
       uint i,j;
       for(i=z;i>0;i--)
          for(j=110;j>0;j--);
    }
    
    void DHT11_start()
    {
       Data=1;
       DHT11_delay_us(2);
       Data=0;
       DHT11_delay_ms(30);   //延时18ms以上
       Data=1;
       DHT11_delay_us(30);
    }
    
    uchar DHT11_rec_byte()      //接收一个字节
    {
       uchar i,dat=0;
      for(i=0;i<8;i++)    //从高到低依次接收8位数据
       {          
          while(!Data);   ////等待50us低电平过去
          DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0 
          dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
          if(Data==1)    //数据为1时,使dat加1来接收数据1
             dat+=1;
          while(Data);  //等待数据线拉低    
        }  
        return dat;
    }
    
    
    //延时程序 单位ms
    void delay222(unsigned int x)
    {
        unsigned int i,j;
    
        for(i=x;i>0;i--)
            for(j=110;j>0;j--);
    }
    
    
    //设置温度值
    void SetTemperature(uchar value)
    {
    
        //取出个位、十位数字
       int unitPlace = value/1%10;
       int tenPlace = value/10%10;
        
        
        P0 = led[tenPlace];
        P2 = 0x80;
        delay222(3);
        P2 = 0x00;
              
        P0 = led[unitPlace];
        P2 = 0x40;
        delay222(3);
        P2 = 0x00;
    }
    
    //设置湿度值
    void SetHumidity(uchar value)
    {
    
        //取出个位、十位数字
       int unitPlace = value/1%10;
       int tenPlace = value/10%10;
        
        
        P0 = led[tenPlace];
        P2 = 0x20;
        delay222(3);
        P2 = 0x00;
              
        P0 = led[unitPlace];
        P2 = 0x10;
        delay222(3);
        P2 = 0x00;
    }
    void DHT11_receive()      //接收40位的数据
    {
        uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise; 
        int number; //闪烁频率
        int count2;
        uchar tempValue;
        uchar  humidityValue;
    
    
        number = 20;
        count2 = 0;
    
        DHT11_start();
    
    
    
        count2 = 0;
        if(Data==0)
        {
            while(Data==0);   //等待拉高     
            DHT11_delay_us(40);  //拉高后延时80us
            R_H=DHT11_rec_byte();    //接收湿度高八位  
            R_L=DHT11_rec_byte();    //接收湿度低八位  
            T_H=DHT11_rec_byte();    //接收温度高八位  
            T_L=DHT11_rec_byte();    //接收温度低八位
            revise=DHT11_rec_byte(); //接收校正位
    
            DHT11_delay_us(25);    //结束
    
            if((R_H+R_L+T_H+T_L)==revise)      //校正
            {
                RH=R_H;
                RL=R_L;
                TH=T_H;
                TL=T_L;
            }
    
            /*数据处理,方便显示*/
    //        rec_dat[0]='0'+(RH/10);
    //        rec_dat[1]='0'+(RH%10);
    //        rec_dat[2]='R';
    //        rec_dat[3]='H';
    //        rec_dat[4]=' ';
    //        rec_dat[5]=' ';
    //        rec_dat[6]='0'+(TH/10);
    //        rec_dat[7]='0'+(TH%10);
    //        rec_dat[8]='C';
    
    
    
    
            //读取温度湿度
                 tempValue = RH;
                 humidityValue = TH;
                
                while(count2 < number)
                {
                    //设置温度
                    SetTemperature(tempValue);
                    //设置湿度
                    SetHumidity(humidityValue);
    
                    count2++;
                }
        
                count2=0;
    
        }
    }
    
    
    
    /*这里使用lcd1602来显示采集到的数据,lcd1602驱动程序在博主的51单片机系列博文中有详细讲解*/
    void main()
    {
       uchar i;   
    
       while(1)
       {   
    
           DHT11_receive();
               
       }
    }

    5.面包板调试电路和程序  

    买了俩个红色的2位共阳极数码管10脚的,结果没有接限流电阻,烧坏了一个,被迫又一次下单购买,结果购买错了,买了俩个绿色的共阴极18脚的,太恶心了,焊接过得人估计能体会

    6.器件部署和电路板焊接

    焊接的过程中,发现还可以增加个报警指示灯。于是又焊接了俩个报警指示灯连接到了P1.0(温度)和P1.1(湿度)

    因为不会绘制pcb布线,就大概摆了一下,然后就开始焊接了。。。

    实不相瞒,太恶心了,就因为买错了,买了个共阴极18脚的2位数码管。。就焊接成这样了,水平有限大神直接飘过吧。。。。

    7.成品展示

    左侧是温度,右侧是湿度显示,然后因为数码管换了,所以程序也改了,并且新增了个报警指示灯

     

    因为仿真电路和我的实际成品有区别成品中的程序

      1 //****************************************************************//
      2 //大男孩温湿度信号采集
      3 //单片机 STC89C52RC 
      4 //功能   数码管显示温度和湿度   备注:晶振 11.0592M 波特率 9600 
      5 //硬件   P3.6口为通讯口连接DHT11,DHT11的电源和地连接单片机的电源和地   
      6 //****************************************************************//
      7 
      8 #include <reg51.h>
      9 #include <intrins.h> 
     10 
     11 
     12 //数据类型定义
     13 typedef unsigned char  U8;       /* defined for unsigned 8-bits integer variable       无符号8位整型变量  */
     14 typedef signed   char  S8;       /* defined for signed 8-bits integer variable          有符号8位整型变量  */
     15 typedef unsigned int   U16;      /* defined for unsigned 16-bits integer variable       无符号16位整型变量 */
     16 typedef signed   int   S16;      /* defined for signed 16-bits integer variable       有符号16位整型变量 */
     17 typedef unsigned long  U32;      /* defined for unsigned 32-bits integer variable       无符号32位整型变量 */
     18 typedef signed   long  S32;      /* defined for signed 32-bits integer variable       有符号32位整型变量 */
     19 typedef float          F32;      /* single precision floating point variable (32bits) 单精度浮点数(32位长度) */
     20 typedef double         F64;      /* double precision floating point variable (64bits) 双精度浮点数(64位长度) */
     21 
     22 
     23 //----------------------------------------------//
     24 //----------------IO口定义区--------------------//
     25 //----------------------------------------------//
     26 sbit P3_6  = P3^6 ;     //DHT11数据针脚
     27 sbit P1_0 = P1^0;     //温度报警针脚
     28 sbit P1_1 = P1^1;     //湿度报警针脚
     29 
     30 //----------------------------------------------//
     31 //----------------数码管数字 0--9---------------//
     32 //----------------------------------------------//
     33 
     34 //uint led[10]={0xc0,0xf9,0xa4, 0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  
     35 U8 led[10]={0x3F,0x06,0x5b, 0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};  
     36 
     37 //----------------------------------------------//
     38 //----------------数据存储和数据缓存区----------//
     39 //----------------------------------------------//
     40 U8  U8FLAG;
     41 U8  U8temp;
     42 U8  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
     43 U8  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
     44 U8  U8comdata;
     45   
     46 //----------------------------------------------//
     47 //----------------延时程序----------------------//
     48 //----------------------------------------------//
     49 
     50 //延时程序
     51 void Delay(U16 j)
     52 {      
     53     U8 i;
     54     for(;j>0;j--)
     55     {     
     56         for(i=0;i<27;i++);
     57 
     58     }
     59 }
     60 
     61 //延时程序10us
     62 void  Delay_10us(void)
     63 {
     64     U8 i;
     65     i--;
     66     i--;
     67     i--;
     68     i--;
     69     i--;
     70     i--;
     71 }
     72 
     73 //延时程序 单位ms
     74 void Delayms(unsigned int x1)
     75 {
     76     unsigned int i1,j1;
     77 
     78     for(i1=x1;i1>0;i1--)
     79         for(j1=110;j1>0;j1--);
     80 }
     81     
     82 
     83 
     84 //--------------------------------
     85 //-----湿度读取子程序 ------------
     86 //--------------------------------
     87 //----以下变量均为全局变量--------
     88 //----温度高8位== U8T_data_H------
     89 //----温度低8位== U8T_data_L------
     90 //----湿度高8位== U8RH_data_H-----
     91 //----湿度低8位== U8RH_data_L-----
     92 //----校验 8位 == U8checkdata-----
     93 //----调用相关子程序如下----------
     94 //---- Delay();, Delay_10us();,COM(); 
     95 //--------------------------------
     96 
     97 
     98 void COM(void)
     99 {
    100      
    101     U8 i;
    102           
    103     for(i=0;i<8;i++)       
    104     {
    105         
    106            U8FLAG=2;    
    107            while((!P3_6)&&U8FLAG++);
    108         
    109         Delay_10us();
    110         Delay_10us();
    111         Delay_10us();
    112         
    113         U8temp=0;
    114          
    115         if(P3_6)U8temp=1;
    116             U8FLAG=2;
    117             
    118         while((P3_6)&&U8FLAG++);
    119 
    120            //超时则跳出for循环          
    121             if(U8FLAG==1)
    122              break;
    123 
    124            //判断数据位是0还是1
    125         // 如果高电平高过预定0高电平值则数据位为 1 
    126             
    127         U8comdata<<=1;
    128            U8comdata|=U8temp;        //0
    129     }//rof
    130        
    131 }
    132 
    133 
    134 //总线数据读取
    135 void RH(void)
    136 {
    137        //主机拉低18ms 
    138        P3_6=0;
    139        Delay(180);
    140 
    141        //总线由上拉电阻拉高 主机延时20us
    142        P3_6=1;
    143        Delay_10us();
    144        Delay_10us();
    145        Delay_10us();
    146        Delay_10us();
    147 
    148     //主机设为输入 判断从机响应信号 
    149        P3_6=1;
    150 
    151       //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行     
    152    if(!P3_6)         //T !      
    153     {
    154         U8FLAG=2;
    155         //判断从机是否发出 80us 的低电平响应信号是否结束     
    156         while((!P3_6)&&U8FLAG++);
    157 
    158         U8FLAG=2;
    159         //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
    160         while((P3_6)&&U8FLAG++);
    161 
    162 
    163         //数据接收状态         
    164         COM();
    165         U8RH_data_H_temp=U8comdata;
    166         COM();
    167         U8RH_data_L_temp=U8comdata;
    168         COM();
    169         U8T_data_H_temp=U8comdata;
    170         COM();
    171         U8T_data_L_temp=U8comdata;
    172         COM();
    173         U8checkdata_temp=U8comdata;
    174 
    175         //数据读取完后拉高总线电平
    176         P3_6=1;
    177 
    178          //数据校验
    179         U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
    180         if(U8temp==U8checkdata_temp)
    181         {
    182             U8RH_data_H=U8RH_data_H_temp;
    183             U8RH_data_L=U8RH_data_L_temp;
    184             U8T_data_H=U8T_data_H_temp;
    185             U8T_data_L=U8T_data_L_temp;
    186             U8checkdata=U8checkdata_temp;
    187         }
    188     }
    189 
    190 }
    191 
    192 
    193 //----------------------------------------------//
    194 //------------温度湿度数码管显示区--------------//
    195 //----------------------------------------------//
    196 //设置温度值
    197 void SetTemperature(unsigned char value)
    198 {
    199 
    200     unsigned char unitPlace, tenPlace;
    201 
    202     //取出个位、十位数字
    203     unitPlace = value/1%10;
    204     tenPlace = value/10;
    205     
    206     P0 = led[tenPlace];
    207     P2 = 0x7f;
    208     Delayms(4);
    209     P2 = 0xff;
    210           
    211     P0 = led[unitPlace];
    212     P2 = 0xbF;
    213     Delayms(4);
    214     P2 = 0xff;
    215 }
    216 
    217 //设置湿度值
    218 void SetHumidity(unsigned char value)
    219 {
    220     unsigned char unitPlace, tenPlace;
    221 
    222     //取出个位、十位数字
    223     unitPlace = value/1%10;
    224     tenPlace = value/10;
    225     
    226     
    227     P0 = led[tenPlace];
    228     P2 = 0xDF;
    229     Delayms(4);
    230     P2 = 0xFF;
    231           
    232     P0 = led[unitPlace];
    233     P2 = 0xEF;
    234     Delayms(4);
    235     P2 = 0xFF;
    236 }
    237 
    238 
    239 //----------------------------------------------//
    240 //-----系统初始化点亮报警灯和显示数码管---------//
    241 //-----点亮报警灯,显示数码管88------------------//
    242 //----------------------------------------------//
    243 //系统初始化
    244 void Init(void)
    245 {
    246     U8 number = 100; //闪烁频率
    247     U8 count = 0;      //计数
    248 
    249     P1_0 = 0;
    250     P1_1 = 0;
    251 
    252     while(count < number)
    253     {
    254         //设置温度
    255         SetTemperature(88);
    256         //设置湿度
    257         SetHumidity(88);
    258 
    259         count++;
    260     }
    261 
    262     Delayms(500);
    263 
    264     P1_0 = 1;
    265     P1_1 = 1;
    266 
    267 }
    268 
    269     
    270 //----------------------------------------------//
    271 //----------温度湿度读取和显示控制--------------//
    272 //----------------------------------------------//
    273 void main()
    274 {
    275 
    276     //报警值区域
    277     U8 tempAlarmMin = 20;
    278     U8 tempALarmMax = 32;
    279     U8 HumidityMin = 45;
    280     U8 HumidityMax = 65;
    281     
    282     //显示循环次数
    283     U8 number = 250; 
    284     U8 count = 0;      
    285 
    286     //系统初始化
    287     Init();
    288     
    289     while(1)
    290     { 
    291            count =0;
    292 
    293            //调用温湿度读取子程序 
    294            RH();
    295 
    296            
    297            if(U8T_data_H > tempALarmMax || U8T_data_H < tempAlarmMin)
    298            {
    299                 P1_0 = 0;
    300            }
    301            else
    302            {
    303                P1_0 = 1;
    304            }
    305 
    306         if(U8RH_data_H < HumidityMin || U8RH_data_H > HumidityMax)
    307         {
    308             P1_1 = 0;
    309         }
    310         else
    311         {
    312             P1_1 = 1;
    313         }
    314         
    315        //读取模块数据周期不易小于 2S 所以这里循环显示2s后读取      
    316        while(count < number)
    317        {
    318             //设置温度
    319             SetTemperature(U8T_data_H);
    320             //设置湿度
    321             SetHumidity(U8RH_data_H);
    322 
    323             count++;
    324        }
    325        
    326 
    327     }
    328     
    329 }
    View Code

    电路大概介绍

  • 相关阅读:
    Jenkins+ant循环执行jmeter文件
    Jmeter接口模版说明
    jenkins与远程服务器配置SSH免密登录
    xcode developer tools简介
    MySQL之模糊查询
    MySQL排名函数
    openblas下载安装与使用
    CVX安装使用
    AMD包下载及使用
    Python及相应软件安装
  • 原文地址:https://www.cnblogs.com/JiYF/p/12555161.html
Copyright © 2011-2022 走看看