DHT11简介:
DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个 I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。
DHT11与DS1B8B20的时序有相似之处,但相对来说简单许多。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先发。 DHT11 的数据格式为: 8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数部分+8bit 校验和。其中校验和数据为前面四个字节相加。DHT11 和 MCU 的一次通信最大为 34ms 左右,建议主机连续读取时间间隔不要小于 2s。
工作时序:
首先主机发送开始信号,从机发出响应信号。然后开始数据传输,数据传输包括:湿度、温度、校验位。
起始信号以及响应信号: 主机拉低总线,保持低电平时间20ms,然后释放总线,保持时间10-35us,DHT11拉低数据线78-88us,然后拉高数据线,延时87us,开始传输数据。
读时序:
读0和读1的区别在与高电平延长的时间不同。
代码:
DHT11.h
#define DHT11_GPIO_PORT GPIOB
#define DHT11_GPIO_PIN GPIO_PIN_13
#define DHT11_CLK_ENABLE() do{__HAL_RCC_GPIOB_CLK_ENABLE();}while(0)
#define DHT11_OUT(x) do{x?\
HAL_GPIO_WritePin(DHT11_GPIO_PORT,DHT11_GPIO_PIN,GPIO_PIN_SET):\
HAL_GPIO_WritePin(DHT11_GPIO_PORT,DHT11_GPIO_PIN,GPIO_PIN_RESET);\
}while (0)
#define DHT11_Read HAL_GPIO_ReadPin(DHT11_GPIO_PORT,DHT11_GPIO_PIN)
DHT11.c
/**
* @brief 初始化DHT11相关IO口, 并使能时钟
* @param 无
* @retval 无
*/
void DHT11_init()
{
GPIO_InitTypeDef gpio_init_struct;
DHT11_CLK_ENABLE();
gpio_init_struct.Pin = DHT11_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_GPIO_PORT, &gpio_init_struct);
}
/**
* @brief 主机发送开始信号
* @param 无
* @retval 无
*/
void DHT11_Start()
{
DHT11_OUT(0);
delay_ms(20);
DHT11_OUT(1);
delay_us(13);
}
/**
* @brief 检测DHT11是否发生响应
* @param 无
* @retval 0:表示成功相应,1:表示相应失败
*/
uint8_t DHT11_Check()
{
uint8_t retry,rval=0;
while(DHT11_Read && retry<100) /*判断DHT11没有把总线拉低*/
{
retry++;
delay_us(1);
}
if (retry>=100)
{
rval=1;
}
else
{
retry=0;
while(!DHT11_Read && retry<100) /*判断DHT11没有把总线拉高*/
{
retry++;
delay_us(1);
}
if (retry>=100) rval=1;
}
return rval;
}
/**
* @brief 从DHT11读取一个位
* @param 无
* @retval 0:表示成功相应,1:表示相应失败
*/
uint8_t DHT11_Read_bit()
{
uint8_t retry=0;
while(DHT11_Read && retry<100)
{
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_Read && retry<100)
{
retry++;
delay_us(1);
}
/*数字0还是1,延长的时间大于数字0的时间小于数字1的时间*/
delay_us(40);
if (DHT11_Read)
{
return 1;
}
else{
return 0;
}
}
/**
* @brief 从DHT11读取一个字节
* @param 无
* @retval 读到的数据data
*/
uint8_t DHT11_Read_Byte()
{
uint8_t i,data=0;
for (i=0;i<8;i++)
{
data<<=1; /*变量data向左移1位,结果仍保存在data中*/
data|=DHT11_Read_bit();
}
return data;
}
/**
* @brief 从DHT11读取一次数据
* @param temp:温度值(-20~60)
* @param hum:湿度值:(5%~95%)
* @retval 0:表示成功相应,1:表示相应失败
*/
uint8_t DHT11_Read_data()
{
uint8_t buf[5]={0}; /*将获得数据储存到数组中*/
uint8_t i;
uint8_t temp=0;
uint8_t hum=0;
DHT11_Start();
if (DHT11_Check() == 0)
{
for ( i = 0; i < 5; i++)
{
buf[i]=DHT11_Read_Byte();
}
/*校验监测数据是否正确*/
if (buf[0]+buf[1]+buf[2]+buf[3]==buf[4])
{
hum=buf[0];
temp=buf[2];
}
/*通过串口输出*/
printf("T:%d H:%d\r\n",temp,hum);
}
else{
return 1;
}
return 0;
}