前言最近购入了一台示波器,想着示波器到了总得做个小项目,不然怎么发挥示波器的作用。正好用到之前限制下来的一块51单片机的学习板,还有一块DHT11温湿度传感器,所以决定做一个基于51单片机的温度计,然后用oled屏显示出来。所以本期文章会有DHT11传感器的解析,以及代码全部开源,欢迎大家来参考
下载地址
材料准备
(一)51单片机
(二)DHT11温湿度传感器
(三)0.96OLED屏,4针脚
(四)示波器(选配,用来分析DHT11)
DHT温湿度传感器
简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
引脚
串行通信(理论,文档)
【单总线说明】
DHT11器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制
均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许
设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约
4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主
机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序
列混乱,器件将不响应主机。
【单总线传送数据位定义】
DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次传送40位数据,
高位先出。
【数据格式】
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位
注:其中湿度小数部分为0。
【校验位数据定义】
“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”8bit校验位等于所得结果的末8位
【数据时序图】
用户主机(MCU)发送一次开始信号后,DHT11从低功耗模式转换到高速模式,待主机开始
信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信采集。
【读取步骤】
串行通信(示波器实操)
光看理论肯定没这么通俗易懂,所以我直接上示波器给大家演示一下数据是如何传输的,可能有误,欢迎指正!
(示波器测量的光标可能没对准,但是差的不多,误差1-3us内)
(一)开始时,要求MCU将电平拉低18ms以上,我这里拉了20ms
(二)当DHT11检测到MCU的低电平信号后,等待低电平信号结束,然后拉高电平,等待DHT11相应
(三)但83us的应答低电平发出后,再发出87us的高电平通知muc准备接收数据
(四)DHT会发送0和1数据,让我们看看如何区分0和1的。每个信号都有两部分组成,54us低电平的主机信号 + 0或1高电平的从机信号,0的高电平为23us,1的高电平为68us
所以数据1的电平为54+68=122us,数据0的电平为54+23=77us
(五)数据分析
由图可以分析出5段8bit的数据,湿度高位,湿度低位,温度高位,温度低位,校验位
校验为等于4项相加
0011 0001(湿度高位)0000 0000(湿度低位)
0001 1101(温度高位)0000 1000(温度低位)
0101 0110(校验)
正确数据接收:0011 0001 + 0000 0000 + 0001 1101 + 0000 1000 = 0101 0110
湿度:0011 0001 = 49(十进制整数部分)0000 0000 = 0(十进制小数部分)
湿度为:49.0
温度:0001 1101 = 29(十进制整数部分)0000 1000 = 8(十进制小数部分)
温度为:29.8
代码解析
【完整的代码在文章开头有下载地址,免费】
(一)延迟函数,一个为us,一个为ms
void delay_us(uchar u) //us延时
{
while(--u);
}
void delay_as(uint m) //ms延时
{
uint i,j;
for(i=m;i>0;i--)
for(j=112;j>0;j--);
}
(二)MCU拉低电平20ms,并等待DHT11响应
void start()
{
Data=1; //初始拉高电平
delay_us(5);
Data=0; //发送开始信号
delay_as(20); //延时18ms以上
Data=1; //拉高等待
delay_us(30);
}
(三)接收数据,通过延时,判断高电平的数据是0还是1
uchar DHT11_rec_byte()
{
uchar i,dat=0;
for(i=0;i<8;i++) //从高到低依次接收8位数据
{
while(!Data); //等待50us低电平过去
delay_us(8); //延时60us,如果还为高则数据为1,否则为0
dat<<=1; //移位使正确接收8位数据,数据为0时直接移位
if(Data==1) //数据为1时,使dat加1来接收数据1
dat+=1;
while(Data); //等待数据线拉低
}
return dat;
}
(四)整合数据,并校验,然后保存在变量中
void shou()
{
uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
start();
if(Data==0)
{
while(Data==0); //等待拉高
delay_us(40); //拉高后延时80us
R_H=DHT11_rec_byte(); //接收湿度高八位
R_L=DHT11_rec_byte(); //接收湿度低八位
T_H=DHT11_rec_byte(); //接收温度高八位
T_L=DHT11_rec_byte(); //接收温度低八位
revise=DHT11_rec_byte(); //接收校正位
delay_us(25); //结束
if((R_H+R_L+T_H+T_L)==revise) //校正
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
}
wendu = TH;
shidu = RH;
}
}
(五)通过oled屏幕显示,具体位置可看源码附带的oled函数
void xianshi()
{
OLED_ShowCHinese(30,5,2);
OLED_ShowCHinese(50,5,3);
OLED_ShowCHinese(30,10,0);
OLED_ShowCHinese(50,10,1);
OLED_ShowNum(70,2,wendu,2,16);
OLED_ShowNum(70,5,shidu,2,16);
}
总结
51单片机温度计,这个项目是非常适合新手朋友的,一方面是51单片机入门很简单,另一方面是学习示波器的使用方法
通过小项目,可以学到很多知识,特别是二进制的计算方法,进制转换也是电子入门必学的
DHT11的分析方法,在任何单片机里面都可以用,不局限51单片机
文章评论(0条评论)
登录后参与讨论