[开发工具] DHT11读写

[复制链接]
 楼主| claretttt 发表于 2024-8-20 21:34 | 显示全部楼层 |阅读模式



  1. #define uchar unsigned char
  2. #define uint unsigned int


  3. sbit Data=P1^0; //数据线
  4. uchar rec_dat[9]; //储存数据
  5. void Delay2us()                //@32MHz
  6. {
  7.         _nop_();
  8. }

  9. void Delay8us()                //@32MHz
  10. {
  11.         unsigned char i;

  12.         i = 8;
  13.         while (--i);
  14. }
  15. void Delay25us()                //@32MHz
  16. {
  17.         unsigned char i;

  18.         _nop_();
  19.         i = 30;
  20.         while (--i);
  21. }
  22. void Delay30us()                //@32MHz
  23. {
  24.         unsigned char i;

  25.         _nop_();
  26.         i = 37;
  27.         while (--i);
  28. }

  29. void Delay40us()                //@32MHz
  30. {
  31.         unsigned char i;

  32.         _nop_();
  33.         i = 50;
  34.         while (--i);
  35. }



  36. /*
  37. 主机(单片机)发送起始信号:
  38. 1.主机先拉高data。
  39. 2.拉低data延迟18ms。
  40. 3.拉高data并延迟等待(通过此操作将单片机引脚设置为输入)。
  41. */
  42. void DHT11_start(void)
  43. {
  44.    Data=1;
  45.    Delay2us();
  46.    Data=0;
  47.    Delay25us();   //拉低延时18ms以上
  48.    Data=1;
  49.    Delay30us();   //拉高 延时 20~40us,取中间值 30us
  50. }

  51. /*------------------------------------------------
  52.               接收八位二进制
  53. ------------------------------------------------*/
  54. uchar DHT11_rec_byte(void)      //接收一个字节
  55. {
  56.   unsigned char i,dat=0;
  57.   for(i=0;i<8;i++)    //从高到低依次接收8位数据
  58.    {         
  59.       while(Data);   //等待进入低电平
  60.       while(!Data);   //等待50us低电平过去
  61.       Delay8us();     //延时60us,如果还为高则数据为1,否则为0
  62.       dat<<=1;//移位(低位补零)使正确接收8位数据,数据为0时直接移位
  63.       if(Data==1)    //数据为1时,使dat加1来接收数据1
  64.         dat+=1;
  65.       while(Data);  //等待数据线拉低   
  66.    }  
  67.     return dat;
  68. }


  69. /*------------------------------------------------
  70.               接收40bit数据(具体的温湿度)
  71. 1.主机先把data线拉高(io设置为输入)。
  72. 2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)
  73.   从机拉高data线后,延迟40us左右(28~70us之间)主机再次读取data线电平,如果为低电平,则为“0”,如果为高电平,则为“1”。
  74. 3.继续重复上述1,2步骤累计40次。
  75. ------------------------------------------------*/
  76. uchar T_H;
  77. void DHT11_receive(void)      //接收40位的数据
  78. {
  79.     uchar R_H,R_L,T_L,RH,RL,TH,TL,revise;
  80.     DHT11_start();//发送起始信号:
  81.     if(Data==0)
  82.     {
  83.         while(Data==0);   //等待拉高     
  84.         Delay40us();  //拉高后延时80us
  85.                        
  86.         R_H=DHT11_rec_byte();    //接收湿度高八位  
  87.         R_L=DHT11_rec_byte();    //接收湿度低八位  
  88.         T_H=DHT11_rec_byte();    //接收温度高八位  
  89.         T_L=DHT11_rec_byte();    //接收温度低八位
  90.         revise=DHT11_rec_byte(); //接收校正位

  91.         Delay25us();    //结束

  92.         if((R_H+R_L+T_H+T_L)==revise)      //最后一字节为校验位,校验是否正确
  93.         {
  94.             RH=R_H;
  95.             RL=R_L;
  96.             TH=T_H;
  97.             TL=T_L;
  98.         }
  99.                                
  100.         /*数据处理,转换为字符,方便显示*/
  101.                 //湿度
  102.                 rec_dat[0]=(28);
  103.                 rec_dat[1]=(5);
  104.                 rec_dat[2]=' ';
  105.                 rec_dat[3]=' ';

  106.                 //温度
  107.                 rec_dat[4]='0'+(TH/10);
  108.                 rec_dat[5]='0'+(TH%10);
  109.                 rec_dat[6]=' ';
  110.                        
  111.     }

  112. }


  1. void main(void)
  2. {       

  3.     IcResourceInit();
  4.         ADC_Init1(0x08);
  5.         TR0=0;关闭模式0和1的中断源
  6.     ET0=0;
  7.     TRX=0;
  8.     ET2=0;
  9.     IE1 &=~0x08;
  10.     OLED_Init();        
  11.     OLED_Clear();

  12.        
  13.        
  14.     while(1)
  15.     {

  16. #if(TestMode==1)
  17.                 GetADCValue();
  18.                 OLED_ShowCHinese( 2 , 0 , 0 );
  19.                 OLED_ShowCHinese( 20 , 0 , 1 );
  20.                 OLED_ShowCHinese( 36 , 0 , 2 );
  21.                 OLED_ShowCHinese( 84 , 0 , 9 );
  22.                 OLED_ShowCHinese( 102 , 0 , 10 );
  23. //                OLED_ShowString(10,2,CharData,16);
  24.         DHT11_receive();
  25.                 OLED_ShowNum(40,4,rec_dat[5],6,16);   //}  
  26.                 OLED_ShowNum(10,4,rec_dat[4],6,16);
  27.       
  28.             OLED_ShowNum(40,4,rec_dat[1],6,16);   //}  
  29.                 OLED_ShowNum(10,4,rec_dat[0],6,16);
  30. ;

  31. #endif


  32.     }

  33. }


小夏天的大西瓜 发表于 2024-8-21 23:02 | 显示全部楼层
程序非常清晰明了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

1656

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部