**
关于DHT11(ASAIR)温湿度传感器的使用(软件)
**
前言
此次在学习中使用到的是ASAIR公司生产的DHT11型温湿度传感器,说明书可前往ASAIR官网下载。
网址:DHT11官方网页
要使用好DHT11传感器,需要根据说明书的要求来进行编程。
关于DHT11
DHT11有4个引脚,分别是:
1、VCC :供电3.3~5.5V
2、DATA :串行数据,单总线
3、NC :空脚(一般接地)
4、GND :接地或者电源负极
接线如下图:
关于传感器的误差等其他信息可在前言处通过连接前往官网下载。
串行单总线通信
DHT11传输数据的模式是串行单总线,可理解为DHT11和我们所使用的的芯片(例如我使用的STM32)之间的首发数据都是通过一根数据线,通常要求上拉一个4.7kΩ左右的电阻,以保证总线在闲置的时候状态为高电平。
DHT11与STM32之间的通讯时序要求
DHT11的通信必须严格按照数据时序图在操作芯片引脚的输入输出模式和高低电平。
数据时序图如下:
程序编写
步骤一:初始化引脚
void DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;//输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//高速
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空
GPIO_Init(GPIOG,&GPIO_InitStruct);
Dat_out = 1;//此处主动拉高引脚电平(#define Dat_out PGout(9))
}
步骤二:引脚功能选择
由于通讯的时候需要设置引脚的输入输出模式,所以编写此代码增强阅读性。
void DHT11_Mode_Init(GPIOMode_TypeDef Mode)//将连接DH11数据引脚的芯片引脚初始化
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = Mode;//输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//高速
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空
GPIO_Init(GPIOG,&GPIO_InitStruct);
}
步骤三:通讯开始
开始通讯的时候,需要将STM32引脚设置成输出模式,等待1s的DHT11不稳定时间,然后拉低引脚电平20ms(18ms~30ms)
void DHT11_Star(void)
{
DHT11_Mode_Init(GPIO_Mode_OUT);//将引脚模式设置为输出模式,电平由上拉电阻自动拉高
delay_s(1);//等待一秒DH11的不稳定状态过去
Dat_out = 0;//将芯片引脚电平拉低
delay_ms(20);//芯片引脚拉低至少18ms,不能超过30ms
}
步骤四:DHT11应答
通讯开始时STM32引脚发生信号给DHT11,然后引脚需要设置成输入模式等待接收DHT11发送的信号
int DHT11_Answer(void)
{
int i=0;
DHT11_Mode_Init(GPIO_Mode_IN);//将芯片引脚设置为输入模式,电平由上拉电阻自动拉高,等待DH11做出应答
while(Dat_in==1)
{
delay_us(1);
i++;
if(i>1000000)//将超时时间设置为1s
{
return -1;//如果超时,返回-1
}
}
while(Dat_in==0);//等待低电平结束,此时电平由DH11控制
while(Dat_in==1);//等待高电平结束,此时电平由DH11控制
return 0;//此时返回0标识DH11有应答
}
步骤五:接收数据
DHT11应答之后会开始发送数据给STM32的引脚,发送的数据为5个8位共40位的数据,如下图所示
位数据“0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据“1”的格式为:54微秒的低
电平加68-74微秒的高电平。
u8 DHT11_Rec_Data(void)
{
int i;
u8 rec = 0;
DHT11_Mode_Init(GPIO_Mode_IN);
for(i=0;i<8;i++)
{
while(Dat_in == 0);
delay_us(35);//此处由于DH11低电平过后输出高电平,位数0则输出23~27us的高电平,位数1则输出68~74us的高电平,若延时过后还是高电平,那就是位数1
if(Dat_in == 1)
{
rec |= 0x01<<(7-i);
while(Dat_in == 1);//在此等待高电平结束
}
}
return rec;
}
步骤六:结束
void DHT11_End(void)
{
DHT11_Mode_Init(GPIO_Mode_OUT);
Dat_out = 1;
delay_ms(10);
}
主函数:
int DHT11_Main(float num)
{
u8 TR[5];
DHT11_Star();
if(DHT11_Answer()==-1)
{
printf("连接超时\r\n");
return -1;
}
for(int i=0; i<5; i++)
{
TR[i] = DHT11_Rec_Data();
}
DHT11_End();
if((u8)(TR[0]+TR[1]+TR[2]+TR[3]) == TR[4])
{
printf("温度:%d.%d 湿度:%d\r\n",TR[2],TR[3],TR[0]);
}
}
以上是我在学习中对DHT11温湿度传感器的使用总结出来的一点笔记,希望各位大佬不吝赐教,我都会虚心接受,感谢!