基于LPC11C14和DHT11的温湿度传感器编程

本文介绍了如何使用LPC11C14单片机通过单总线通信方式与DHT11温湿度传感器进行数据交互,详细阐述了数据格式、校验位计算方法以及读取步骤,并提供了一个编程示例,适用于温湿度监测系统的开发。

一、模块简介

DHT11数字温度传感器是一款含有已校准数字信号输出的温湿度符合传感器。它应用专用的数字模块技术和温湿度传感技术,确保产品具有可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连。可应用于暖通空调、除湿器、测试及检测设备、消费品、汽车、自动控制、数据记录器、气象站、家电、温度调节器、医疗等其他相关温湿度检测控制。

二、使用方法

DHT11器件采用简单的单总线通信方式,系统中的数据交换、控制均由单总线完成。

1)单总线传送数据位定义

DATA用于微处理器与DHT11 之间的通讯和同步,采用单总线数据格式,一次传送40位数据,高位先出。

 数据格式:

8bit湿度整数数据  + 8bit湿度小数数据+8bit温度整数数据  + 8bit温度小数数据+8bit校验位。

2)校验位数据定义

“8bit湿度整数数据  + 8bit湿度小数数据+8bit温度整数数据  + 8bit温度小数数据”8bit校验位等于所得结果的末 8位。

示例一:接收到的40位数据为:

0011 0101       0000 0000        0001 1000       0000 0000        0100 1101

湿度高 8位    湿度低8位    温度高8 位     温度低8 位      校验位

计算:

0011 0101+0000 0000+0001 1000+0000 0000= 0100 1101

接收数据正确:

湿度:0011 0101=35H=53%RH

温度:0001 1000=18H=24℃

 

示例二:接收到的40位数据为:

0011 0101      0000 0000        0001 1000       0000 0000        0100 1001

湿度高 8位    湿度低8位   温度高8位     温度低8 位         校验位

计算:

0011 0101+0000 0000+0001 1000+0000 0000=  0100 1101

01001101 不等于0100 1001

本次接收的数据不正确,放弃,重新接收数据。

 

 

3)外设读取步骤

步骤一:

DHT11 上电后(DHT11上电后要等待  1S 以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,幵记录数据,同时  DHT11的DATA数据线由上拉电阻拉高一直保持高电平;此时  DHT11的 DATA 引脚处于输入状态,时刻检测外部信号。

步骤二:

微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms,然后微处理器的 I/O设置为输入状态,由于上拉电阻,微处理器的 I/O即 DHT11的 DATA数据线也随之变高,等待 DHT11作出回答信号,发送信号如图所示:

 

 

步骤三:

DHT11 的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的DATA引脚处于输出状态,输出  80微秒的低电平作为应答信号,紧接着输出  80 微秒的高电平通知外设准备接收数据,微处理器的  I/O 此时处于输入状态,检测到  I/O 有低电平(DHT11回应信号)后,等待80微秒

的高电平后的数据接收,发送信号如图所示:

 

 

步骤四:

由DHT11的 DATA引脚输出40位数据,微处理器根据 I/O电平的变化接收40 位数据,位数据“0”的格式为:  50 微秒的低电平和  26-28 微秒的高电平,位数据“1”的格式为:  50 微秒的低电平加70微秒的高电平。位数据“0”、“1”格式信号如图所示:

 

 

结束信号:

DHT11 的DATA引脚输出 40 位数据后,继续输出低电平50 微秒后转为输入状态,由于上拉电阻随之变为高电平。但 DHT11内部重测环境温湿度数据,幵记录数据,等待外部信号的到来。

 

三、编程示例

注:本段程序是读取DHT11数据的核心代码,为不完整的片段,旨在说明DHT11模块在编程控制的编写方法,使用时请根据具体情况进行完善。

uint32_t Read_Temp_Hum(uint8_t *temp, uint8_t *hum)

{

  uint32_t   cnt_last;          //32位无符号整形变量,用来辅助记录中断计数

  uint8_t     temp10, temp01, hum10, hum01, chksum, chk; //温湿度的高低位和校验位

  uint32_t   tc1, tc;             //保存时钟值

  uint32_t   i;               //循环计数器

 

  p3_2_counter = 0;                 //中断计数器

  cnt_last = p3_2_counter;

 

  GPIOSetDir(PORT3, 2, 1);             // 设置对应引脚为输出模式

  GPIOSetValue(PORT3, 2, 0);          //设置输出为低电平

  delay_ms(30);            //保持大于18ms的低电平

  GPIOSetValue(PORT3, 2, 1);    //电平拉高释放总线

 

  GPIOSetDir(PORT3, 2, 0);             //设置为输入模式

  GPIOSetInterrupt(PORT3, 2, 0, 0, 0);   //设置控制器为下降沿中断模式

  GPIOIntEnable(PORT3, 2);            //使能中断

 

  for(i=0; i<3; i++)       //此段代码作用是运用中断获取DHT11的应答信号通知

  {

    GPIOSetInterrupt(PORT3, 2, 0, 0, i&0x01);  //分别设置上升沿或下降沿中断来捕获DHT11的应答信号(三次沿跳变,实际上是两次电平跳变)。

    while(p3_2_counter == cnt_last);          //死循环,等待中断触发,在中断处理函数中改变cnt_counter的值,跳出循环。

    cnt_last = p3_2_counter;                 //使两变量的值相等,为下次中断等待做准备。

  }

 

  for(i=0; i<40; i++)                //此段代码作用是开始读取40位温湿度数据,仍然用中断获取数据起始通知

  {

      GPIOSetInterrupt(PORT3, 2, 0, 0, 1);      //上升沿触发,捕获数据起始位

    while(p3_2_counter == cnt_last);                 //等待触发

    cnt_last = p3_2_counter;

      tc1 = p3_2_tc;        //先在中断处理函数中将当前时钟值保存到p3_2_tc中,中断出发后赋值给tc1

      GPIOSetInterrupt(PORT3, 2, 0, 0, 0);      //下降沿触发,捕获数据结束

    while(p3_2_counter == cnt_last);                      //等待触发

    cnt_last = p3_2_counter;                

      if(p3_2_tc < tc1)                //计算时间差,用以判断是数据1还是数据0

      {

        tc = tc1 - p3_2_tc;

      }

      else

      {

        tc = 48000 - (p3_2_tc - tc1);   //这里一定要根据具体芯片的时钟频做计算

      }

 

      if(i < 8) //湿度高八位(高位先出)

      {

        temp10 <<= 1;

        if(tc >= 2328)      //2328在本处理器中时间长度是48.5uS,大于则为数据1位

          temp10 |= 0x01;

      }

      else if(i < 16)          //湿度低八位

      {

        temp01 <<= 1;

        if(tc >= 2328)

          temp01 |= 0x01;

      }

      else if(i < 24)          //温度高8位

      {

        hum10 <<= 1;

        if(tc >= 2328)

          hum10 |= 0x01;

      }

      else if(i < 32)          //温度高八位

      {

        hum01 <<= 1;

        if(tc >= 2328)

          hum01 |= 0x01;

      }

      else            //8位校验位

      {

        chksum <<= 1;

        if(tc >= 2328)

          chksum |= 0x01;

      }

  }

 

  GPIOSetInterrupt(PORT3, 2, 0, 0, 1);         //上升沿触发,DHT11释放总线,数据传输结束

  while(p3_2_counter == cnt_last);

//以下代码是数据的校验

  *temp = temp10;

  *(temp+1) = temp01;

 

  *hum = hum10;

  *(hum+1) = hum01;

 

  chk = temp10;

  chk += temp01;

  chk += hum10;

  chk += hum01;

 

  if(chk == chksum)

    return 1;

  else

    return 0;

}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值