/*********************************************************************************************
程序名: DHT11驅動程序
編寫人: 王朗的誘惑
編寫時間: 2015年8月4日
硬件支持: STC12C5A60S2 DHT11
接口說明: DHT11:VCC GND DATA
*********************************************************************************************
說明:1、單片機是STC12C5A60S2,晶振頻率12MHz,實驗成功。換用12T單片機或別的晶振的時候要修改
延時函數和JUDGE。程序里判斷超時的變量t的閥值也要改。
2、好東西要共享,大家隨意折騰~~
*********************************************************************************************/
#include <STC12C5A60S2.H>
typedef unsigned char uchar;
typedef unsigned int uint;
#define JUDGE 30 //用于判斷通信的0和1,與單片機速度和晶振頻率有關
sbit DATA = P1^0; //定義數據引腳
uchar dat_r[5]; //用于存放從DHT11讀取到的數值
/*********************************************************************************************
函數名:延時函數
調 用:Delay30us();/Delay20ms();/Delay1s();
參 數:無
返回值:無
結 果:延時相應時間
備 注:振蕩晶體為12MHz(所有延時函數Copy自STC-ISP(v6.85).exe)
**********************************************************************************************/
void Delay30us() //@12.000MHz
{
unsigned char i;
i = 87;
while (--i);
}
void Delay20ms() //@12.000MHz
{
unsigned char i, j, k;
i = 1;
j = 234;
k = 113;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay1s() //@12.000MHz
{
unsigned char i, j, k;
i = 46;
j = 153;
k = 245;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*********************************************************************************************
函數名:UART串口初始化函數
調 用:UART_Init();
參 數:無
返回值:無
結 果:啟動UART串口接收中斷,允許串口接收,啟動T/C1產生波特率(占用)
備 注:振蕩晶體為12MHz,PC串口端設置 [ 4800,8,無,1,無 ]
**********************************************************************************************/
void UART_Init (void){
EA = 1; //允許總中斷(如不使用中斷,可用//屏蔽)
ES = 1; //允許UART串口的中斷
TMOD = 0x20; //定時器T/C1工作方式2
SCON = 0x50; //串口工作方式1,允許串口接收(SCON = 0x40 時禁止串口接收)
TH1 = 0xF3; //定時器初值高8位設置
TL1 = 0xF3; //定時器初值低8位設置
PCON = 0x80; //波特率倍頻(屏蔽本句波特率為2400)
TR1 = 1; //定時器啟動
}
/*********************************************************************************************
函數名:UART串口發送函數
調 用:UART_T (?);
參 數:需要UART串口發送的數據(8位/1字節)
返回值:無
結 果:將參數中的數據發送給UART串口,確認發送完成后退出
備 注:
**********************************************************************************************/
void UART_T (uchar UART_data){ //定義串口發送數據變量
SBUF = UART_data; //將接收的數據發送回去
while(TI == 0); //檢查發送中斷標志位
TI = 0; //令發送中斷標志位為0(軟件清零)
}
/*********************************************************************************************
函數名:DHT11讀數據函數
調 用:? = GetData();
參 數:無
返回值:失敗->-1,-2,-3,-4;成功->0
結 果:讀DHT11數據并保存到數組dat_r[]
備 注:
**********************************************************************************************/
char GetData (void)
{
uchar i,j; //for循環變量
uchar t; //超時判斷
uchar dat8=0; //一次讀取的8位數據,需要讀5次
DATA = 0; //主機發起始信號
Delay20ms(); //主機拉低總線至少18ms
DATA = 1; //主機拉高總線20~40us
Delay30us();
t = 80; //設置超時等待時間
while(DATA && t--); //等待DHT11拉低總線
if(t == 0) //超時
{
DATA = 1;
return -1; //通信錯誤退出,返回錯誤信號:-1
}
//等80us響應信號
t = 250; //設置超時等待時間
while(!DATA && t--); //等待DHT11拉高總線
if(t == 0) //超時
{
DATA = 1;
return -2; //通信錯誤退出,返回錯誤信號:-2
}
//等80us響應信號
t = 250; //設置超時等待時間
while(DATA && t--); //等待DHT11拉低總線
if(t == 0) //超時
{
DATA = 1;
return -3; //通信錯誤退出,返回錯誤信號:-3
}
for(j=0; j<5; j++) //5次讀取
{
for(i=0; i<8; i++) //1次8個位
{
//等待50us開始時隙
t = 150; //設置超時等待時間
while(!DATA && t--); //等待DHT11拉高總線
if(t == 0) //超時
{
DATA = 1;
return -4; //通信錯誤退出,返回錯誤信號:-4
}
t = 0; //記錄時間清零
while(DATA && ++t); //等待并記錄高電平持續時間
dat8 <<= 1;
if(t > JUDGE) //高電平持續時間較長(70us)
dat8 += 1; //傳輸值為1
//else dat8 += 0;
}
dat_r[j] = dat8;
}
Delay30us(); //等待DHT11拉低50us
Delay30us();
DATA = 1; //結束,拉高總線
return 0; //返回成功信號
}
/*********************************************************************************************
函數名:數據校驗函數
調 用:? = Check();
參 數:無
返回值:成功->0;失敗->-1;
結 果:數據校驗
備 注:數據傳送正確時校驗和數據等于“8bit濕度整數數據+8bit濕度小數數據+8bi溫度整數數據+8bit溫度小數數據”所得結果的末8位。
**********************************************************************************************/
char Check (void)
{
uchar i; //for循環變量
uint chk=0; //校驗和
for(i=0; i<4; i++)
chk += dat_r[i]; //累加
if((uchar)chk != dat_r[4]) //比對
return -1; //返回錯誤信號:-1
else
return 0; //返回正確信號:0
}
/*********************************************************************************************
函數名:主函數
調 用:無
參 數:無
返回值:無
結 果:讀DHT11數據并送到串口顯示
備 注:
**********************************************************************************************/
void main (void)
{
char i;
UART_Init(); //串口初始化
Delay1s(); //等待DHT11穩定
do
{
i = GetData(); //讀數據
if(i != 0) //有錯誤
{
UART_T(-i); //返回錯誤值
break; //重新開始
}
i = Check(); //數據校驗
if(i != 0) //有錯誤
{
UART_T(-i); //返回錯誤值
break; //重新開始
}
UART_T(dat_r[0]); //濕度整數
//UART_T(dat_r[1]); //濕度小數(根據數據手冊,DHT11小數部分一直是0沒用)
UART_T(dat_r[2]); //溫度整數
//UART_T(dat_r[3]); //溫度小數(根據數據手冊,DHT11小數部分一直是0沒用)
UART_T(dat_r[4]); //校驗值
Delay1s(); //經測試,兩次連讀要至少延時80ms
}while(1);
}//main
|