1、使用小熊派(BearPi-HM_Nano)驱动DHT11

 DHT11时序讲解(很详细):

https://blog.csdn.net/qq_21990661/article/details/81043121

时序对应代码:

 首先小熊派给DHT11发送启动时序,如图,拉低大于18ms后再拉高即可。

 启动时序对应代码如下所示:

GpioInit();//初始化
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13,WIFI_IOT_IO_FUNC_GPIO_13_GPIO);
IoSetPull(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_PULL_UP);
GpioSetDir(WIFI_IOT_GPIO_IDX_13,WIFI_IOT_GPIO_DIR_OUT);
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_13,0);//拉低并延时 大于18ms
osDelay(2U);//貌似100U = 1s
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_13,1);//拉高
delay_us(30);     	       //拉高20~40us 

若DHT11正确接收到启动信号,会拉低总线80us后,再拉高80us,通知接收数据。

 小熊派接收DHT11响应代码:

    /*等待低电平的到来*/
    GpioSetDir(WIFI_IOT_GPIO_IDX_13,WIFI_IOT_GPIO_DIR_IN);
    GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
    int num=0;
    while(inputdata&&num<=100)
    {
        num++;
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
    }
    if(num>100)return 0;//大于100表示DHT11未启动成功

    /*接收80us低电平*/
    while(!inputdata&&timer<=100)
    {
        timer++;
        delay_us(1);
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
    }

    if (timer>100 || timer<20) //判断响应时间
    {
        return 0;
    }

    /*接收80us高电平*/
    timer = 0;
    while(inputdata&&timer<=100)
    {
        timer++;
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
        delay_us(1);
    }
    if (timer>100 || timer<20) //检测响应信号之后的高电平
    {
        return 0;
    }
    return 1;//成功启动

 成功接收DHT11响应信号后,DHT11开始按照高位在前的顺序,将数据一位一位传给主机。

 可以看到数据“0”和数据“1”的差别在于高电平的持续时间,可以通过高电平持续时间内变量累计次数来确定数据“0”,“1”。

上述链接文章详细描述了数据格式。数据共40位,分5次接收,一次接收一字节,即8位。 

读取一字节的代码如下所示:

    for (i=0; i<8; i++)
    {
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
        int num=0;
        while (inputdata&&num<=100)  //等待低电平,数据位前都有50us低电平时隙
        {
            GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
            num++;
        }
        num=0;
        while (!inputdata&&num<=100) //等待高电平,开始传输数据位
        {
            GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
            num++;
        }
        num=0;
        while(inputdata&&num<=80)
        {
            GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
            num++;
        }
        byt <<= 1;         //因高位在前,所以左移byt,最低位补0
        if (num>30)      //将总线电平值读取到byt最低位中
        {
            byt |= 0x01;
        }
    }

 读取所有数据:首先检测DHT11是否能正常响应,后读取5字节即40位数据,读完后,按照数据格式进行校验。

    if (DHT11RstAndCheck())         //检测响应信号
    {
        for(i=0;i<5;i++)            //读取40位数据
        {
            buf[i]=DHT11ReadByte(); //读取1字节数据
        }
        if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校验成功
        {
            *Humi = buf[0];         //保存湿度整数部分数据
            *Temp = buf[2];         //保存温度整数部分数据
        }
        sta = 1;
    }
    else //响应失败返回-1
    {
        *Humi = 0xFF; //响应失败返回255
        *Temp = 0xFF; //响应失败返回255
        sta = -1;
    }

总代码: 

DHT11.h、

#ifndef _DHT11_H
#define _DHT11_H
#include "utils_config.h"

#define  DHT11_OUT  PC_OUT(13)
#define  DHT11_IN   PC_IN(13)

int DHT11Init(void);
int DHT11ReadData(int *Humi,int *Temp);
int DHT11RstAndCheck(void);
void delay_us(int num);
#endif

DHT11.c、

#include "dht11.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_adc.h"
#include <stdio.h>
#include "cmsis_os2.h"
#include <ohos_init.h>
#include <unistd.h>
#include <time.h>
/*DHT11复位和检测响应函数,返回值:1-检测到响应信号;0-未检测到响应信号*/
WifiIotGpioValue inputdata={0};
WifiIotGpioValue outputdata={0};
int DHT11RstAndCheck(void)
{
     int timer = 0;
    GpioInit();
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13,WIFI_IOT_IO_FUNC_GPIO_13_GPIO);
    IoSetPull(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_PULL_UP);
    GpioSetDir(WIFI_IOT_GPIO_IDX_13,WIFI_IOT_GPIO_DIR_OUT);
    GpioSetOutputVal(WIFI_IOT_GPIO_IDX_13,0);
    osDelay(2U);
    GpioSetOutputVal(WIFI_IOT_GPIO_IDX_13,1);
     delay_us(30);     	       //拉高20~40us  
    GpioSetDir(WIFI_IOT_GPIO_IDX_13,WIFI_IOT_GPIO_DIR_IN);
    GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
    int num=0;
    while(inputdata&&num<=100)
    {
        num++;
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
    }
    if(num>100)return 0;
    while(!inputdata&&timer<=100)
    {
        timer++;
        delay_us(1);
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
    }

    if (timer>100 || timer<20) //判断响应时间
    {
        return 0;
    }
    timer = 0;
    while(inputdata&&timer<=100)
    {
        timer++;
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
        delay_us(1);
    }
    if (timer>100 || timer<20) //检测响应信号之后的高电平
    {
        return 0;
    }
    return 1;
}


// /*读取一字节数据,返回值-读到的数据*/
int DHT11ReadByte(void)
{
    uint8_t i;
    int byt = 0;
    for (i=0; i<8; i++)
    {
        GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
        int num=0;
        while (inputdata&&num<=100)  //等待低电平,数据位前都有50us低电平时隙
        {
            GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
            num++;
        }
        num=0;
        while (!inputdata&&num<=100) //等待高电平,开始传输数据位
        {
            GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
            num++;
        }
        num=0;
        while(inputdata&&num<=80)
        {
            GpioGetInputVal(WIFI_IOT_GPIO_IDX_13,&inputdata);
            num++;
        }
        byt <<= 1;         //因高位在前,所以左移byt,最低位补0
        if (num>30)      //将总线电平值读取到byt最低位中
        {
            byt |= 0x01;
        }
    }

    return byt;
}

// /*读取一次数据,返回值:Humi-湿度整数部分数据,Temp-温度整数部分数据;返回值: -1-失败,1-成功*/
int DHT11ReadData(int *Humi, int *Temp)
{
    //printf("access\n");
    int sta = 0;
    uint8_t i;
    int buf[5];

    if (DHT11RstAndCheck())         //检测响应信号
    {
        for(i=0;i<5;i++)            //读取40位数据
        {
            buf[i]=DHT11ReadByte(); //读取1字节数据
        }
        if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校验成功
        {
            *Humi = buf[0];         //保存湿度整数部分数据
            *Temp = buf[2];         //保存温度整数部分数据
        }
        sta = 1;
    }
    else //响应失败返回-1
    {
        *Humi = 0xFF; //响应失败返回255
        *Temp = 0xFF; //响应失败返回255
        sta = -1;
    }
    return sta;    
}
//应该延时了1us吧
void delay_us(int num)
{
    while(num--)
    {
        for(int i=0;i<25;i++){}
    }
}

直接调用就好啦

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值