F407系列DHT22温湿度驱动移植


前言

和DHT11一样,都是单总线,通过判断电平变化时间来确定0,1。只需要在dht22.h中修改dht_IO和dht_gpio即可。


详细资料参考微雪电子官网https://www.waveshare.net/wiki/DHT22_Temperature-Humidity_Sensor

一、dht22单总线通信时序

在这里插入图片描述

在这里插入图片描述

废话不多说,我们对着参考手册来写简单的驱动代码

二、使用步骤

步骤一:

发送我们的主机信号,告诉传感器该上班了。

对应上面的时序图应该显而易见,先将SDA拉低保持1ms,再释放SDA保持20us,但是我们参考表6,还是保持30us好。

void dht22_start()
{
    dht22_gpio_Init_out();
    GPIO_ResetBits(dht_IO,dht_gpio);
    delay_ms(1);
    GPIO_SetBits(dht_IO,dht_gpio);
    delay_us(30);
}


步骤二:

主机已经喊了,那传感器总要应答。不能让别人单方面付

那么我们怎么判断收没收到呢,厂家规定了,先检测80us低电平如果之后的80us是高电平那说明是应答信号

下面的代码也不难理解,如果是低电平那么就进入判断,如果不是低电平说明一开始的80us低电平都不满足那就直接返回错误。

进入条件之后 我们每1us就让cnt++,参考表6最大值是85,那我们设置成85也没关系嘛,反正在范围里面,然后大家也可以试试其他的数,看看有没有影响。如果大于85说明也是需要返回错误。那么我们的第一个条件80us就判断完毕了,那么就判断第二个条件80us的高电平,所以在此之前将cnt清0。同样的道理,这里就不说了

uint8_t dht22_Recive_Ack()
{
    
    uint8_t cnt = 0;
   
    dht22_gpio_Init_in();
    if(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == Bit_RESET)     //如果检测80us低电平之后80us高电平,那么说明是应答信号
    {
        
        while( (cnt<=85) && ( !GPIO_ReadInputDataBit(dht_IO,dht_gpio) ))
        {
            cnt++;
            delay_us(1);
            
        }
        if(cnt > 85) {return 0;}
        else {cnt = 0;}
        
        while(GPIO_ReadInputDataBit(dht_IO,dht_gpio) && (cnt<= 85 ))
        {
            cnt++;
            delay_us(1);
        }
        if(cnt > 85) {return 0;}
        else {cnt = 0;return 1;}
            
    }
    else 
    {
        
        return 0;
    }
}

步骤三:

那我主机和传感器已经双向奔赴了,就要开始干一点正事了吧,那么主机怎么知道传感器发送的是0还是1呢

可以看到表6已经给出了解释,0,1的低电平时间都是50,那我50+26 那说明我是0,我50+70说明我是1。那既然0,1已经知道怎么区分了,那我们来看看读取

因为我们dht11和dht22一样,总共传输40位,其中温度整数、小数、湿度整数、小数,校验五个,所以每一个都是8位数据。

然后就开始判断嘛,首先给45us的低电平,为什么是45s的低电平呢,因为可以看到0的高电平最大为30,1的高电平最大为75,朋友们可以在中间取一个数值当做判断条件,看看会不会影响。

如果大于45之后还是高电平那说明就是1,我们等待电平结束,然后就数据每次左移1位。
如果大于45之后不是高电平那说明是0,我们也让数据左移,再取反,因为我们低电平要的是0。

朋友们也可以试着用其他方法写,下面是我提供的另一个写法,会不会看起来简洁一点。

for(i =0;i<8;i++)
    {
       dht22_byte <<= 1;
        while(!GPIO_ReadInputDataBit(dht_IO,dht_gpio));
        Delay_us(45);
        GPIO_ReadInputDataBit(dht_IO,dht_gpio) ? (dht22_byte |= 0x01) : (dht22_byte &=~0x01);
        while(GPIO_ReadInputDataBit(dht_IO,dht_gpio));
    }
uint8_t dht22_read_byte()
{
    uint8_t i,dht22_byte;
    for(i = 0;i<8;i++)
    {
        while(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == 0);
        delay_us(45);
        if(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == 1)        
        {
            while(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == 1);
            dht22_byte |= (uint8_t)(0x01<<(7-i));           // 1
        }
        else 
        {
            dht22_byte &= (uint8_t)~(0x01 << (7-i));     // 0
        }
    }
    return dht22_byte;
}

步骤四:

最后一步也是我们说的40位需要5次读取

在这里插入图片描述

uint8_t dht22_read_data()
{
    dht22_start();
    if(dht22_Recive_Ack() == 1)
    {
        
        dht22_data[0] = dht22_read_byte();
        dht22_data[1] = dht22_read_byte();
        dht22_data[2] = dht22_read_byte();
        dht22_data[3] = dht22_read_byte();
        dht22_data[4] = dht22_read_byte();
    }
    
    dht22_gpio_Init_out();
    GPIO_SetBits(dht_IO,dht_gpio);
  
    if(dht22_data[4] == (uint8_t)(dht22_data[0] +  dht22_data[1] + dht22_data[2] + dht22_data[3]))
    {
        humi = (float)((256*dht22_data[0]+dht22_data[1] )/ 10);
        tem = (float)((256*dht22_data[2]+dht22_data[3] )/ 10);
        
        return 1;
    }
    else  return 0;
       
}

注:一定要注意在协议中调试会不会影响时序

.c和.h文件,修改端口和引脚即可食用

#include "stm32f4xx.h"                  // Device header
#include "dht22.h"
#include "delay.h"
#include "usart.h"

uint8_t dht22_data[5];
float tem,humi;
void dht22_gpio_Init_out()
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef GPIO_InitSturcture;
    
    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitSturcture.GPIO_OType = GPIO_OType_PP;
    GPIO_InitSturcture.GPIO_Pin = dht_gpio;
    GPIO_InitSturcture.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
    
    GPIO_Init(dht_IO,&GPIO_InitSturcture);
}

void dht22_gpio_Init_in()
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef GPIO_InitSturcture;
    
    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitSturcture.GPIO_Pin = dht_gpio;
    GPIO_InitSturcture.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(dht_IO,&GPIO_InitSturcture);
}

void dht22_start()
{
    dht22_gpio_Init_out();
    GPIO_ResetBits(dht_IO,dht_gpio);
    delay_ms(1);
    GPIO_SetBits(dht_IO,dht_gpio);
    delay_us(30);
}

uint8_t dht22_Recive_Ack()
{
    
    uint8_t cnt = 0;
   
    dht22_gpio_Init_in();
    if(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == Bit_RESET)     //如果检测80us低电平之后80us高电平,那么说明是应答信号
    {
        
        while( (cnt<=85) && ( !GPIO_ReadInputDataBit(dht_IO,dht_gpio) ))
        {
            cnt++;
            delay_us(1);
            
        }
        if(cnt > 85) {return 0;}
        else {cnt = 0;}
        
        while(GPIO_ReadInputDataBit(dht_IO,dht_gpio) && (cnt<= 85 ))
        {
            cnt++;
            delay_us(1);
        }
        if(cnt > 85) {return 0;}
        else {cnt = 0;return 1;}
            
    }
    else 
    {
        
        return 0;
    }
}


uint8_t dht22_read_byte()
{
    uint8_t i,dht22_byte;
    for(i = 0;i<8;i++)
    {
        while(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == 0);
        delay_us(40);
        if(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == 1)        
        {
            while(GPIO_ReadInputDataBit(dht_IO,dht_gpio) == 1);
            dht22_byte |= (uint8_t)(0x01<<(7-i));           // 1
        }
        else 
        {
            dht22_byte &= (uint8_t)~(0x01 << (7-i));     // 0
        }
    }
    return dht22_byte;
}


uint8_t dht22_read_data()
{
    dht22_start();
    if(dht22_Recive_Ack() == 1)
    {
        
        dht22_data[0] = dht22_read_byte();
        dht22_data[1] = dht22_read_byte();
        dht22_data[2] = dht22_read_byte();
        dht22_data[3] = dht22_read_byte();
        dht22_data[4] = dht22_read_byte();
    }
    
    dht22_gpio_Init_out();
    GPIO_SetBits(dht_IO,dht_gpio);
    
    
    
    //printf("%d,%d,%d,%d---%d\r\n",dht22_data[0],dht22_data[1],dht22_data[2],dht22_data[3],dht22_data[4]);
    
    if(dht22_data[4] == (uint8_t)(dht22_data[0] +  dht22_data[1] + dht22_data[2] + dht22_data[3]))
    {
        humi = (float)((256*dht22_data[0]+dht22_data[1] )/ 10);
        tem = (float)((256*dht22_data[2]+dht22_data[3] )/ 10);
        
        printf("humi:%f,tem:%f\r\n",humi,tem);
        return 1;
    }
    else  return 0;
       
}


#ifndef __DHT22_H
#define __DHT22_H

#define dht_IO       GPIOA
#define dht_gpio     GPIO_Pin_6


void dht22_gpio_Init_out();
void dht22_gpio_Init_in();


void dht22_start();
uint8_t dht22_Recive_Ack();
uint8_t dht22_read_byte();
uint8_t dht22_read_data();
#endif




总结

dht22模块驱动和dht11模块驱动相差不大,大家也可以学习完dht11之后根据提供的数据手册自行编写驱动

然后一定要注意!!!!一定要注意!!!!一定要注意!!!!在函数中打印数据调试的前提是不会影响到时序!!!!

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值