標(biāo)題: 51單片機(jī)+DHT11讀數(shù)據(jù)時而正確時而錯誤 [打印本頁]

作者: MirrAKe    時間: 2021-2-27 21:17
標(biāo)題: 51單片機(jī)+DHT11讀數(shù)據(jù)時而正確時而錯誤
兩段程序用的DHT11驅(qū)動是同一個文件,
下面這段程序可以正常運(yùn)行,可以正常顯示數(shù)據(jù),數(shù)據(jù)也是正常的:

    #include<reg51.h>
        #include<intrins.h>
    #define uchar unsigned char        //無符號字符型類型數(shù)據(jù)
    #define uint unsigned int //無符號整型數(shù)據(jù)

        extern void InitLCD1602();
        extern void LcdShowStr(uchar x, uchar y, uchar *str);
        extern void DHT11GetData(uchar *dat);
        extern void Delay20ms();
        void Delay1000ms();
        void RefreashDHT11DataShow();
        sbit lcd1602bg = P2^2;
        uchar dht11data[5] = {48,49,50,51,'\0'};
        
        void main()
        {
            
            lcd1602bg = 0;
            Delay1000ms();
            
            InitLCD1602();
            while(1)
            {
                Delay1000ms();
                DHT11GetData(dht11data);
                LcdShowStr(0,0,dht11data);
                RefreashDHT11DataShow();
            }
        }

        
        
void RefreashDHT11DataShow()
{
    static uchar RH[3],Temp[3];
   
    RH[0] = dht11data[0];
    RH[1] = dht11data[1];
    RH[2] = '\0';
    Temp[0] = dht11data[2];
    Temp[1] = dht11data[3];
    Temp[2] = '\0';
   
    LcdShowStr(13,0,RH);
    LcdShowStr(12,1,Temp);
}

void Delay1000ms()        //@11.0592MHz
{
    unsigned char i, j, k;

    _nop_();
    i = 8;
    j = 1;
    k = 243;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}






下面這段程序就會出現(xiàn)數(shù)據(jù)時而正確,時而錯誤(省去了關(guān)于時間和按鍵的代碼,時間和按鍵的代碼也是完全正常的運(yùn)行,之前測試過了):
#include <reg52.h>

typedef unsigned char uchar;
typedef unsigned int uint;


bit timeflag200ms = 1;
bit dht11flag1s = 0;
struct stime buftime;                                        //日期時間緩沖區(qū)
uchar dht11data[4];                                          //濕度十位,濕度個位,溫度十位,溫度個位
uchar T0RH = 0;                                              //T0重載值的高字節(jié)
uchar T0RL = 0;                                              //T0重載值的低字節(jié)
uint setindex = 0;                                           //時間設(shè)置索引

sbit lcd1602gb = P2^2;
extern void KeyScan();                                       //掃描按鍵
extern void KeyDriver();                                     //按鍵驅(qū)動
   
extern void InitDS1302();                                    //初始化DS1302
extern void GetRealTime(struct stime *time);                 //獲得時間
extern void SetRealTime(struct stime *time);                 //設(shè)置時間

extern void InitLcd1602();                                   //初始化LCD1602
extern void LcdShowStr(uchar x, uchar y, uchar *str);        //顯示字符串 在液晶上顯示字符串,(x,y)-對應(yīng)屏幕上的起始坐標(biāo),str-字符串指針
extern void LcdSetCursor(uchar x, uchar y);                  //設(shè)置坐標(biāo)
extern void LcdOpenCursor();                                 //打開閃爍光標(biāo)
extern void LcdCloseCursor();                                //關(guān)閉光標(biāo)
extern void LcdWriteDat(uchar dat);                         //寫字符
extern void LcdSetCursor(uchar x, uchar y);                  //設(shè)置光標(biāo)位置

extern void DHT11GetData(uchar *dat);                        //獲取DHT11數(shù)據(jù)

void ConfigTimer0(uint ms);                                  //配置計時器T0
void RefreshTimeShow();                                      //刷新時間顯示
void RefreashDHT11DataShow();                                //刷新DHT11數(shù)據(jù)顯示

void main()
{
    uchar psec = 0xAA;                //秒備份,初值A(chǔ)A確保首次讀取時間后會刷新顯示
  uchar du = 0xdf;                  //°ascii碼         
    EA = 1;                           //開總中斷
    ConfigTimer0(1);                  //T0定時1ms
    InitDS1302();                     //初始化實(shí)時時鐘
    InitLcd1602();                    //初始化液晶
   
    //初始化屏幕上固定不變的內(nèi)容
  LcdShowStr(0, 0, "20  -  -       %");
  LcdShowStr(0, 1, "  :  :         C");
    LcdSetCursor(14,1);
    LcdWriteDat(du);                  //顯示°符號
    lcd1602gb = 0;                    //默認(rèn)打開背光
   
    while(1)
    {
        KeyDriver();
        if(timeflag200ms && (setindex == 0))
        {
            timeflag200ms = 0;
            GetRealTime(&buftime);        //獲取當(dāng)前時間
            if (psec != buftime.sec)      //檢測到時間有變化時刷新顯示
            {
                RefreshTimeShow();
                psec = buftime.sec; //用當(dāng)前值更新上次秒數(shù)
            }
        }
                  if(dht11flag1s && (setindex == 0))
                {
                    dht11flag1s = 0;
                    DHT11GetData(dht11data);
                    RefreashDHT11DataShow();
                }
    }
}

void ConfigTimer0(uint ms)
{
    unsigned long tmp;                //臨時變量
   
    tmp = 11059200 / 12;                //定時器計數(shù)頻率
    tmp = (tmp * ms) / 1000;          //計算所需的計數(shù)值
    tmp = 65536 - tmp;                //計算定時器重載值
    tmp = tmp + 28;                   //補(bǔ)償中斷響應(yīng)延時造成的誤差
    T0RH = (uchar)(tmp>>8);           //定時器重載值拆分為高低字節(jié)
    T0RL = (uchar)tmp;
    TMOD &= 0xF0;                     //清零T0的控制位
    TMOD |= 0x01;                     //配置T0為模式1
    TH0 = T0RH;                       //加載T0重載值
    TL0 = T0RL;                       
    ET0 = 1;                          //使能T0中斷
    TR0 = 1;                          //啟動T0
}

void RefreashDHT11DataShow()
{
    static uchar RH[3],Temp[3];
   
    RH[0] = dht11data[0];
    RH[1] = dht11data[1];
    RH[2] = '\0';
    Temp[0] = dht11data[2];
    Temp[1] = dht11data[3];
    Temp[2] = '\0';
   
    LcdShowStr(13,0,RH);
    LcdShowStr(12,1,Temp);
}

void InterruptTimer0() interrupt 1
{
    static uint tmr200ms = 0;
    static uint tmr1s = 0;
   
    TH0 = T0RH;  //重新加載重載值
  TL0 = T0RL;
    KeyScan();
   
    tmr200ms++;
    tmr1s++;
   
    if (tmr200ms >= 200)  //定時200ms
    {
        tmr200ms = 0;
        timeflag200ms = 1;
    }
        if(tmr1s >= 1000)
        {
            tmr1s = 0;
            dht11flag1s = 1;
        }
}









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