STM32
直播中

王秀兰

8年用户 1462经验值
私信 关注
[问答]

请问STM32F103C8T6如何通过DHT11获取温湿度数据?

请问STM32F103C8T6如何通过DHT11获取温湿度数据?

回帖(1)

席连施

2021-11-25 14:34:50
dht11简易获取温湿度数据
DHT11数据格式

采集范围:温度0-50°±2°,湿度:20-90%RH。
精度:湿度±5%RH, 温度±2℃
采用单总线双向串行通信协议,每次采集都要由单片机发起开始信号,然后DHT11会向单片机发送响应并开始传输40位数据帧。
如接收到的 40 位数据为:
0011 0101 0000 0000 0001 1000 0000 0100 0101 0001
湿度高 8 位 湿度低 8 位 温度高 8 位 温度低 8 位 校验位
校验位为“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据” 8bit 校验位等于所得结果的末 8 位
校验计算
0011 0101+0000 0000+0001 1000+0000 0100= 0101 0001 则接收数据正确
湿度: 0011 0101(整数)=35H=53%RH 0000 0000(小数)=00H=0.0%RH =>53%RH + 0.0%RH =
53.0%RH
温度: 0001 1000(整数)=18H=24℃ 0000 0100(小数)=04H=0.4℃ =>24℃ + 0.4℃ = 24.4℃
DHT11时序:






时序流程详解:
1.主机把总线拉低大于18ms,保证DHT11能检测。
2.主机拉高等待延时20us-40us。
3.DHT11若有响应,会返回给主机低电平接近80us,即响应信号。
4.DHT11返回给主机高电平80us,准备发送数据给主机。
5.发送的数据每1bit之间间隙为50us,当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
数据格式
发送的数据如何判断为0还是1呢,由发送时高电平的持续时长决定。





检测高电平为70us,即为1.





检测高电平为26us-28us,即为0
硬件连接






本实验以PA1连接DHT11的DQ引脚

部分代码
按照之前的时序详解来说明:


时序流程一,二步:
1


void DHT11_Rst(void)   
{                 
   DHT11_IO_OUT(); //设置GPIOA1为输出
    DHT11_DQ_Low; //DQ=0
    delay_ms(20);    //拉低至少18ms
    DHT11_DQ_High; //DQ=1
delay_us(30);     //主机拉高20~40us
}


时序流程三,四步:


u8 DHT11_Check(void)   
{   
u8 retry=0;//定义临时变量
DHT11_IO_IN();//SET INPUT
    while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//DHT11会拉低40~80us
        {
                retry++;
                printf("%s %dn",__FUNCTION__,__LINE__);//方便在串口中观察错误是否DHT11未响应
                delay_us(1);
        };
if(retry>=100)return 1; //并无响应
else retry=0;//有响应
               
        while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//DHT11拉低后会再次拉高40~80us
        {
                retry++;
                delay_us(1);
        };
if(retry>=100)return 1;   //拉高过久还未发送数据给主机
return 0;
}


时序流程第五部,读取一位:
1
u8 DHT11_Check(void)   
{   
u8 retry=0;//定义临时变量
DHT11_IO_IN();//SET INPUT
    while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//DHT11会拉低40~80us
                                {
                        retry++;
                                        printf("%s %dn",__FUNCTION__,__LINE__);//方便在串口中观察错误是否DHT11未响应
                        delay_us(1);
                        };
if(retry>=100)return 1; //并无响应
else retry=0;//有响应
               
                        while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//DHT11拉低后会再次拉高40~80us
                                {
                                retry++;
                                delay_us(1);
                                };
if(retry>=100)return 1;   //拉高过久还未发送数据给主机
return 0;
}
//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void)  
{
u8 retry=0;
        while((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//等待变为低电平,数据间隙
                {
                        retry++;
                        delay_us(1);
                }
retry=0;
        while((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//等待变高电平,数据
                {
                        retry++;
                        delay_us(1);
                }
delay_us(40);//等待40us
if(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1) return 1;  //若还为高电平,数据为1
else return 0;   //数据为0
}


读取一字节函数:
1
u8 DHT11_Read_Byte(void)   
{        
    u8 i,dat;
    dat=0;
for (i=0;i<8;i++)
{
   dat<<=1;
    dat|=DHT11_Read_Bit(); //8位
    }   
    return dat;  //返回8位
}


读取一次数据函数,校验并存储数据道buf中:


u8 DHT11_Read_Data(u8 *temp,u8 *humi)   
{        
u8 buf[5];
u8 i;
DHT11_Rst(); //时序流程一,二步。
if(DHT11_Check()==0) //有响应
{
                for(i=0;i<5;i++)//读取40位数据
                {
                        buf=DHT11_Read_Byte();
                }
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])  //校验成功
                {
                *humi=buf[0];  //湿度高16位
                *temp=buf[2]; // 温度的16位
                }
}
else return 1; //失败
return 0;    //成功
}


各类初始化:


void DHT11_Init(void)
{     
DHT11_Rst();  //复位DHT11
DHT11_Check();//等待DHT11的回应
}


还有初始化PA1位模拟输入和推挽输出的函数,就不列出了
DHT11_IO_IN();//设置输入
DHT11_IO_OUT();//设置输出


main
1
int main
{         
         u8 wd=0;      
     u8 sd=0;
         DHT11_Init();
         USART1_config(115200);
           while(1)
           {
           DHT11_Read_Data(&wd,&sd);//读取温湿度值   
           printf("temp = %d  humi =%dn",wd,sd);               
           delay_ms(1000);
           delay_ms(1000);
           }
  }


结果



举报

更多回帖

×
20
完善资料,
赚取积分