项目中涉及到温湿度传感器,原理图给出,用DHT11温湿度一体IC

DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数
字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一
个电阻式感湿元件和一个 NTC  测温元件。

单总线说明
DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线
完成。设备(主机或从机)通过一个漏枀开路或三态端口连至该数据线,以允许设备在不发送数据时能够
释放总线,而让其它设备使用总线;单总线通常要求外接一个约  5.1kΩ 的上拉电阻,这样,当总线闲置时,
其状态为高电平。由于它们是主从结极,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须
严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。

单总线传送数据位定义
DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次传送 40 位数据,高位先
出。
数据格式:
8bit 湿度整数数据  + 8bit 湿度小数数据+8bit 温度整数数据  + 8bit 温度小数数据+8bit 校验位。

校验位数据定义

“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
下面是一些代码,其中涉及到时序的地方做出注释
uint32_t Read_Temp_Hum(uint8_t *temp, uint8_t *hum)
 {
   uint32_t cnt_last;
   uint8_t hum_10, hum_01, temp_10, temp_01, chksum, chk;
   uint32_t tc1, tc;
   uint32_t i;


   p3_2_counter = 0; // 用来检测中断是否产生,在中断中进行p3_2_counter++;
   cnt_last = p3_2_counter;


   GPIOIntDisable(PORT1, 5);

  /************************************************************************************************   微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms,然后微处理器的 I/O
    设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变高,等待 DHT11 作
    出回答信号**************************************************************************************************/
   GPIOSetDir(PORT1, 5, 1); // Set PIO1_5 to output
   GPIOSetValue(PORT1, 5, 0);
   delay_ms(30); //保证时间大于18ms
   GPIOSetValue(PORT1, 5, 1); //变成高电平


   GPIOSetDir(PORT1, 5, 0); //set PIO1_5 to input


   GPIOSetInterrupt(PORT1, 5, 0, 0, 0); //设置下降沿触发,使能中断
   GPIOIntEnable(PORT1, 5);/************************************************************************************************
  DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA
   引脚处于输出状态,输出  80 微秒的低电平作为应答信号,紧接着输出  80  微秒的高电平通知外设准备接
   收数据,微处理器的  I/O  此时处于输入状态,检测到  I/O  有低电平(DHT11 回应信号)后,等待 80 微秒的高电平后的数据接收**************************************************************************************************/
 


   for(i=0; i<3; i++) 
 //应答信号刚好是三个跳变沿,全部接受后,进行数据的接收 

   { 

     GPIOSetInterrupt(PORT1, 5, 0, 0, i&0x01); 

     while(p3_2_counter == cnt_last); 
 //用来检测是否有中断产生,生成中断后p3_2_counter++; 

     cnt_last = p3_2_counter; 

   } 


 /************************************************************************************************ 
   由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,
   位数据“0”的格式为:  50  微秒的低电平和  26-28  微秒的高电平。
   位数据“1”的格式为:  50  微秒的低电平加  70  微秒的高电平。
**************************************************************************************************/
   for(i=0; i<40; i++)
   {
GPIOSetInterrupt(PORT1, 5, 0, 0, 1);
     while(p3_2_counter == cnt_last); //功能同上
     cnt_last = p3_2_counter;
tc1 = p3_2_tc;  // p3_2_tc = SysTick->VAL;在中断中完成


GPIOSetInterrupt(PORT1, 5, 0, 0, 0);
     while(p3_2_counter == cnt_last);
     cnt_last = p3_2_counter;


if(p3_2_tc < tc1)
{
 tc = tc1 - p3_2_tc;    //高电平时间,低电平都是50us不判断,判断高电平是时间来判断是‘0’ or ‘1’
}
else
{
 tc = 48000 - (p3_2_tc - tc1);
}/***********************************************************************************************

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

    数据格式: 

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



if(i < 8) 

{ 

 hum_10 <<= 1; 

 if(tc >= 2328) 
// 这里的2328是怎么得到的,系统时钟设置为48MHz,(1/48MHZ )*2328 = 48.5us; 
   hum_10 |= 0x01;// 上面提到位数据“0”时高电平26-28 微秒我们取27us,位数据“1”时高电平70,
} // 判断高低的临界值(27 + 70)/2 = 48.5;
else if(i < 16)
{
 hum_01 <<= 1;
 if(tc >= 2328)
   hum_01 |= 0x01;
}
else if(i < 24)
{
 temp_10 <<= 1;
 if(tc >= 2328)
   temp_10 |= 0x01;
}
else if(i < 32)
{
 temp_01 <<= 1;
 if(tc >= 2328)
   temp_01 |= 0x01;
}
else
{
 chksum <<= 1;
 if(tc >= 2328)
   chksum |= 0x01;
}
   }

 /***********************************************************************************************   当一位数据传输结束后,总线重新恢复高电平状态,下面的一次中断,就是恢复高电平状态同时也用来
   同步p3_2_counter == cnt_last;
**************************************************************************************************/

   GPIOSetInterrupt(PORT1, 5, 0, 0, 1);
   while(p3_2_counter == cnt_last);


   GPIOIntDisable(PORT1, 5);


   *temp = temp_10;
   *(temp+1) = temp_01;


   *hum = hum_10;
   *(hum+1) = hum_01;/************************************************************************************************
   下面是对校验位核对,如上面所诉
  “8bit 湿度整数数据  + 8bit 湿度小数数据+8bit 温度整数数据  + 8bit 温度小数数据” 8bit 校验位等于所
**************************************************************************************************/
 

   chk = hum_10; 

   chk += hum_01; 

   chk += temp_10; 

   chk += temp_01; 



   if(chk == chksum) 

     return 1; 

   else 

     return 0; 

 }


以上就是单总线下温湿度传感器的核心代码,其中中断部分不同处理器定义不同,这里就不进行阐述了。还有不处理器的系统时钟设置不同,在临界值得判断也不一样。