| 
 
   
- 帖子
 - 8 
 - 主题
 - 2 
 - 精华
 - 0 
 - 积分
 - 4 
 - 在线时间
 - 0 小时 
 - 注册时间
 - 2010-10-15 
 
  | 
AVR单片机操作温湿度传感器AM2301(又名DHT21)
 
 AM2301是国产的温湿度传感器,想较瑞士的SHT1X,价格低廉,但性能有所降低,在对性能 要求不是很高的情况下,可以考虑用该款温湿度传感器。  
       单片机对AM2301的操作非常简单,通过AM2301的数据手册,便可写出访问它的程序,例程如下,期望能达到抛砖引玉的目的,以AVR系列的Mega16为例:  
一、头文件  
/***********************************************************************************************  
文件:am2301.h  
作者:wxxujian  
用途:温湿度传感器AM2301(又名:DHT21)的驱动程序  
MCU: AVR Mega16 晶振:8MHz  
编译器:WinAVR2010  
版本:1.0(创建日期:2010-7-27) 能正常显示湿度,仅能显示正温度  
      1.1(修改日期:2010-7-28) 能正常显示湿度和温度(正、负温度均可)  
日期:2010-7-27  
***********************************************************************************************/  
 
#include <avr/io.h>  
 
#ifndef AM2301_H  
#define AM2301_H  
 
//////////////////////////////   宏定义(须根据实际情况而修改)  ///////////////////////////////  
 
//功能:定义与AM2301的数据位相连的单片机的端口及数据位  
//注意:这些宏须随着实际的硬件电路情况而修改  
 
#define AM2301_DATA_DDR DDRD  
#define AM2301_DATA_PORT PORTD  
#define AM2301_DATA_PIN PIND  
#define AM2301_DATA_BIT PD2  
 
//////////////////////////////   宏定义(结束)  ///////////////////////////////  
 
 
//////////////////////////////      函数声明    //////////////////////////////////////////////////  
//说明:共2个函数,分别是:  
// AM2301_CollectCharData(int *pvHumidity,int *pvTemperature)  
// AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)  
//详细内容如下:  
 
 
/********************************************************************************  
函数名:AM2301_CollectCharData(int *pvHumidity,int *pvTemperature)  
功  能:获得数据(湿度、温度),获得的数据保存于形参所提供的指针所指向的变量中  
返回值:  
0:数据校验正确;  
1:数据校验错误  
2:获取数据错误  
3: 等待响应信号错误  
参  数:  
pvHumidity:   湿度变量的指针,用于保存采集到的湿度,数据类型为:signed char,得到的数据仅为湿度的整数部分,小数部分自动舍弃  
pvTemperature:温度变量的指针,用于保存采集到的温度,数据类型为:signed char,得到的数据仅为温度的整数部分,小数部分自动舍弃  
 
 
说  明:建议执行此函数的间隔为2秒,绝不能小1秒。若间隔时间很长,建议采集2次,以2次为准  
当发生错误,即返回值为1、2或3时,应间隔2秒后重新读取数据  
注  意:因为:WinAVR默认将char 视为unsigned char   
所以:参数必须定义为signed char,-128<signed char<127,足以保存所得到的数据  
原  理:详见AM2301的数据手册  
*********************************************************************************/  
unsigned char AM2301_CollectCharData(signed char *pvHumidity,signed char *pvTemperature);  
 
/********************************************************************************  
函数名:AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)  
功  能:获得数据(湿度、温度),获得的数据保存于形参所提供的指针所指向的变量中  
返回值:  
0:数据校验正确;  
1:数据校验错误  
2:获取数据错误  
3: 等待响应信号错误  
参  数:  
pvHumidity:   湿度变量的指针,用于保存采集到的湿度,数据类型为:float,得到的数据为完整的数据,但不要用此float数据去比较  
pvTemperature:温度变量的指针,用于保存采集到的温度,数据类型为:float,得到的数据为完整的数据,但不要用此float数据去比较  
 
 
说  明:建议执行此函数的间隔为2秒,绝不能小1秒。若间隔时间很长,建议采集2次,以2次为准  
当发生错误,即返回值为1、2或3时,应间隔2秒后重新读取数据  
原  理:详见AM2301的数据手册  
*********************************************************************************/  
unsigned char AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature);  
 
//////////////////////////////      函数声明(结束)    //////////////////////////////////////////////////  
 
#endif  
 
二、实现文件  
/***********************************************************************************************  
文件:am2301.c  
作者:wxxujian  
用途:温湿度传感器AM2301(又名:DHT21)的驱动程序  
MCU: AVR Mega16 晶振:8MHz  
编译器:WinAVR2010  
版本:1.0(创建日期:2010-7-27) 能正常显示湿度,仅能显示正温度  
  1.1(修改日期:2010-7-28) 能正常显示湿度和温度(正、负温度均可)  
日期:2010-7-27  
***********************************************************************************************/  
 
#include "am2301.h"  
#include <util/delay.h>  
#include "common.h"  
#include "display.h"  
 
 
//////////////////////////////   宏定义(函数样式)   ///////////////////////////////////////////  
 
//功能:操作与am2301的数据位相连的单片机端口与相应位,包括:输入、输出、置1和清0  
//注意:这些宏只供此文件使用  
#define SetDataBitOutput() SetBit(AM2301_DATA_DDR,AM2301_DATA_BIT)  
#define SetDataBitInput() ClearBit(AM2301_DATA_DDR,AM2301_DATA_BIT)  
#define SetDataBit() SetBit(AM2301_DATA_PORT,AM2301_DATA_BIT)  
#define ClearDataBit() ClearBit(AM2301_DATA_PORT,AM2301_DATA_BIT)  
#define TestDataBit() TestBit(AM2301_DATA_PIN,AM2301_DATA_BIT)  
 
//////////////////////////////   宏定义(结束)   ///////////////////////////////////////////  
 
 
//////////////////////////////      函数实现    //////////////////////////////////////////////////  
//说明:共3个函数,分别是:  
// AM2301_ReadByte(unsigned char *pvData)  
// AM2301_CollectCharData(int *pvHumidity,int *pvTemperature)  
// AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)  
//详细内容如下:  
 
/********************************************************************************  
函数名:AM2301_ReadByte(unsigned char *pvData)  
功  能:读取1个字节的数据  
返回值:0:成功;2:读数据错误  
参  数:pvData:所读取的数据  
条  件:与am2301的数据位相连的单片机端口为“输入模式”  
注  意:此函数为辅助函数,仅供本文件使用,外部无法访问  
原  理:数据是从高位往低位依次读取,读得数据的顺序为:湿度高位+湿度低位+温度高位+温度低位+校验位  
*********************************************************************************/  
unsigned char AM2301_ReadByte(unsigned char *pvData)  
{  
unsigned char lvReturn=0,lvI,lvCount,lvBit;  
 
for(lvI=0;lvI<8;lvI++) //循环8次,得到1个字节(含8个数据位)的数据  
{  
lvCount=1;  
while( ! TestDataBit()  && lvCount>0 ) //判断丛机是否发来50us的低电平信号,若超时返回2  
lvCount++;  
if(lvCount==0)  
{  
lvReturn=2;  
break;  
}  
 
_delay_us(35); //延时35us  
 
//判断数据是0或1  
lvBit=0;  
if(TestDataBit())  
lvBit=1;  
 
lvCount=1;  
while( TestDataBit()  && lvCount>0 ) //判断丛机是否发来26-28us的高电平信号,若超时返回2  
lvCount++;  
if(lvCount==0)  
{  
lvReturn=2;  
break;  
}  
 
//把得到的每一位数据保存于pvData中  
if(lvBit)  
*pvData |= 1<<(7-lvI);  
else  
*pvData &= ~1<<(7-lvI);  
 
}  
 
return lvReturn;  
}  
 
 
/********************************************************************************  
函数名:AM2301_CollectCharData(int *pvHumidity,int *pvTemperature)  
功  能:获得数据(湿度、温度),获得的数据保存于形参所提供的指针所指向的变量中  
返回值:  
0:数据校验正确;  
1:数据校验错误  
2:获取数据错误  
3: 等待响应信号错误  
参  数:  
pvHumidity:   湿度变量的指针,用于保存采集到的湿度,数据类型为:signed char,得到的数据仅为湿度的整数部分,小数部分自动舍弃  
pvTemperature:温度变量的指针,用于保存采集到的温度,数据类型为:signed char,得到的数据仅为温度的整数部分,小数部分自动舍弃  
 
 
说  明:建议执行此函数的间隔为2秒,绝不能小1秒。若间隔时间很长,建议采集2次,以2次为准  
当发生错误,即返回值为1、2或3时,应间隔2秒后重新读取数据  
注  意:因为:WinAVR默认将char 视为unsigned char   
所以:参数必须定义为signed char,-128<signed char<127,足以保存所得到的数据  
原  理:详见AM2301的数据手册  
*********************************************************************************/  
unsigned char AM2301_CollectCharData(signed char *pvHumidity,signed char *pvTemperature)  
{  
unsigned char lvReturn=3,lvCount;  
unsigned int  lvTemp16;  
int lvTemp;  
 
unsigned char lvHumidityHigh; //湿度高位  
unsigned char lvHumidityLow;          //湿度低位  
unsigned char lvTemperatureHigh; //温度高位  
unsigned char lvTemperatureLow; //温度低位  
unsigned char lvCheck; //校验位  
 
 
//主机的操作  
SetDataBitOutput();  
ClearDataBit(); //拉低总线  
_delay_us(500); //持续500us  
SetDataBit(); //释放总线  
 
//主机检测丛机  
SetDataBitInput();  
_delay_us(40);  
 
if(! TestDataBit())  
{  
lvCount=1;  
while( ! TestDataBit() && lvCount >0)  //判断丛机是否发送了80us的高电平信号  
lvCount++;  
if(lvCount==0)  
return 3;  
 
lvCount=1;  
while( TestDataBit() && lvCount >0)  //判断丛机是否发送了80us的高电平信号  
lvCount++;  
if(lvCount==0)return 3;  
 
if(AM2301_ReadByte(&lvHumidityHigh)) //获得湿度高位  
return 2;  
 
if(AM2301_ReadByte(&lvHumidityLow)) //获得湿度高位  
return 2;  
 
if(AM2301_ReadByte(&lvTemperatureHigh)) //获得湿度高位  
return 2;  
 
if(AM2301_ReadByte(&lvTemperatureLow)) //获得湿度高位  
return 2;  
 
if(AM2301_ReadByte(&lvCheck)) //获得湿度高位  
return 2;  
 
lvCount=lvHumidityHigh+lvHumidityLow+lvTemperatureHigh+lvTemperatureLow;//计算湿度高位+湿度低位+温度高位+温度低位的和  
 
if(lvCount==lvCheck) //数据校验,若正确则获得正确的湿度和温度,并返回1  
{  
//lvTemperatureHigh |=0x80;  
 
//把湿度的高位和地位组合,得到完整的湿度  
lvTemp16=lvHumidityHigh;  
lvTemp16 <<=8;  
lvTemp16 |= lvHumidityLow;  
*pvHumidity=lvTemp16/10;  
 
//把温度的高位和地位组合,得到完整的温度  
lvTemp16=lvTemperatureHigh;  
lvTemp16 <<=8;  
lvTemp16 |= lvTemperatureLow;  
 
if(lvTemp16 & 0x8000) //如果温度是负值,则转化  
{  
lvTemp16 &=0x7FFF;  
lvTemp=0-lvTemp16;  
}  
*pvTemperature=lvTemp /10 ;  
 
lvReturn=0;  
}  
else //数据校验,若错误,则返回1  
lvReturn=1;  
 
}  
return lvReturn;  
 
}  
/********************************************************************************  
函数名:AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)  
功  能:获得数据(湿度、温度),获得的数据保存于形参所提供的指针所指向的变量中  
返回值:  
0:数据校验正确;  
1:数据校验错误  
2:获取数据错误  
3: 等待响应信号错误  
参  数:  
pvHumidity:   湿度变量的指针,用于保存采集到的湿度,数据类型为:float,得到的数据为完整的数据,但不要用此float数据去比较  
pvTemperature:温度变量的指针,用于保存采集到的温度,数据类型为:float,得到的数据为完整的数据,但不要用此float数据去比较  
 
 
说  明:建议执行此函数的间隔为2秒,绝不能小1秒。若间隔时间很长,建议采集2次,以2次为准  
当发生错误,即返回值为1、2或3时,应间隔2秒后重新读取数据  
原  理:详见AM2301的数据手册  
*********************************************************************************/  
unsigned char AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)  
{  
unsigned char lvReturn=0;  
signed   char lvHumidity; //湿度  
signed   char lvTemperature; //温度  
 
lvReturn=AM2301_CollectCharData(&lvHumidity,&lvTemperature);  
if(lvReturn) //若出错,则直接返回  
return lvReturn;  
 
//若正确读取了数据,则转化为float型数据  
*pvHumidity=lvHumidity/10;  
*pvTemperature=lvTemperature/10;  
 
return lvReturn;  
}  
 
 
//////////////////////////////      函数实现(结束)    //////////////////////////////////////////////////  |  |    |  
  |   
 
 
 
 |