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

 DHT11时序讲解(很详细):

https://blog.youkuaiyun.com/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++){}
    }
}

直接调用就好啦

### 基于Arduino的小熊派智慧农业项目设计方案 #### 1. 系统概述 小熊派智慧农业项目旨在通过物联网技术实现农业生产过程中的智能化管理。该项目利用Arduino作为核心控制器,连接各种传感器和执行器来监测并控制环境参数,从而提高作物产量和质量。 #### 2. 主要组件 - **硬件部分** - Arduino Uno/Nano板卡:用于数据采集与处理的核心设备[^1]。 - 温湿度传感器(DHT11/DHT22):测量空气温度和相对湿度。 - 土壤水分传感器:检测土壤含水量以便及时灌溉。 - 光照强度传感器(LDR):评估光照条件影响植物生长情况。 - 继电器模块:驱动水泵或其他外部负载工作。 - **软件部分** - 使用Arduino IDE编写程序逻辑,完成对各个外设的操作以及网络通信功能的配置。 - 可选地,在云端部署监控平台(如阿里云IoT Studio),实现实时远程查看现场状态变化趋势图等功能。 #### 3. 功能描述 - 自动化浇水系统会依据设定阈值自动开启/关闭水源供应;当土壤湿度过低时启动喷淋装置补充适量水份直至恢复正常水平为止。 - 数据记录仪能够定时保存温湿度、光强等重要指标的历史数值到SD卡内供日后分析研究之用。 - 用户可以通过手机APP随时随地掌握温室内部状况,并手动调整相应设置满足特殊需求。 ```cpp // 示例代码片段展示如何读取DHT11传感器的数据并通过串口打印出来 #include "DHT.h" #define DHTPIN 2 // 定义DHT传感器所接引脚编号 #define DHTTYPE DHT11 // 设置使用的具体型号为DHT11 DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); dht.begin(); } void loop() { float h = dht.readHumidity(); // 获取当前湿度百分比 float t = dht.readTemperature();// 获得摄氏度下的气温 if (isnan(h) || isnan(t)) { // 如果获取失败则跳过本次循环体内的操作 Serial.println("Failed to read from DHT sensor!"); return; } Serial.print("Humidity: "); Serial.print(h); Serial.print("% Temperature: "); Serial.print(t); Serial.println("°C"); delay(2000); // 每隔两秒重复一次上述动作 } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值