DHT22温湿度传感器的使用及Proteus仿真

[复制链接]
2419|12
 楼主| merry_zsp 发表于 2020-3-29 15:53 | 显示全部楼层 |阅读模式
AM2303(DHT22)湿敏电容数字温湿度模块是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个高精度测温元件,并与一个高性能的8位单片机相连。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比高等优点。每个传感器都在极为精确的湿度检验室中进行校准。校准系数以程序的形式储存在单片机中,传感器内部在检测信号的处理过程中要调用这些校准系数。标准单总线接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至比较苛刻的应用场合的最佳选择。产品为3引线(单总线接口)连接方便。特殊封装形式可根据用户需求而提供。

 楼主| merry_zsp 发表于 2020-3-29 15:54 | 显示全部楼层

二、产品图示及性能

2.1 典型应用电路

407855e8054289b720.png

882415e80543b0854e.png



 楼主| merry_zsp 发表于 2020-3-29 15:55 | 显示全部楼层
三、传感器工作过程说明

3.1 单总线说明

AM2302器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由数据线完成。设备(微处理器)通过一个漏极开路或三态端口连接至该数据线,以允许设备在不发送数据时能够释放总线;单总线通常要求外接一个约5.1K欧姆的上拉电阻,这样,当总线闲置时,其状态为高电平。由于他们是主从结构,只有在主机呼叫传感器时,传感器才会应答,因此主机访问传感器必须遵循单总线序列,如果出现序列混乱,传感器将不再响应主机。单总线信号格式如下:
450635e8054625cb83.png


 楼主| merry_zsp 发表于 2020-3-29 15:56 | 显示全部楼层
3.2 数据格式说明
传感器一次传送40bit数据,高位在前低位在后,这40bit数据分别为:湿度值高八位+湿度值低八位+温度值高八位+温度值低八位+八位校验位。当“校验值=度值高八位+湿度值低八位+温度值高八位+温度值低八位”时,说明数据传输正确。
对于温度值,其最高位为符号位。即当最高位为1时,表示温度值为负值;反之,则为正值。
注意:所得温湿度值均为实际值的十倍。
614395e8054a121e8d.png


 楼主| merry_zsp 发表于 2020-3-29 15:58 | 显示全部楼层
3.3 传感器工作时序
3.3.1 发送数据前的准备(向传感器发送起始信号)
首先主机把数据总线(SDA)拉低一段时间(技术手册上说至少1ms,实际中可能需要18ms以上),然后再由主机拉高约20us。然后,传感器响应,响应形式为:传感器先把总线拉低约80us再拉高80us(典型值),随后开始发送40bit数据。时序如图所示:
762875e8054e2c4c7b.png
40bit数据中0与1的判断
在40bit的数据中,每一位数据均由一段低电平加一段高电平组成。0的电平形式为50us低电平+26us高电平;1的电平形式为50us电平+70us高电平。因此,可以得出判断0与1的方法为:先度过低电平,然后延时40us再检测总线电平值,若此时总线为低电平则为0,总线为高电平则为1.。时序图如下:
322655e8055085f7a9.png
AM2302一次完整通信过程时序
549465e8055225eaa6.png
注意:主机从AM2302读取的温湿度数据总是前一次的测量值,如两次测量值间隔时间很长,要连续读两次以第二次获得的值为实时温湿度值,同时两次读取间隔时间最小为2S。



 楼主| merry_zsp 发表于 2020-3-29 16:03 | 显示全部楼层
四、例程(例程均为自己编写且验证通过)

/*****使用单片机为AT89C52;数值测量值用八段数码管显示;温度测量范围为-40.0~80.0摄氏度,湿度测量范围为0~99.9%;测量数据可精确到小数点后一位*****/

  1. #include<reg52.h>
  2. #include<intrins.h>

  3. typedef unsigned char uchar;
  4. typedef unsigned int  uint;


  5. #define DELAY_TIME 5


  6. uchar value[5];
  7. uint temp,hum;

  8. sbit w1=P2^0;
  9. sbit w2=P2^1;
  10. sbit w3=P2^2;
  11. sbit w4=P2^3;
  12. sbit Bus=P2^4;
  13. //P3温度,P1湿度

  14. void Delay10us(void);//10us延时函数
  15. void Delay20us(void);//20us延时函数
  16. void Delay1ms(void);//1ms延时函数
  17. void Read_value(void);//读值子函数
  18. void Show(uint x,y);//显示子函数



  19. void main()
  20. {
  21.         uint i;
  22.         for(i=0;i<2000;i++)
  23.         {
  24.                 Delay1ms();
  25.         }

  26.         Read_value();//读值       

  27.         hum=value[0]*256+value[1];//计算湿度值
  28.         temp=(value[2]&0x7f)*256+value[3];//如果温度为负值,则&0x3f去掉符号位后再计算;若为正值则无影响

  29.         Show(temp,hum);       
  30. }






  31. /***********************10us延时函数*****************************/
  32. void Delay10us()
  33. {
  34.         uchar i;
  35.         i=2;
  36.         while(--i);
  37.              
  38. }
  39. /***********************20us延时函数*****************************/
  40. void Delay20us(void)   //误差 0us
  41. {
  42.     unsigned char a,b;
  43.     for(b=3;b>0;b--)
  44.         for(a=1;a>0;a--);
  45. }



  46. /***********************1ms延时函数*****************************/
  47. void Delay1ms()   //误差 0us
  48. {
  49.     unsigned char a,b,c;
  50.     for(c=1;c>0;c--)
  51.         for(b=142;b>0;b--)
  52.             for(a=2;a>0;a--);
  53. }
  54. /************************读值函数******************************/
  55. void Read_value()
  56. {       
  57.         uchar i,j=0,mask;
  58.         Bus=0;//主机拉低总线至少1ms(20ms)
  59.         for(i=0;i<20;i++)
  60.         {
  61.                 Delay1ms();
  62.         }
  63.         Bus=1;//主机主动拉高20us
  64.         while(Bus);//等待从机拉低总线
  65.         while(!Bus);//度过从机拉低时间
  66.         while(Bus);//度过从机拉高时间
  67.        
  68.         while(j<5)
  69.         {
  70.                 mask=0x80;
  71.                 for(i=0;i<8;i++)
  72.                 {
  73.                         while(!Bus);//度过数据位的低电平
  74.                         Delay20us();//延迟40us后进行电平检测
  75.                         Delay20us();               
  76.                         if(Bus==0)
  77.                         {
  78.                                 value[j]&=(~mask);
  79.                         }
  80.                         else
  81.                         {
  82.                                 value[j]|=mask;
  83.                         }
  84.                         mask>>=1;
  85.                         while(Bus);//度过剩余高电平(如果是1的话)
  86.                 }
  87.                 j++;
  88.         }
  89. }



  90. /**********************显示函数*************************************/
  91. void Show(uint x,y)
  92. {
  93.         char duan1[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//段码
  94.         char duan2[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
  95.         while(1)
  96.         {
  97.                 w1=1;//小数位
  98.                 w2=0;
  99.                 w3=0;
  100.                 w4=0;
  101.                 Delay10us();
  102.                 P3=duan1[x%10];
  103.                 P1=duan1[y%10];
  104.                 Delay1ms();
  105.                 P3=0xff;
  106.                 P1=0xff;


  107.                 w1=0;//个位
  108.                 w2=1;
  109.                 w3=0;
  110.                 w4=0;
  111.                 Delay10us();
  112.                 P3=duan2[(x/10)%10];
  113.                 P1=duan2[(y/10)%10];
  114.                 Delay1ms();
  115.                 P3=0xff;
  116.                 P1=0xff;

  117.                 w1=0;//十位
  118.                 w2=0;
  119.                 w3=1;
  120.                 w4=0;
  121.                 Delay10us();
  122.                 P3=duan1[(x/100)%10];
  123.                 P1=duan1[(y/100)%10];
  124.                 Delay1ms();
  125.                 P3=0xff;
  126.                 P1=0xff;

  127.                 w1=0;//百位
  128.                 w2=0;
  129.                 w3=0;
  130.                 w4=1;
  131.                 Delay10us();
  132.                 if(value[2]>127)//即温度最高位为1,表示负值
  133.                 {
  134.                         P3=0xbf;//显示负号
  135.                 }
  136.                 else
  137.                 {
  138.                         P3=duan1[(x/1000)%10];
  139.                 }
  140.                 P1=duan1[(y/1000)%10];
  141.                 Delay1ms();
  142.                 P3=0xff;
  143.                 P1=0xff;
  144.         }
  145. }

注意:该例程在Proteus仿真中已验证通过。但在Proteus仿真中,即使温湿度值没有问题也存在校验错误的情况,因此在该例程中没有加校验函数。实际使用中,可通过判断value[4]是否等于value[0]+value[1]+value[2]+value[3]的方式进行校验,若相等则校验成功。
 楼主| merry_zsp 发表于 2020-3-29 16:08 | 显示全部楼层

五、Proteus仿真程序

注意:虽然技术手册中要求对传感器的数据线接5.1K的上拉电阻,但在Proteus仿真中发现不用接即可,若接上反而会导致传感器无法对总线进行下拉,最终导致温湿度测量失败。

55325e80578e7a5e8.png



labasi 发表于 2020-4-7 14:09 | 显示全部楼层
非常感谢楼主分享
paotangsan 发表于 2020-4-7 14:09 | 显示全部楼层
非常感谢楼主分享
renzheshengui 发表于 2020-4-7 14:10 | 显示全部楼层
非常感谢楼主分享
wakayi 发表于 2020-4-7 14:10 | 显示全部楼层
非常感谢楼主分享
wowu 发表于 2020-4-7 14:10 | 显示全部楼层
非常感谢楼主分享
Anony2017 发表于 2020-6-4 16:07 | 显示全部楼层
如果打包好了就好了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

75

主题

695

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部