//IO定義
#define P_DataIN_DHT11 PB0_IN
#define P_DataOUT_DHT11 PB0_OUT
//宏定義
#define BSET_DHT11 P_DataOUT_DHT11 = 1
#define BCLR_DHT11 P_DataOUT_DHT11 = 0
//***************************************
// 模塊功能:讀取DHT11的數據
// 該模塊為溫濕度傳感器 當主機給啟動信號后
// 該模塊會連續發出5個字節的數據 共耗時約4MS
// 第一二個字節為濕度數據的整數與小數部分
// 第三四個字節為溫度數據的整數與小數部分
// 第五個字節為校驗碼 它是前四個數據相加后的后8位的數值
// 程序帶未傳感器未連接檢測 及讀數據超時處理
//***************************************
//*************************************
// 函數名稱:VerificaDHT11Data
// 函數功能:效驗DHT11所讀的數據是否正確
// 入口參數:
// 出口參數:校驗正確返回1 否則返回0
// 備注:
//***************************************/
uint8 VerificaDHT11Data(uint8 *a)
{
uint8 i ;
uint8 Tmp = 0 ;
uint16 wTmp = 0 ;
for(i=0;i<4;i++)
{
wTmp += a[i] ;
}
Tmp = (uint8)(wTmp & 0x00ff) ; //取低8位數據
if(Tmp == a[4])
{
return 1 ;
}
else
{
return 0 ;
}
}
//*************************************
// 函數名稱:ReadPinDHT11
// 函數功能:讀管腳並濾波
// 入口參數:
// 出口參數:返回管腳狀態 Fcpu=16M時 耗時6US
//***************************************/
uint8 ReadPinDHT11(void)
{
uint8 Tcon = 0 ;
uint8 i ;
for(i=0;i<5;i++) //讀5次
{
_asm("nop") ;//延時
_asm("nop") ;
_asm("nop") ;
_asm("nop") ;
_asm("nop") ;
if(P_DataIN_DHT11 == 1)
{
Tcon ++ ;
}
}
if(Tcon >= 3) //讀狀態為1的次數大於3次
{
return 1 ;
}
else
{
return 0 ;
}
}
//=====讀一字節數據======
uint8 ReadDHT11DataByte(uint8 InValue)
{
uint8 Data = 0 ;
uint8 i = 0 ;
uint8 ucTOver = 0 ; //等待超時時間
for(i=0;i<8;i++)
{
ucTOver = 30 ; //200U
while(!ReadPinDHT11()&&(ucTOver--)) ; //等待高電平的到來
Nopt(VT_DLY40U) ; //延時40U
Data <<= 1;
ucTOver = 30 ; //200U
if(ReadPinDHT11()&&(ucTOver--)) //判斷IO是否還是被拉高的狀態
{
Data |= 0x01 ;
//讀最后一BIT數據時 不等待高電平
ucTOver = 30 ; //200U
while(ReadPinDHT11()&&(ucTOver--)) ; //等待IO被外設拉低
}
}
return Data ;
}
//*************************************
// 函數名稱:ReadDH11Data
// 函數功能:讀取DHT
// 入口參數:
// 出口參數:返回讀取的數據
// 當讀取到數據時 返回1 未讀取到數據返回0
//***************************************/
uint8 ReadDHT11Data(uint8 *a)
{
uint8 i ;
uint8 ucTOver = 0 ; //等待超時時間
Nopt(VT_DLY40U) ; //延時40U
if(ReadPinDHT11())
{
Nopt(VT_DLY40U) ; //延時40U
//從機一直沒有回應 直接退出
if(ReadPinDHT11())
{
return 0 ;
}
}
//等待從機回應信號結束
ucTOver = 30 ; //200U
while(!ReadPinDHT11()&&(ucTOver--)) ; //從機拉低時一直等待
ucTOver = 30 ; //200U
while(ReadPinDHT11()&&(ucTOver--)) ; //從機拉高時一直等待
for(i=0;i<5;i++) //讀5字節數據
{
*a = ReadDHT11DataByte(i) ;
a++ ;
}
return 1 ;
}
//*************************************
// 函數名稱:CmdDHT11Data
// 函數功能:讀DHT11的濕度 溫度
// 入口參數:延時時間
// 出口參數:無
//***************************************/
void CmdDHT11Data(void)
{
static uint16 Tcyc = 0 ;
static uint8 Tcon = 0 ;
static uint8 TNum = 0 ;
uint8 Tmp = 0 ;
uint16 wTmp = 0 ;
uint8 i ;
Tcyc ++ ;
if(Tcyc >= (VT_1S*VT_READDHT11)) //1s讀取一次數據
{
Tcyc = 0 ;
F_ReadD11 = 1 ;
Tcon = 0 ;
}
if(F_ReadD11) //准備啟動從機 1S動作一次
{
if(Tcon < 4) // 主機啟動 拉低40ms
{
Tcon ++ ;
BCLR_DHT11 ;
}
else
{
F_ReadD11 = 0 ;
F_TestDH11 = 0 ; //讀數據前清掉工作正常標志
for(i=0;i<5;i++) //清空數據緩存
{
aDHT11Data[i] = 0 ;
}
BSET_DHT11 ; //主機拉高 等待從機回應
//從DHT11讀數據
Tmp = ReadDHT11Data(aDHT11Data) ;//
BSET_DHT11 ; //釋放總線
if(Tmp != 0)//讀數據有效
{
if(VerificaDHT11Data(aDHT11Data))
{
F_ReadD11OK = 1 ;//校驗 成功
TNum = 0 ;
}
}
else //傳感器未連接出錯
{
TNum ++ ;
if(TNum >= 4)
{
TNum = 0 ;
F_ERRD11 = 1 ;
}
}
}
}
}
//*************************************
// 函數名稱:CountDHT11
// 函數功能:計算濕度
// 入口參數:延時時間
// 出口參數:無
//***************************************/
void CountHumidity(void)
{
uint8 Tmp ;
static uint8 R_Save[3];
if(!F_ReadD11OK) return ;
F_ReadD11OK = 0 ;
//對數據進行濾波取中值處理
RMovData_Byte(R_Save,3);
R_Save[0] = aDHT11Data[0] ;
//保存結果
Humidity = Order_Byte(R_Save); //處理位數最大3位
F_TestDH11 = 1 ; //DHT11 工作正常
}
//======================================================
//=======main========================================
//======================================================
void main(void)
{
while(1)
{
while(!F_10MS); // 主程序10MS跑一次
F_10MS = 0 ;
CmdDHT11Data() ; //讀DHT11數據
CountHumidity() ; // 計算濕度
}
}
