claretttt 发表于 2024-8-20 21:34

DHT11读写




#define uchar unsigned char
#define uint unsigned int


sbit Data=P1^0; //数据线
uchar rec_dat; //储存数据
void Delay2us()                //@32MHz
{
        _nop_();
}

void Delay8us()                //@32MHz
{
        unsigned char i;

        i = 8;
        while (--i);
}
void Delay25us()                //@32MHz
{
        unsigned char i;

        _nop_();
        i = 30;
        while (--i);
}
void Delay30us()                //@32MHz
{
        unsigned char i;

        _nop_();
        i = 37;
        while (--i);
}

void Delay40us()                //@32MHz
{
        unsigned char i;

        _nop_();
        i = 50;
        while (--i);
}



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

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


/*------------------------------------------------
            接收40bit数据(具体的温湿度)
1.主机先把data线拉高(io设置为输入)。
2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)
从机拉高data线后,延迟40us左右(28~70us之间)主机再次读取data线电平,如果为低电平,则为“0”,如果为高电平,则为“1”。
3.继续重复上述1,2步骤累计40次。
------------------------------------------------*/
uchar T_H;
void DHT11_receive(void)      //接收40位的数据
{
    uchar R_H,R_L,T_L,RH,RL,TH,TL,revise;
    DHT11_start();//发送起始信号:
    if(Data==0)
    {
      while(Data==0);   //等待拉高   
      Delay40us();//拉高后延时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(); //接收校正位

      Delay25us();    //结束

      if((R_H+R_L+T_H+T_L)==revise)      //最后一字节为校验位,校验是否正确
      {
            RH=R_H;
            RL=R_L;
            TH=T_H;
            TL=T_L;
      }
                               
      /*数据处理,转换为字符,方便显示*/
                //湿度
                rec_dat=(28);
                rec_dat=(5);
                rec_dat=' ';
                rec_dat=' ';

                //温度
                rec_dat='0'+(TH/10);
                rec_dat='0'+(TH%10);
                rec_dat=' ';
                       
    }

}


void main(void)
{       

    IcResourceInit();
        ADC_Init1(0x08);
        TR0=0;关闭模式0和1的中断源
    ET0=0;
    TRX=0;
    ET2=0;
    IE1 &=~0x08;
    OLED_Init();      
    OLED_Clear();

       
       
    while(1)
    {

#if(TestMode==1)
                GetADCValue();
                OLED_ShowCHinese( 2 , 0 , 0 );
                OLED_ShowCHinese( 20 , 0 , 1 );
                OLED_ShowCHinese( 36 , 0 , 2 );
                OLED_ShowCHinese( 84 , 0 , 9 );
                OLED_ShowCHinese( 102 , 0 , 10 );
//                OLED_ShowString(10,2,CharData,16);
      DHT11_receive();
                OLED_ShowNum(40,4,rec_dat,6,16);   //}
                OLED_ShowNum(10,4,rec_dat,6,16);
      
          OLED_ShowNum(40,4,rec_dat,6,16);   //}
                OLED_ShowNum(10,4,rec_dat,6,16);
;

#endif


    }

}

小夏天的大西瓜 发表于 2024-8-21 23:02

程序非常清晰明了
页: [1]
查看完整版本: DHT11读写