一、DHT11模块
DHT11模块是一个数字温湿度传感器,是一款含有已经校验数字信号输出的传感器,它其中包含有了电阻式的感知湿度的模块元件和一个可以测温的NTC模块元件,并且和一个高性能的八位单片机相结合。其中模块的性能有品质卓越、超快的响应速度、抗干扰能力强、性价比较高等等的特点备受开习者喜爱。
每个DHT11模块的单线制串行接口,使得系统集成变得简单快捷,其中体积小、低功耗,传输距离达到20米以上的优点,使得他在同类应用上成为最优的选择。模块为四针单排引脚封装,连接方便,特殊封装形式可以根据个人的需求进行操作。
二、接口说明
1.上电的注意事项:
DHT11的供电电压为3-5.5v.传感器上电以后,需要等待一秒钟以使得模块越过不稳定状态在此期间,不用进行任何的指令命令操作。
2.单总线
DHT11只有一根作为通信的数据线,而且该数据线是双向的。因此在我们的通信的过程中,需要我们灵活的来回切换输入输出模式。最后得到的数据(有效数据--其测量结果)DHT11会以40bit的数据包的形式发送过来,高位在前,低位在后。在这40位的数据格式位:8位湿度整数数据+8位湿度小数数据+8位温度整数数据+8位温度小数数据+8位的校验位
3.时序图分析
想要DHT11进行测量,就要进行上述40个位的信息数据读取。其通信的过程就是MCU发送起始的信号,MCU等待响应信号的接收,MCU等待DHT11测量完成,MCU读取测量结果完成,结束通信过程即可完成一系列操作。
小结:主机发送起始信号:主机发送至少18ms的低电平,丛集等待主机释放总线:主机吧总线拉高,延时20-40us.
主机读取响应--主机读取数据:每一个bit数据以5us的低电平开始,数据是0还是1由高电平时长决定,当最后1bit数据传输完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲等待响应的状态。
实例:
main.c
#include "stm32f10x.h" #include "delay.h" #include "usart1.h" #include "cm3_bit.h" #include "dht11.h" #include "string.h" int main(void) //主函数 { u8 data[4]; int i=0; int tem=0; float wendu=0,shidu=0; //组2:2位抢占,2位响应 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); systick_init(); //系统滴答延时 USART1_Init(9600); //串口1 DHT11_Init(); //温湿度初始化 while (1) { tem=DHT11_GetWENSHIDU(&data[0],&data[1],&data[2],&data[3]); if(tem==0) { printf("采集校验完成\r\n"); shidu=data[0]+(data[1]/100.0);//整数部分+小数部分即可得出湿度的结果 wendu=data[2]+(data[3]/100.0); printf("温度:%.2f 湿度:%.2f\r\n",wendu,shidu); } delay_ms(1200); } }
dht11.c
#include "dht11.h" #include "delay.h" void DHT11_Init(void) { delay_ms(1000); DHT11_Output(); //等待 1S 以越过不稳定状态在此期间不能发送任何指令 //GPIO_SetBits(GPIOB,GPIO_Pin_6); //拉高等待 } //功能为输出模式 void DHT11_Output(void) { GPIO_InitTypeDef DHT11; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); DHT11.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式 DHT11.GPIO_Pin=GPIO_Pin_6; //引脚6 DHT11.GPIO_Speed=GPIO_Speed_50MHz; //最高速50Mhz GPIO_Init(GPIOB, &DHT11); //根据beep配置的参数进行初始化 } //功能为输入模式 void DHT11_Input(void) { GPIO_InitTypeDef DHT11; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); DHT11.GPIO_Mode=GPIO_Mode_IN_FLOATING; //上拉输入模式 DHT11.GPIO_Pin=GPIO_Pin_6; //引脚6 DHT11.GPIO_Speed=GPIO_Speed_50MHz; //最高速50Mhz GPIO_Init(GPIOB, &DHT11); //根据beep配置的参数进行初始化 } //主机发送起始信号 void DHT11_Start(void) { GPIO_ResetBits(GPIOB,GPIO_Pin_6); //输出低电平 delay_ms(18); //大于18ms,小于30ms GPIO_SetBits(GPIOB,GPIO_Pin_6); //拉高等待 delay_us(20); } //读1字节数据 u8 DHT11_ReadByte(void) //1001 0001 { int i; u8 DATA=0; //读到保存到的一个字节 for(i=0;i<8;i++) { while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等待54us低电平时间过去 delay_us(40); //延迟一下,再判断是不是高电平 if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1) //延迟过后,还是高电平,把位1存起来 { while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等待高电平时间结束 DATA = DATA | 1<<(7-i); //保存1 } } return DATA; //返回读到的字节数据 } //温湿度采集,返回0值代表数据采集完成,返回1值说明采集不成功;返回2值时代表校验不成功,且本次数据采集无效 int DHT11_GetWENSHIDU(u8 *S_H,u8 *S_L,u8 *W_H,u8 *W_L) { u8 check=0; int n=0; DHT11_Output(); //输出模式 DHT11_Start(); //起始信号 DHT11_Input(); //输入模式 //单片机等待从机响应,怎么响应,单片机读PB6引脚为低电平 while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)) //等待从机响应低电平,退出等待 { n++; delay_us(1); if(n>100) return 1; } while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等从机响应后的低电平时间,完全过去 while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等80us高电平时间过去,就可以开始读数据 //单片机读取40位数据----读8位一个字节 *S_H=DHT11_ReadByte(); //湿度的高位字节 *S_L=DHT11_ReadByte(); //湿度的低位字节 *W_H=DHT11_ReadByte(); //温度的高位字节 *W_L=DHT11_ReadByte(); //温度的低位字节 check=DHT11_ReadByte(); //校验数据 DHT11_Output(); //输出模式 GPIO_SetBits(GPIOB,GPIO_Pin_6); //拉高释放总线 if((*S_H+*S_L+*W_H+*W_L)==check) { return 0; //采集数据成功 }else{ return 2; //校验不成功 } }
dht11.h
#ifndef __DHT11_H #define __DHT11_H #include "stm32f10x.h" // Device header void DHT11_Init(void); void DHT11_Output(void); void DHT11_Input(void); int DHT11_GetWENSHIDU(u8 *S_H,u8 *S_L,u8 *W_H,u8 *W_L); #endif