AM2301是國(guó)產(chǎn)的溫濕度傳感器,想較瑞士的SHT1X,價(jià)格低廉,但性能有所降低,在對(duì)性能 要求不是很高的情況下,可以考慮用該款溫濕度傳感器。 AM2301/DHT21電容型數(shù)字溫濕度傳感器(替代SHT10 SHT11 SHT15)。
單片機(jī)對(duì)AM2301的操作非常簡(jiǎn)單,通過(guò)AM2301的數(shù)據(jù)手冊(cè),便可寫出訪問(wèn)它的程序,例程如下,期望能達(dá)到拋磚引玉的目的,以AVR系列的Mega16為例:
一、頭文件
[code="CSHARP"]二、實(shí)現(xiàn)文件
[code="c"]
/***********************************************************************************************
文件:am2301.c
作者:wxxujian
用途:溫濕度傳感器AM2301(又名:DHT21)的驅(qū)動(dòng)程序
MCU: AVR Mega16 晶振:8MHz
編譯器:WinAVR2010
版本:1.0(創(chuàng)建日期:2010-7-27) 能正常顯示濕度,僅能顯示正溫度
1.1(修改日期:2010-7-28) 能正常顯示濕度和溫度(正、負(fù)溫度均可)
日期:2010-7-27
***********************************************************************************************/
#include "am2301.h"
#include <util/delay.h>
#include "common.h"
#include "display.h"
////////////////////////////// 宏定義(函數(shù)樣式) ///////////////////////////////////////////
//功能:操作與am2301的數(shù)據(jù)位相連的單片機(jī)端口與相應(yīng)位,包括:輸入、輸出、置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)
////////////////////////////// 宏定義(結(jié)束) ///////////////////////////////////////////
////////////////////////////// 函數(shù)實(shí)現(xiàn) //////////////////////////////////////////////////
//說(shuō)明:共3個(gè)函數(shù),分別是:
// AM2301_ReadByte(unsigned char *pvData)
// AM2301_CollectCharData(int *pvHumidity,int *pvTemperature)
// AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)
//詳細(xì)內(nèi)容如下:
/********************************************************************************
函數(shù)名:AM2301_ReadByte(unsigned char *pvData)
功 能:讀取1個(gè)字節(jié)的數(shù)據(jù)
返回值:0:成功;2:讀數(shù)據(jù)錯(cuò)誤
參 數(shù):pvData:所讀取的數(shù)據(jù)
條 件:與am2301的數(shù)據(jù)位相連的單片機(jī)端口為“輸入模式”
注 意:此函數(shù)為輔助函數(shù),僅供本文件使用,外部無(wú)法訪問(wèn)
原 理:數(shù)據(jù)是從高位往低位依次讀取,讀得數(shù)據(jù)的順序?yàn)椋簼穸雀呶?濕度低位+溫度高位+溫度低位+校驗(yàn)位
*********************************************************************************/
unsigned char AM2301_ReadByte(unsigned char *pvData)
{
unsigned char lvReturn=0,lvI,lvCount,lvBit;
for(lvI=0;lvI<8;lvI++) //循環(huán)8次,得到1個(gè)字節(jié)(含8個(gè)數(shù)據(jù)位)的數(shù)據(jù)
{
lvCount=1;
while( ! TestDataBit() && lvCount>0 ) //判斷叢機(jī)是否發(fā)來(lái)50us的低電平信號(hào),若超時(shí)返回2
lvCount++;
if(lvCount==0)
{
lvReturn=2;
break;
}
_delay_us(35); //延時(shí)35us
//判斷數(shù)據(jù)是0或1
lvBit=0;
if(TestDataBit())
lvBit=1;
lvCount=1;
while( TestDataBit() && lvCount>0 ) //判斷叢機(jī)是否發(fā)來(lái)26-28us的高電平信號(hào),若超時(shí)返回2
lvCount++;
if(lvCount==0)
{
lvReturn=2;
break;
}
//把得到的每一位數(shù)據(jù)保存于pvData中
if(lvBit)
*pvData |= 1<<(7-lvI);
else
*pvData &= ~1<<(7-lvI);
}
return lvReturn;
}
/********************************************************************************
函數(shù)名:AM2301_CollectCharData(int *pvHumidity,int *pvTemperature)
功 能:獲得數(shù)據(jù)(濕度、溫度),獲得的數(shù)據(jù)保存于形參所提供的指針?biāo)赶虻淖兞恐?
返回值:
0:數(shù)據(jù)校驗(yàn)正確;
1:數(shù)據(jù)校驗(yàn)錯(cuò)誤
2:獲取數(shù)據(jù)錯(cuò)誤
3: 等待響應(yīng)信號(hào)錯(cuò)誤
參 數(shù):
pvHumidity: 濕度變量的指針,用于保存采集到的濕度,數(shù)據(jù)類型為:signed char,得到的數(shù)據(jù)僅為濕度的整數(shù)部分,小數(shù)部分自動(dòng)舍棄
pvTemperature:溫度變量的指針,用于保存采集到的溫度,數(shù)據(jù)類型為:signed char,得到的數(shù)據(jù)僅為溫度的整數(shù)部分,小數(shù)部分自動(dòng)舍棄
說(shuō) 明:建議執(zhí)行此函數(shù)的間隔為2秒,絕不能小1秒。若間隔時(shí)間很長(zhǎng),建議采集2次,以2次為準(zhǔn)
當(dāng)發(fā)生錯(cuò)誤,即返回值為1、2或3時(shí),應(yīng)間隔2秒后重新讀取數(shù)據(jù)
注 意:因?yàn)椋篧inAVR默認(rèn)將char 視為unsigned char
所以:參數(shù)必須定義為signed char,-128<signed char<127,足以保存所得到的數(shù)據(jù)
原 理:詳見(jiàn)AM2301的數(shù)據(jù)手冊(cè)
*********************************************************************************/
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; //校驗(yàn)位
//主機(jī)的操作
SetDataBitOutput();
ClearDataBit(); //拉低總線
_delay_us(500); //持續(xù)500us
SetDataBit(); //釋放總線
//主機(jī)檢測(cè)叢機(jī)
SetDataBitInput();
_delay_us(40);
if(! TestDataBit())
{
lvCount=1;
while( ! TestDataBit() && lvCount >0) //判斷叢機(jī)是否發(fā)送了80us的高電平信號(hào)
lvCount++;
if(lvCount==0)
return 3;
lvCount=1;
while( TestDataBit() && lvCount >0) //判斷叢機(jī)是否發(fā)送了80us的高電平信號(hào)
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;//計(jì)算濕度高位+濕度低位+溫度高位+溫度低位的和
if(lvCount==lvCheck) //數(shù)據(jù)校驗(yàn),若正確則獲得正確的濕度和溫度,并返回1
{
//lvTemperatureHigh |=0x80;
//把濕度的高位和地位組合,得到完整的濕度
lvTemp16=lvHumidityHigh;
lvTemp16 <<=8;
lvTemp16 |= lvHumidityLow;
*pvHumidity=lvTemp16/10;
//把溫度的高位和地位組合,得到完整的溫度
lvTemp16=lvTemperatureHigh;
lvTemp16 <<=8;
lvTemp16 |= lvTemperatureLow;
if(lvTemp16 & 0x8000) //如果溫度是負(fù)值,則轉(zhuǎn)化
{
lvTemp16 &=0x7FFF;
lvTemp=0-lvTemp16;
*pvTemperature=lvTemp /10 ;
}
else
{
*pvTemperature=lvTemp16/10 ;
}
lvReturn=0;
}
else //數(shù)據(jù)校驗(yàn),若錯(cuò)誤,則返回1
lvReturn=1;
}
return lvReturn;
}
/********************************************************************************
函數(shù)名:AM2301_CollectFloatData(float *pvHumidity,float *pvTemperature)
功 能:獲得數(shù)據(jù)(濕度、溫度),獲得的數(shù)據(jù)保存于形參所提供的指針?biāo)赶虻淖兞恐?
返回值:
0:數(shù)據(jù)校驗(yàn)正確;
1:數(shù)據(jù)校驗(yàn)錯(cuò)誤
2:獲取數(shù)據(jù)錯(cuò)誤
3: 等待響應(yīng)信號(hào)錯(cuò)誤
參 數(shù):
pvHumidity: 濕度變量的指針,用于保存采集到的濕度,數(shù)據(jù)類型為:float,得到的數(shù)據(jù)為完整的數(shù)據(jù),但不要用此float數(shù)據(jù)去比較
pvTemperature:溫度變量的指針,用于保存采集到的溫度,數(shù)據(jù)類型為:float,得到的數(shù)據(jù)為完整的數(shù)據(jù),但不要用此float數(shù)據(jù)去比較
說(shuō) 明:建議執(zhí)行此函數(shù)的間隔為2秒,絕不能小1秒。若間隔時(shí)間很長(zhǎng),建議采集2次,以2次為準(zhǔn)
當(dāng)發(fā)生錯(cuò)誤,即返回值為1、2或3時(shí),應(yīng)間隔2秒后重新讀取數(shù)據(jù)
原 理:詳見(jiàn)AM2301的數(shù)據(jù)手冊(cè)
*********************************************************************************/
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) //若出錯(cuò),則直接返回
return lvReturn;
//若正確讀取了數(shù)據(jù),則轉(zhuǎn)化為float型數(shù)據(jù)
*pvHumidity=lvHumidity/10;
*pvTemperature=lvTemperature/10;
return lvReturn;
}
[/code]
////////////////////////////// 函數(shù)實(shí)現(xiàn)(結(jié)束) //////////////////////////////////////////////////