【鸿蒙开发】Hi3861学习笔记-DHT11温湿度传感器
00. 目录
文章目录
- 00. 目录
- 01. DHT11概述
- 02. DHT11特性
- 03. DHT11管脚
- 04. DHT11数据格式
- 05. DHT11传输时序
- 06. 硬件接线
- 07. 软件设计
- 08. 实验现象
- 09. 附录
01. DHT11概述
DHT11 是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连
接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11 与单片机之间能采用简单的单总线进行通信,仅
仅需要一个I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的
准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。
02. DHT11特性
性能指标和特性如下:
- 工作电压范围:3.5V-5.5V
- 工作电流 :平均 0.5mA
- 湿度测量范围:20-90%RH
- 温度测量范围:0-50℃
- 湿度分辨率 :1%RH 8 位
- 温度分辨率 :1℃ 8 位
- 采样周期 :1S
- 单总线结构
- 与 TTL 兼容(5V)
03. DHT11管脚
DHT11 数字湿温度传感器连接方法极为简单。第一脚接电源正,第四脚接电源地端。数据端为第二脚。可直接接主机(单片机)的 I/O
口。为提高稳定性,建议在数据端和电源正之间接一只 4.7K 的上拉电阻。第三脚为空脚,此管脚悬空不用。
04. DHT11数据格式
DHT11数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5Byte(40Bit)组成。数据分小数部分和整数部分,具体格式在下面说明。
一次完整的数据传输为40bit,高位先出。
数据格式:
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和
校验和数据为前四个字节相加。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。如果,某次从传感器中读取如下5Byte数据:
05. DHT11传输时序
5.1 DHT11开始发送数据流程
主机发送开始信号后,延时等待 20us-40us 后读取 DH11T 的回应信号,读取总线为低电平,说明 DHT11 发送响应信号,DHT11 发送响应
信号后,再把总线拉高,准备发送数据,每一 bit 数据都以低电平开始,格式见下面图示。如果读取响应信号为高电平,则 DHT11 没有响应,请
检查线路是否连接正常。
5.2 主机复位信号和 DHT11 响应信号
5.3 数字0信号表示方法
5.4 数字1信号表示方法
06. 硬件接线
07. 软件设计
bsp_dht11.h
#ifndef BSP_DHT11_H
#define BSP_DHT11_H#include "cmsis_os2.h"
#include "hi_io.h"
#include "hi_gpio.h"//管脚定义
#define DHT11_PIN HI_IO_NAME_GPIO_7
#define DHT11_GPIO_FUN HI_IO_FUNC_GPIO_7_GPIO#define DHT11_DQ_OUT(a) hi_gpio_set_ouput_val(DHT11_PIN,a)//函数声明
void dht11_io_out(void);
void dht11_io_in(void);
void dht11_reset(void);
uint8_t dht11_check(void);
uint8_t dht11_read_bit(void);
uint8_t dht11_read_byte(void);
uint8_t dht11_read_data(uint8_t *temp,uint8_t *humi) ;
uint8_t dht11_init(void);#endif
bsp_dht11.c
#include "bsp_dht11.h"
#include <unistd.h>
#include "hi_time.h"//DHT11输出配置
void dht11_io_out(void)
{hi_gpio_init(); // GPIO初始化hi_io_set_pull(DHT11_PIN, HI_IO_PULL_UP); // 设置GPIO上拉hi_io_set_func(DHT11_PIN, DHT11_GPIO_FUN); // 设置IO为GPIO功能hi_gpio_set_dir(DHT11_PIN, HI_GPIO_DIR_OUT); // 设置GPIO为输出模式
}//DHT11输入配置
void dht11_io_in(void)
{hi_io_set_pull(DHT11_PIN, HI_IO_PULL_NONE); // 设置GPIO浮空hi_gpio_set_dir(DHT11_PIN, HI_GPIO_DIR_IN); // 设置GPIO为输入模式
}/******************************************************* 函数名 :GPIO_GetInputValue* 功能 :获取GPIO输入状态* 输入 :id, *val* 输出 :0/1*******************************************************/
hi_gpio_value DHT11_DQ_IN = {0};
uint8_t GPIO_GetInputValue(hi_gpio_idx id,hi_gpio_value *val)
{hi_gpio_get_input_val(id,val);return *val;
}//dht11复位
void dht11_reset(void)
{ hi_gpio_set_dir(DHT11_PIN, HI_GPIO_DIR_OUT); // 设置GPIO为输出模式DHT11_DQ_OUT(0); //拉低DQhi_udelay(20*1000); //拉低至少18msDHT11_DQ_OUT(1); //DQ=1 hi_udelay(30); //30US
}//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t dht11_check(void)
{ uint8_t retry=0;dht11_io_in(); while (GPIO_GetInputValue(DHT11_PIN,&DHT11_DQ_IN)&&retry<100)//DHT11会拉低40~50us{retry++;hi_udelay(1);}; if(retry>=100)return 1;else retry=0;while ((!GPIO_GetInputValue(DHT11_PIN,&DHT11_DQ_IN))&&retry<100)//DHT11拉低后会再次拉高40~50us{retry++;hi_udelay(1);};if(retry>=100)return 1; return 0;
}//从DHT11读取一个位
//返回值:1/0
uint8_t dht11_read_bit(void)
{uint8_t retry=0;dht11_io_in();while(GPIO_GetInputValue(DHT11_PIN,&DHT11_DQ_IN)&&retry<100)//等待变为低电平 12-14us 开始{retry++;hi_udelay(1);}retry=0;while((!GPIO_GetInputValue(DHT11_PIN,&DHT11_DQ_IN))&&retry<100)//等待变高电平 26-28us表示0,116-118us表示1{retry++;hi_udelay(1);}hi_udelay(40);//等待40usif(GPIO_GetInputValue(DHT11_PIN,&DHT11_DQ_IN))return 1;else return 0;
}//从DHT11读取一个字节
//返回值:读到的数据
uint8_t dht11_read_byte(void)
{ uint8_t i,dat;dat=0;for (i=0;i<8;i++) {dat<<=1; dat|=dht11_read_bit();} return dat;
}//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t dht11_read_data(uint8_t *temp,uint8_t *humi)
{ uint8_t buf[5];uint8_t i;dht11_reset();if(dht11_check()==0){for(i=0;i<5;i++)//读取40位数据{buf[i]=dht11_read_byte();}if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){*humi=buf[0];*temp=buf[2];}}else return 1;return 0;
}//DHT11初始化
//返回0:初始化成功,1:失败
uint8_t dht11_init(void)
{hi_gpio_init(); // GPIO初始化hi_io_set_pull(DHT11_PIN, HI_IO_PULL_UP); // 设置GPIO上拉hi_io_set_func(DHT11_PIN, DHT11_GPIO_FUN); // 设置IO为GPIO功能hi_gpio_set_dir(DHT11_PIN, HI_GPIO_DIR_OUT); // 设置GPIO为输出模式dht11_reset();return dht11_check();
}
template.c
/******************************************************************************************************* @file template.c***************************************************************************************************** 实验现象:串口输出DHT11采集温度和湿度******************************************************************************************************/#include <stdio.h>
#include <unistd.h>#include "ohos_init.h"
#include "cmsis_os2.h"#include "bsp_led.h"
#include "bsp_dht11.h"//LED任务
osThreadId_t LED_Task_ID; //led任务IDvoid LED_Task(void)
{led_init();//LED初始化while (1) {LED(1); usleep(200*1000); //200msLED(0);usleep(200*1000); //200ms}
}
//LED任务创建
void led_task_create(void)
{osThreadAttr_t taskOptions;taskOptions.name = "LEDTask"; // 任务的名字taskOptions.attr_bits = 0; // 属性位taskOptions.cb_mem = NULL; // 堆空间地址taskOptions.cb_size = 0; // 堆空间大小taskOptions.stack_mem = NULL; // 栈空间地址taskOptions.stack_size = 1024; // 栈空间大小 单位:字节taskOptions.priority = osPriorityNormal; // 任务的优先级LED_Task_ID = osThreadNew((osThreadFunc_t)LED_Task, NULL, &taskOptions); // 创建任务1if (LED_Task_ID != NULL){printf("ID = %d, Create LED_Task_ID is OK!\n", LED_Task_ID);}
}//控制任务
osThreadId_t DHT11_Task_ID; //任务IDvoid DHT11_Task(void)
{static uint8_t i=0;uint8_t temp; uint8_t humi;while(dht11_init()){printf("DHT11检测失败,请插好!\r\n");usleep(500*1000); //500ms}printf("DHT11检测成功!\r\n");while (1) {i++;if(i%50==0){dht11_read_data(&temp,&humi);printf("温度 = %d°C 湿度 = %d%%RH\r\n", temp, humi);}usleep(10*1000); //10ms}
}
//任务创建
void dht11_task_create(void)
{osThreadAttr_t taskOptions;taskOptions.name = "dht11Task"; // 任务的名字taskOptions.attr_bits = 0; // 属性位taskOptions.cb_mem = NULL; // 堆空间地址taskOptions.cb_size = 0; // 堆空间大小taskOptions.stack_mem = NULL; // 栈空间地址taskOptions.stack_size = 1024; // 栈空间大小 单位:字节taskOptions.priority = osPriorityNormal1; // 任务的优先级LED_Task_ID = osThreadNew((osThreadFunc_t)DHT11_Task, NULL, &taskOptions); // 创建任务if (LED_Task_ID != NULL){printf("ID = %d, LED_Task_ID Create OK!\n", LED_Task_ID);}
}/*** @description: 初始化并创建任务* @param {*}* @return {*}*/
static void template_demo(void)
{printf("普中-Hi3861开发板--DHT11温湿度传感器实验\r\n");led_task_create();dht11_task_create();//任务创建
}
SYS_RUN(template_demo);