標(biāo)題: DHT11驅(qū)動(dòng)程序 [打印本頁(yè)]

作者: 891896039    時(shí)間: 2017-11-26 22:36
標(biāo)題: DHT11驅(qū)動(dòng)程序
/*********************************************************************************************
程序名:    DHT11驅(qū)動(dòng)程序
編寫人:    王朗的誘惑
編寫時(shí)間:  2015年8月4日
硬件支持:  STC12C5A60S2  DHT11
接口說(shuō)明:  DHT11:VCC GND DATA
*********************************************************************************************
說(shuō)明:1、單片機(jī)是STC12C5A60S2,晶振頻率12MHz,實(shí)驗(yàn)成功。換用12T單片機(jī)或別的晶振的時(shí)候要修改
          延時(shí)函數(shù)和JUDGE。程序里判斷超時(shí)的變量t的閥值也要改。
          2、好東西要共享,大家隨意折騰~~
*********************************************************************************************/
#include <STC12C5A60S2.H>

typedef unsigned char        uchar;
typedef unsigned int        uint;

#define JUDGE        30                //用于判斷通信的0和1,與單片機(jī)速度和晶振頻率有關(guān)

sbit DATA = P1^0;                //定義數(shù)據(jù)引腳

uchar dat_r[5];                        //用于存放從DHT11讀取到的數(shù)值

/*********************************************************************************************
函數(shù)名:延時(shí)函數(shù)
調(diào)  用:Delay30us();/Delay20ms();/Delay1s();
參  數(shù):無(wú)
返回值:無(wú)
結(jié)  果:延時(shí)相應(yīng)時(shí)間
備  注:振蕩晶體為12MHz(所有延時(shí)函數(shù)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);
}

/*********************************************************************************************
函數(shù)名:UART串口初始化函數(shù)
調(diào)  用:UART_Init();
參  數(shù):無(wú)
返回值:無(wú)
結(jié)  果:?jiǎn)?dòng)UART串口接收中斷,允許串口接收,啟動(dòng)T/C1產(chǎn)生波特率(占用)
備  注:振蕩晶體為12MHz,PC串口端設(shè)置 [ 4800,8,無(wú),1,無(wú) ]
**********************************************************************************************/
void UART_Init (void){
        EA = 1; //允許總中斷(如不使用中斷,可用//屏蔽)
        ES = 1; //允許UART串口的中斷

        TMOD = 0x20;        //定時(shí)器T/C1工作方式2
        SCON = 0x50;        //串口工作方式1,允許串口接收(SCON = 0x40 時(shí)禁止串口接收)
        TH1 = 0xF3;        //定時(shí)器初值高8位設(shè)置
        TL1 = 0xF3;        //定時(shí)器初值低8位設(shè)置
        PCON = 0x80;        //波特率倍頻(屏蔽本句波特率為2400)
        TR1 = 1;        //定時(shí)器啟動(dòng)   
}

/*********************************************************************************************
函數(shù)名:UART串口發(fā)送函數(shù)
調(diào)  用:UART_T (?);
參  數(shù):需要UART串口發(fā)送的數(shù)據(jù)(8位/1字節(jié))
返回值:無(wú)
結(jié)  果:將參數(shù)中的數(shù)據(jù)發(fā)送給UART串口,確認(rèn)發(fā)送完成后退出
備  注:
**********************************************************************************************/
void UART_T (uchar UART_data){ //定義串口發(fā)送數(shù)據(jù)變量
        SBUF = UART_data;        //將接收的數(shù)據(jù)發(fā)送回去
        while(TI == 0);                //檢查發(fā)送中斷標(biāo)志位
        TI = 0;                        //令發(fā)送中斷標(biāo)志位為0(軟件清零)
}

/*********************************************************************************************
函數(shù)名:DHT11讀數(shù)據(jù)函數(shù)
調(diào)  用:? = GetData();
參  數(shù):無(wú)
返回值:失敗->-1,-2,-3,-4;成功->0
結(jié)  果:讀DHT11數(shù)據(jù)并保存到數(shù)組dat_r[]
備  注:
**********************************************************************************************/
char GetData (void)
{
        uchar i,j;                                //for循環(huán)變量
        uchar t;                                //超時(shí)判斷
        uchar dat8=0;                        //一次讀取的8位數(shù)據(jù),需要讀5次

        DATA = 0;                                //主機(jī)發(fā)起始信號(hào)
        Delay20ms();                        //主機(jī)拉低總線至少18ms
        DATA = 1;                                //主機(jī)拉高總線20~40us
        Delay30us();

        t = 80;                                        //設(shè)置超時(shí)等待時(shí)間
        while(DATA && t--);                //等待DHT11拉低總線
        if(t == 0)                                //超時(shí)
        {
                DATA = 1;
                return -1;                        //通信錯(cuò)誤退出,返回錯(cuò)誤信號(hào):-1
        }

        //等80us響應(yīng)信號(hào)
        t = 250;                                //設(shè)置超時(shí)等待時(shí)間
        while(!DATA && t--);        //等待DHT11拉高總線
        if(t == 0)                                //超時(shí)
        {
                DATA = 1;
                return -2;                        //通信錯(cuò)誤退出,返回錯(cuò)誤信號(hào):-2
        }

        //等80us響應(yīng)信號(hào)
        t = 250;                                //設(shè)置超時(shí)等待時(shí)間
        while(DATA && t--);                //等待DHT11拉低總線
        if(t == 0)                                //超時(shí)
        {
                DATA = 1;
                return -3;                        //通信錯(cuò)誤退出,返回錯(cuò)誤信號(hào):-3
        }

        for(j=0; j<5; j++)                //5次讀取
        {
                for(i=0; i<8; i++)                        //1次8個(gè)位
                {
                        //等待50us開(kāi)始時(shí)隙
                        t = 150;                                //設(shè)置超時(shí)等待時(shí)間
                        while(!DATA && t--);        //等待DHT11拉高總線
                        if(t == 0)                                //超時(shí)
                        {
                                DATA = 1;
                                return -4;                        //通信錯(cuò)誤退出,返回錯(cuò)誤信號(hào):-4
                        }
                        t = 0;                                        //記錄時(shí)間清零
                        while(DATA && ++t);                //等待并記錄高電平持續(xù)時(shí)間
                        dat8 <<= 1;
                        if(t > JUDGE)                        //高電平持續(xù)時(shí)間較長(zhǎng)(70us)
                                dat8 += 1;                        //傳輸值為1
                        //else dat8 += 0;
                }
                dat_r[j] = dat8;
        }

        Delay30us();                //等待DHT11拉低50us
        Delay30us();
        DATA = 1;                        //結(jié)束,拉高總線
        return 0;                        //返回成功信號(hào)
}

/*********************************************************************************************
函數(shù)名:數(shù)據(jù)校驗(yàn)函數(shù)
調(diào)  用:? = Check();
參  數(shù):無(wú)
返回值:成功->0;失敗->-1;
結(jié)  果:數(shù)據(jù)校驗(yàn)
備  注:數(shù)據(jù)傳送正確時(shí)校驗(yàn)和數(shù)據(jù)等于“8bit濕度整數(shù)數(shù)據(jù)+8bit濕度小數(shù)數(shù)據(jù)+8bi溫度整數(shù)數(shù)據(jù)+8bit溫度小數(shù)數(shù)據(jù)”所得結(jié)果的末8位。
**********************************************************************************************/
char Check (void)
{
        uchar i;                        //for循環(huán)變量
        uint chk=0;                        //校驗(yàn)和
        for(i=0; i<4; i++)
                chk += dat_r[i];                //累加
        if((uchar)chk != dat_r[4])        //比對(duì)
                return -1;                                //返回錯(cuò)誤信號(hào):-1
        else
                return 0;                                //返回正確信號(hào):0
}

/*********************************************************************************************
函數(shù)名:主函數(shù)
調(diào)  用:無(wú)
參  數(shù):無(wú)
返回值:無(wú)
結(jié)  果:讀DHT11數(shù)據(jù)并送到串口顯示
備  注:
**********************************************************************************************/
void main (void)
{
        char i;
        UART_Init();                //串口初始化
        Delay1s();                        //等待DHT11穩(wěn)定
        do
        {
                i = GetData();        //讀數(shù)據(jù)
                if(i != 0)                //有錯(cuò)誤
                {
                        UART_T(-i);        //返回錯(cuò)誤值
                        break;                //重新開(kāi)始
                }

                i = Check();        //數(shù)據(jù)校驗(yàn)
                if(i != 0)                //有錯(cuò)誤
                {
                        UART_T(-i);        //返回錯(cuò)誤值
                        break;                //重新開(kāi)始
                }

                UART_T(dat_r[0]);                //濕度整數(shù)
                //UART_T(dat_r[1]);                //濕度小數(shù)(根據(jù)數(shù)據(jù)手冊(cè),DHT11小數(shù)部分一直是0沒(méi)用)
                UART_T(dat_r[2]);                //溫度整數(shù)
                //UART_T(dat_r[3]);                //溫度小數(shù)(根據(jù)數(shù)據(jù)手冊(cè),DHT11小數(shù)部分一直是0沒(méi)用)
                UART_T(dat_r[4]);                //校驗(yàn)值

                Delay1s();                                //經(jīng)測(cè)試,兩次連讀要至少延時(shí)80ms        
        }while(1);
}//main






歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1