DHT11是一款数字温湿度传感器。
- 含有已校准数字信号输出的温湿度复合传感器;
- 传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接;
- 单线制串行接口,信号传输距离可达20米以上。
测量范围及精度 :
20-90%RH ±5%RH
0-50℃ ±2℃
DHT11硬件部分
电源引脚:
DHT11的供电电压为3-5.5V。
传感器上电后,要等待1s 以越过不稳定状态,在此期间无需发送任何指令。
电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。
实物张下图的样子:
接口:建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。
所以典型的应用电路如下:
原理图如下:
综上在仿真里这部分是这样设计的
DHT11接口部分
上面看完了硬件部分的介绍,下面看使用传感器读取数据的接口部分。
DHT11接口上面介绍了是单线制串行接口
DHT11单总线工作原理:
DATA 输出线用于单片机与DHT11之间的通讯,一次通讯时间4ms左右
单片机发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后
DHT11发送响应信号,送出40bit的数据,并触发一次信号采集
用户可选择读取数据,采集数据后转换到低速模式
如果没有接收到主机发送的开始信号,DHT11不会主动进行温湿度采集
DHT11数据格式:
一次完整的数据传输为40bit,高位先出
_数据格式_:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验;
DHT11数据分小数部分和整数部分,当前小数部分用于以后扩展,现读出为零; 测量分辨率分别为8bit(温度)、8bit(湿度)
数据传送正确时校验位等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”之和
一次完整的信号读取如上图所示
开始信号由于上拉电阻,总线空闲状态为高电平,主机发出开始信号,把总线拉低大于18ms,拉高电平延时等待20-40us后, 读取DHT11的响应信号
响应信号: DHT11接收到主机的开始信号后,等待主机开始信号结束,发送80us低电平响应信号,再把总线拉高80us;主机发送开始信号结束后,可以切换到输入模式,总线由上拉电阻拉高或者输出高电平均可。
这两部分的信号如下:深绿色是主机信号,浅绿色是DHT11信号
数据信号: 每一bit数据都以50us低电平开始,高电平的长短决定数据位是0还是1(26us-28us为0;70us为1),如下图所示:
结束信号: 当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
了解完接口部分,下面看看代码如何实现读取数据的。
开始信号代码
/*主机(stm32)发送 开始信号*/
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //stm32的io口设置为输出模式
DHT11_DQ_High ;//拉高
DHT11_DQ_Low ;//拉低
delay(25000); //延时,拉低至少18ms
DHT11_DQ_High; //DQ=1
delay(55); //主机拉高20~40us
}
DHT11响应信号代码
//等待DHT11的回应 DHT的响应信号 先拉低80us,在拉高80us
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void)
{
u8 retry=0;//定义临时变量
DHT11_IO_IN(); //stm32的io口设置为输入模式
if (GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)//DHT11会拉低40~80us 如果是高则DHT11没有响应信号则判断没有DHT11
{
return 0 ;//如果是高则DHT11没有响应信号则判断没有DHT11
}else
{
while(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0 && (retry < 200))//DHT11拉低了持续200个循环 DHT11会拉低80us
retry++ ;
}
delay(40) ;
delay(40) ;
return 1 ;
}
在使用DHT11的时候,肯定要初始化,那么就可以先调用开始信号函数,然后接受响应函数,判断DHT11是否存在,存在则初始化完成
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
void DHT11_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA口时钟
DHT11_Rst(); //复位DHT11
DHT11_Check();//等待DHT11的回应
}
//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//等待变为低电平 每一bit数据都以50us低电平开始
{
retry++;
delay(2);
}
retry=0;
while((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//等待变高电平 然后的高电平持续时间决定了该位是0还是1
{
retry++;
delay(2);
}
delay(40);//等待40us 26us-28us为0;70us为1 所以等待40us后,是高则为1 是低则为0
if(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)//判断是高还是低
return 1;
else
return 0;
}
从DHT11读取一个位
首先等待变为低电平 每一bit数据都以50us低电平开始
然后等待变高电平 然后的高电平持续时间决定了该位是0还是1
等待40us 26us-28us为0;70us为1 所以等待40us后,是高则为1 是低则为0
最后判断是高还是低
有了读取位的函数则可以将8位组成一个字节
//从DHT11读取一个字节(8位)
//返回值:读到的数据
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;//数据清0
for (i=0;i<8;i++) //循环8次,组成一个字节
{
dat<<=1; //左移一位 ,高位在前
dat|=DHT11_Read_Bit();//或与及把最后1位置成了读取的1位
}
return dat;//返回数据
}
然后一帧数据有40位,及5个字节,最后一个字节是校验位,其它字节代表已在前面描述
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
u8 buf[5];//5个字节 一帧数据
u8 i;
DHT11_Rst();//开始信号
if(DHT11_Check()==0)//DHT11拉高准备输出
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();//读一个字节
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])//校验位判断
{
*humi=buf[0];//赋值湿度
*temp=buf[2];//赋值温度
}
}
else return 1;
return 0;
}
上的代码把DHT11的驱动代码写完了,在main函数中调用也很简单,下面给个例程
int main(void)
{
//配置系统时钟
。。。
//初始化DHT11
DHT11_Init();
u8 temperature,humidity;//声明温度及湿度
while(1)
{
DHT11_Read_Data(&temperature,&humidity) ;//读取一次数据
}
}
DHT11 protues测试
在protues中加入lcd1602的显示代码,则可以显示读取的数据和传感器本身的数据是否一致
评论(0)
您还未登录,请登录后发表或查看评论