dht11采集温湿度

简单的分析第二张图--时序图,通信过程就是:

MCU发送起始信号,MCU等待响应,MCU等待DHT11测量完毕,MCU读取测量结果,结束一次通信

主机发送起始信号:主机发送至少18ms的低电平;

从机等待主机释放总线:主机把总线拉高,延时20~40us;

主机读取响应;

主机读取数据:每一bit数据以5us的低电平开始,数据是0还是1由高电平时长决定;

当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。

代码如下:

.c文件

void DHT11_Init()
{
    delay_ms(1000); //等待1S以越过不稳定状态在此期间不能发送任何指令    
    DHT11_Output(); //主机发开始信号
}

void DHT11_Output()
{
    GPIO_InitTypeDef dht11;  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    dht11.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
    dht11.GPIO_Pin=GPIO_Pin_6 ;//PB6
    dht11.GPIO_Speed=GPIO_Speed_50MHz; //高速
    GPIO_Init(GPIOB,&dht11); 
}

//主机发起始信号
void DHT11_Start()
{    
    GPIO_ResetBits(GPIOB,GPIO_Pin_6); //低电平 
    delay_ms(18); //微处理器的 I/O 设置为输出同时输出低电平,低电平保持时间不能小于18ms(最大不得超过 30ms)
    GPIO_SetBits(GPIOB,GPIO_Pin_6); //拉高等待
    delay_us(20); //从机等待主机释放总线:主机把总线拉高,延时20~40us
}

//DHT11发出信号,主机接收信号,切换输入模式
void DHT11_Input()
{
    GPIO_InitTypeDef dht11; 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    
    dht11.GPIO_Mode=GPIO_Mode_IN_FLOATING; //上拉输入  输入上拉:引脚为输入模式,引脚输入状态默认为高电平
    dht11.GPIO_Pin=GPIO_Pin_6 ;
    dht11.GPIO_Speed=GPIO_Speed_50MHz; //高速
    GPIO_Init(GPIOB,&dht11); //根据key配置的参数初始化外设GPIOA寄存器         
}
u8 DHT11_Readbyte()
{
    int i;
    u8 data=0; //读到保存的一个字节
    for(i=0;i<8;i++) //8位
    {
        while(!(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6))); //等待54us低电平时间过去
        delay_us(40); //再延时,判断是否为高电平
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1) //延时过后,确定为高电平,把1存起来
        {
            while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等待高电平结束
            data |=1<<(7-i);
        }
    }
    return data; //返回读到的字节数据
}

int DHT11_GetTH(u8 buf[])
{
    u8 check=0;
    int n=0; 
    DHT11_Output();
    DHT11_Start();
    DHT11_Input();
    //单片机(主机)等待从机响应,单片机读PB6引脚为低电平
    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)) //等待从机响应低电平 
    {
        delay_us(1);
        n++;
        if(n>100)
            return 1; //不响应
    }
    while(!(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6))); //等响应后的低电平时间完全过去
    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等待80us的高电平过去
    
    //单片机读取40位数据--8位1个字节
    buf[0]=DHT11_Readbyte(); //湿度的高位字节
    buf[1]=DHT11_Readbyte(); //湿度的低位字节
    buf[2]=DHT11_Readbyte(); //温度的高位字节
    buf[3]=DHT11_Readbyte(); //温度的低位字节
    check=DHT11_Readbyte();  
    //释放总线
    DHT11_Output(); //变成输出模式
    GPIO_SetBits(GPIOB,GPIO_Pin_6);  //拉高--高电平
    if((buf[0]+buf[1]+buf[2]+buf[3])==check)    
    {
        return 0; //采集数据成功
    }
    else
    {
        return 2; //校验不成功
    }
}

main函数
int main(void)  //主函数  
{
    u8 data[4];
    int temp=0;
    float T=0,H=0;
    systick_init(); //系统滴答时钟初始化
    USART1_Init(9600); //串口通信初始化
    DHT11_Init();
    
    while (1)
    {    
        temp=DHT11_GetTH(data);
        if(temp==0)
        {
            printf("采集校验成功!%d\r\n",temp);
            H=data[0]+(data[1]/100.0);
            T=data[2]+(data[3]/100.0);
            printf("温度:%.2f,湿度:%.2f\r\n",T,H);
        }
        delay_ms(2000);

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值