我的风格就是先上代码!
main函数段:
#include <REGX52.h>
#include <INTRINS.h>
#include <delay_500ms.h>
#include <usart.h>
#include <dht11.h>
extern unsigned char TH;
extern unsigned char TL;
extern unsigned char HH;
extern unsigned char HL;
void main()
{
UartInit();
while(1)
{
DHT11_Receive_40bit();
sendbyte(TH);
Delay500ms();
sendbyte(HH);
Delay500ms();
}
}
QQ:1504012979 name:Vincent njw glut
DHT11驱动函数段:
#include <REGX52.H>
#include "dht11.h"
#include "delay_500ms.h"
sbit DATE=P2^0;
unsigned char TH;
unsigned char TL;
unsigned char HH;
unsigned char HL;
unsigned char CHECK;
//起始信号
void DHT_start()
{ Delay500ms();//每一次卡开始都要等待一秒左右,让DHT11越过不稳定状态
Delay500ms();
DATE=1;
delay30us();
DATE=0;
delay20ms();//低电平延时>18ms
DATE=1;
delay30us();
DATE=1;
}
//接收一个字节
unsigned char DHT11_Receive_Byte()
{
unsigned char i,b=0;//b表示接收到的一个字节数据
for(i=0;i<8;i++)
{
while(!DATE);
delay30us();
b<<=1;
if(DATE==1)
b|=0x01;
while(DATE);
}
return b;
}
//接收40bit
void DHT11_Receive_40bit()
{
DHT_start();
if(DATE==0)
{
while(!DATE);
while(DATE);
TH=DHT11_Receive_Byte();
TL=DHT11_Receive_Byte();
HH=DHT11_Receive_Byte();
HL=DHT11_Receive_Byte();
CHECK=DHT11_Receive_Byte();//最后的检验是TH+TL+HH+HL=CHECK,但是我觉得没有必要
DATE=0;
delay55us();
DATE=1;
}
}
效果图片:
这里说明一下,我代码给大家展示的是通过串口接收的温湿度数据,而图片是用LCD1602直接显示温湿度。对于我本人而言,我觉得LCD的可用性不大,占用mcu引脚太多,但是对于学习通信协议的时序来说,它也是一个不错的入门项目。(这里指的是,不是直接用现成的驱动库,而是自己写库,熟悉每个通信协议的时序。)
硬件部分:
C51,DHT11,CH340这些硬件都很简单,我就不做过多的介绍。
软件部分:
首先对于一个通信协议来说,最重要的也是它的灵魂就是时序图。大家可以对照我的代码,一行一行一步一步的对照时序图看 。
1:起始信号
起始信号是主机也就是mcu发出的。以下是DHT11的数据手册对于起始信号的说明:
意思就是说拉低18ms以上之后然后拉高等待20-40us。对应的是这一段:
2:等待DHT11响应
以下是DHT11数据手册对于响应信号的说明
意思就是DHT11会发送一个80us的低电平信号,然后又拉高80us,这时候我们需要用软件检测和耗尽这两段时间,可以用while(!date);和while(date);来耗尽和检测这些时间。
对应的是以下这段:
3:对于数据的读取
DHT11采取的是单总线通信协议,01的判决和其他的通信方式有很大的区别。以下是01信号的时序图。
我们可以对比一下01信号的时序,可以发现,它们两个的起始低电平的持续时间是一样的,都是50us,我们可以用延时50us或者用while(!date);来耗尽这些低电平信号的时间。然后延时28-70us之间的任意一个时间,检测延时过后的高低电平,如果是高电平,按位和0x01或运算,如果是低电平,直接把数据整体左移(因为DHT11先发的是高位)。
我们需要接受5个8位二进制数,说明如下:
最后一位是校验位,我个人觉得校不校验没啥影响,当然你也可以不接受这个校验位,用延时让这个校验位走完。最后拉低延时然后在拉高就可以进行下一次的数据读取了。
需要注意的是:
1:对于通信协议来说,时序就是灵魂,对于延时时间的精确度要有一定的要求,建议大家选择自己相信的延时函数,要不然很难受。
2:每一次DHT11的数据读取都需要等待1s左右的时间等待它越过不稳定状态。
希望大家看完文章之后多思考,多终结。
Vincent 想让学习变得简单!