本文为我的学习总结,有相似之处,有巧合,有错误,请指出!
提示:以下是本文的文本内容,以下案例可供参考
一、DHT11模块
DHT11模块是一个数字温湿度传感器,是一款含有已经校验数字信号输出的传感器,它其中包含有了电阻式的感知湿度的模块元件和一个可以测温的NTC模块元件,并与高性能的八位单片机相结合。其中,该模块具有质量优良、响应速度超快、抗干扰能力强、性价比高等特点。
每个DHT11模块的单线串行接口使系统集成简单快捷,具有体积小、功耗低、传输距离超过20米的优点,成为同类应用的最佳选择。该模块为四针单排引脚包装,连接方便,可根据个人需要操作特殊包装形式。
二、接口说明
1.上电注意事项:
DHT供电电压为3-5.5v.传感器上电后,需要等待一秒钟,使模块越过不稳定状态,在此期间不需要任何指令。
2.单总线
DHT只有一条数据线作为通信,数据线是双向的。因此,在我们的通信过程中,我们需要灵活地来回切换输入和输出模式。最终数据(有效数据-测量结果)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