找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2464|回復: 0
收起左側(cè)

DHT11溫濕度傳感器程序 普中單片機開發(fā)版

[復制鏈接]
ID:974010 發(fā)表于 2022-4-19 21:14 | 顯示全部樓層 |閱讀模式
簡單修改成開發(fā)板使用的。開發(fā)板使用時記得把74HC595的oe端與vcc短接,不然會引腳沖突導致lcd亂碼

單片機源程序如下:
    #include <reg52.h>                                   // 頭文件包含
    #include <intrins.h>

    #define uchar unsigned char        // 以后unsigned char就可以用uchar代替
    #define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

    sfr ISP_DATA  = 0xe2;                        // 數(shù)據(jù)寄存器
    sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
    sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
    sfr ISP_CMD   = 0xe5;                        // 命令寄存器
    sfr ISP_TRIG  = 0xe6;                        // 命令觸發(fā)寄存器
    sfr ISP_CONTR = 0xe7;                        // 命令寄存器


    sbit DHT11_P   = P1^5;                 // 溫濕度傳感器DHT11數(shù)據(jù)接入
    sbit LcdRs_P   = P2^6;    // 1602液晶的RS管腳      
    sbit LcdRw_P   = P2^5;    // 1602液晶的RW管腳
    sbit LcdEn_P   = P2^7;    // 1602液晶的EN管腳

    uchar temp;                                        // 保存溫度
    uchar humi;                                        // 保存濕度



    /*********************************************************/
    // 單片機內(nèi)部EEPROM不使能
    /*********************************************************/
    void ISP_Disable()
    {
            ISP_CONTR = 0;
            ISP_ADDRH = 0;
            ISP_ADDRL = 0;
    }


    /*********************************************************/
    // 從單片機內(nèi)部EEPROM讀一個字節(jié),從0x2000地址開始
    /*********************************************************/
    unsigned char EEPROM_Read(unsigned int add)
    {
            ISP_DATA  = 0x00;
            ISP_CONTR = 0x83;
            ISP_CMD   = 0x01;
            ISP_ADDRH = (unsigned char)(add>>8);
            ISP_ADDRL = (unsigned char)(add&0xff);
            // 對STC89C51系列來說,每次要寫入0x46,再寫入0xB9,ISP/IAP才會生效
            ISP_TRIG  = 0x46;         
            ISP_TRIG  = 0xB9;
            _nop_();
            ISP_Disable();
            return (ISP_DATA);
    }


    /*********************************************************/
    // 往單片機內(nèi)部EEPROM寫一個字節(jié),從0x2000地址開始
    /*********************************************************/
    void EEPROM_Write(unsigned int add,unsigned char ch)
    {
            ISP_CONTR = 0x83;
            ISP_CMD   = 0x02;
            ISP_ADDRH = (unsigned char)(add>>8);
            ISP_ADDRL = (unsigned char)(add&0xff);
            ISP_DATA  = ch;
            ISP_TRIG  = 0x46;
            ISP_TRIG  = 0xB9;
            _nop_();
            ISP_Disable();
    }


    /*********************************************************/
    // 擦除單片機內(nèi)部EEPROM的一個扇區(qū)
    // 寫8個扇區(qū)中隨便一個的地址,便擦除該扇區(qū),寫入前要先擦除
    /*********************************************************/
    void Sector_Erase(unsigned int add)         
    {
            ISP_CONTR = 0x83;
            ISP_CMD   = 0x03;
            ISP_ADDRH = (unsigned char)(add>>8);
            ISP_ADDRL = (unsigned char)(add&0xff);
            ISP_TRIG  = 0x46;
            ISP_TRIG  = 0xB9;
            _nop_();
            ISP_Disable();
    }


    /*********************************************************/
    // 毫秒級的延時函數(shù),time是要延時的毫秒數(shù)
    /*********************************************************/
    void DelayMs(uint time)
    {
            uint i,j;
            for(i=0;i<time;i++)
                    for(j=0;j<112;j++);
    }


    /*********************************************************/
    // 1602液晶寫命令函數(shù),cmd就是要寫入的命令
    /*********************************************************/
    void LcdWriteCmd(uchar cmd)
    {
            LcdRs_P = 0;
            LcdRw_P = 0;
            LcdEn_P = 0;
            P0=cmd;
            DelayMs(2);
            LcdEn_P = 1;   
            DelayMs(2);
            LcdEn_P = 0;      
    }


    /*********************************************************/
    // 1602液晶寫數(shù)據(jù)函數(shù),dat就是要寫入的數(shù)據(jù)
    /*********************************************************/
    void LcdWriteData(uchar dat)
    {
            LcdRs_P = 1;
            LcdRw_P = 0;
            LcdEn_P = 0;
            P0=dat;
            DelayMs(2);
            LcdEn_P = 1;   
            DelayMs(2);
            LcdEn_P = 0;
    }


    /*********************************************************/
    // 1602液晶初始化函數(shù)
    /*********************************************************/
    void LcdInit()
    {
            LcdWriteCmd(0x38);        // 16*2顯示,5*7點陣,8位數(shù)據(jù)口
            LcdWriteCmd(0x0C);        // 開顯示,不顯示光標
            LcdWriteCmd(0x06);        // 地址加1,當寫入數(shù)據(jù)后光標右移
            LcdWriteCmd(0x01);        // 清屏
    }


    /*********************************************************/
    // 液晶光標定位函數(shù)
    /*********************************************************/
    void LcdGotoXY(uchar line,uchar column)
    {
            // 第一行
            if(line==0)        
                    LcdWriteCmd(0x80+column);
            // 第二行
            if(line==1)        
                    LcdWriteCmd(0x80+0x40+column);
    }


    /*********************************************************/
    // 液晶輸出字符串函數(shù)
    /*********************************************************/
    void LcdPrintStr(uchar *str)
    {
            while(*str!='\0')                         // 判斷是否到字符串的盡頭了
                    LcdWriteData(*str++);
    }


    /*********************************************************/
    // 液晶輸出數(shù)字
    /*********************************************************/
    void LcdPrintNum(uchar num)
    {
            LcdWriteData(num/10+48);        // 十位
            LcdWriteData(num%10+48);         // 個位
    }


    /*********************************************************/
    // 液晶顯示內(nèi)容的初始化
    /*********************************************************/
    void LcdShowInit()
    {
            LcdGotoXY(0,0);                                                                // 第0行的顯示內(nèi)容
            LcdPrintStr("  DHT11 System  ");
            LcdGotoXY(1,0);                                                           // 第1行的顯示內(nèi)容
            LcdPrintStr("T:   C   H:   %");
            LcdGotoXY(1,4);                                                                // 溫度單位攝氏度上面的圓圈符號
            LcdWriteData(0xdf);      
    }



    /*********************************************************/
    // 10us級延時程序
    /*********************************************************/
    void Delay10us()
    {
            _nop_();        // 執(zhí)行一條指令,延時1微秒
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
    }


    /*********************************************************/
    // 讀取DHT11單總線上的一個字節(jié)
    /*********************************************************/
    uchar DhtReadByte(void)
    {   
            bit bit_i;
            uchar j;
            uchar dat=0;

            for(j=0;j<8;j++)   
            {
                    while(!DHT11_P);        // 等待低電平結(jié)束      
                    Delay10us();                        // 延時
                    Delay10us();
                    Delay10us();
                    if(DHT11_P==1)                // 判斷數(shù)據(jù)線是高電平還是低電平
                    {
                            bit_i=1;
                            while(DHT11_P);
                    }
                    else
                    {
                            bit_i=0;
                    }
                    dat<<=1;                                   // 將該位移位保存到dat變量中
                    dat|=bit_i;   
            }
            return(dat);  
    }


    /*********************************************************/
    // 讀取DHT11的一幀數(shù)據(jù),濕高、濕低(0)、溫高、溫低(0)、校驗碼
    /*********************************************************/
    void ReadDhtData()
    {            
            uchar HumiHig;                // 濕度高檢測值
            uchar HumiLow;                // 濕度低檢測值
            uchar TemHig;                        // 溫度高檢測值
            uchar TemLow;                        // 溫度低檢測值
            uchar check;                        // 校驗字節(jié)
         
            DHT11_P=0;                                // 主機拉低
            DelayMs(20);                        // 保持20毫秒
            DHT11_P=1;                                // DATA總線由上拉電阻拉高

            Delay10us();                         // 延時等待30us
            Delay10us();
            Delay10us();

            while(!DHT11_P);        // 等待DHT的低電平結(jié)束
            while(DHT11_P);                // 等待DHT的高電平結(jié)束

            //進入數(shù)據(jù)接收狀態(tài)
            HumiHig = DhtReadByte();         // 濕度高8位
            HumiLow = DhtReadByte();         // 濕度低8為,總為0
            TemHig  = DhtReadByte();         // 溫度高8位
            TemLow  = DhtReadByte();         // 溫度低8為,總為0
            check   = DhtReadByte();        // 8位校驗碼,其值等于讀出的四個字節(jié)相加之和的低8位

            DHT11_P=1;                                // 拉高總線

            if(check==HumiHig + HumiLow + TemHig + TemLow)                 // 如果收到的數(shù)據(jù)無誤
            {
                    temp=TemHig;                         // 將溫度的檢測結(jié)果賦值給全局變量temp
                    humi=HumiHig;                        // 將濕度的檢測結(jié)果賦值給全局變量humi
            }
    }


    /*********************************************************/

    // 主函數(shù)
    /*********************************************************/
    void main()
    {
            uchar i;

            LcdInit();                                                        // 液晶功能的初始化                       
            LcdShowInit();                                         // 液晶顯示的初始化

         
         
            while(1)
            {
                    ReadDhtData();                                 // 檢測溫濕度數(shù)據(jù)

                    LcdGotoXY(1,2);                                 // 定位到要顯示溫度的地方
                    LcdPrintNum(temp);                // 顯示溫度值
                    LcdGotoXY(1,11);                        // 定位到要顯示濕度的地方
                    LcdPrintNum(humi);                // 顯示濕度值
                  
                  

                    for(i=0;i<25;i++)
                    {
                           
                            DelayMs(20);                                // 延時      
                    }
            }



評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表