今天,记录一下DHT11,涉及到了单总线协议,所以先花点时间谈论一下单总线协议(DS18B20也是用的单总线)。
单总线协议
单总线技术的通信协议
可能这时序图就是个例子,ds18b20的时序图与DHT11的时序图也是不一样的。
DHT11
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h" // Device header#define DHT11_PORT GPIOC
#define DHT11_PIN GPIO_Pin_10
#define DHT11_PORT_RCC RCC_APB2Periph_GPIOC#define dht11_high GPIO_SetBits(GPIOC, GPIO_Pin_10)
#define dht11_low GPIO_ResetBits(GPIOC, GPIO_Pin_10)
#define Read_Data GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_10)void DHT11_GPIO_Init_OUT(void);
void DHT11_GPIO_Init_IN(void);
void DHT11_Start(void);
unsigned char DHT11_REC_Byte(void);
void DHT11_REC_Data(void);#endif
#include "stm32f10x.h" // Device header
#include "dht11.h"
#include "SysTick.h"
//数据
unsigned int rec_data[4];//对于stm32来说,是输出
void DH11_GPIO_Init_OUT(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);}//对于stm32来说,是输入
void DH11_GPIO_Init_IN(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);}//主机发送开始信号
void DHT11_Start(void)
{DH11_GPIO_Init_OUT(); //输出模式dht11_high; //先拉高delay_us(30);dht11_low; //拉低电平至少18usdelay_ms(20);dht11_high; //拉高电平20~40usdelay_us(30);DH11_GPIO_Init_IN(); //输入模式,可以说是释放总线
}//获取一个字节
char DHT11_Rec_Byte(void)
{unsigned char i = 0;unsigned char data;for(i=0;i<8;i++) //1个数据就是1个字节byte,1个字节byte有8位bit{while( Read_Data == 0); //从1bit开始,低电平变高电平,等待低电平结束delay_us(30); //延迟30us是为了区别数据0和数据1,0只有26~28usdata <<= 1; //左移if( Read_Data == 1 ) //如果过了30us还是高电平的话就是数据1{data |= 1; //数据+1}while( Read_Data == 1 ); //高电平变低电平,等待高电平结束}return data;
}//获取数据void DHT11_REC_Data(void)
{unsigned int R_H,R_L,T_H,T_L;unsigned char RH,RL,TH,TL,CHECK;DHT11_Start(); //主机发送信号dht11_high; //拉高电平if( Read_Data == 0 ) //判断DHT11是否响应{while( Read_Data == 0); //低电平变高电平,等待低电平结束while( Read_Data == 1); //高电平变低电平,等待高电平结束,耗费掉DHT11的响应输出R_H = DHT11_Rec_Byte();R_L = DHT11_Rec_Byte();T_H = DHT11_Rec_Byte();T_L = DHT11_Rec_Byte();CHECK = DHT11_Rec_Byte(); //接收5个数据dht11_low; //当最后一bit数据传送完毕后,DHT11拉低总线 50usdelay_us(55); //这里延时55usdht11_high; //随后总线由上拉电阻拉高进入空闲状态。if(R_H + R_L + T_H + T_L == CHECK) //和检验位对比,判断校验接收到的数据是否正确{RH = R_H;RL = R_L;TH = T_H;TL = T_L;}}rec_data[0] = RH;rec_data[1] = RL;rec_data[2] = TH;rec_data[3] = TL;
}
像DHT11响应输出,以及DHT11输出的0和1,这些是DHT11内部的控制器发出来的,我们不需要写时序去描述,只需要对DHT11输出的数据进行读取,判断即可
附录:
DHT11详细介绍(内含51和STM32代码)_安赫'的博客-CSDN博客
七、【中级篇】传感器DHT11、DHT22、DS18B20_dht22和dht11比较_十七阿哥的春天的博客-CSDN博客
16 STM32基础学习 DS18B20 温度与DHT11温湿度模块 - 古月居 (guyuehome.com)
【通信协议】1-Wire 单总线_淹死的大白鲨的博客-CSDN博客
DHT11 温湿度传感器_比特冬哥的博客-CSDN博客