文章为本人的学习总结,有雷同,为巧合,有错误,请指出!
提示:以下是本篇文章正文内容,下面案例可供参考
一、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