找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 4825|回復(fù): 7
打印 上一主題 下一主題
收起左側(cè)

DHT11的STM32歷程移植到51單片機(jī),數(shù)據(jù)和校驗(yàn)都出了問題!能否看下怎么解決,謝謝!

[復(fù)制鏈接]
回帖獎(jiǎng)勵(lì) 2 黑幣 回復(fù)本帖可獲得 2 黑幣獎(jiǎng)勵(lì)! 每人限 1 次
跳轉(zhuǎn)到指定樓層
樓主
ID:116263 發(fā)表于 2018-5-10 03:59 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
將正點(diǎn)原子的歷程移植到51中,時(shí)序圖對(duì)照了感覺沒錯(cuò),DHT11能響應(yīng),但是讀數(shù)據(jù)時(shí)卻不對(duì),只能讀數(shù)據(jù)“1”,讀不到數(shù)據(jù)“0”,校驗(yàn)也不對(duì),在stm32中卻可以顯示,對(duì)照了下DHT11整個(gè)時(shí)序圖,覺得沒問題,想問下怎么解決,謝謝!

line level    source
   1          #include "REG51.h"
   2          #include <intrins.h>
   3          #include "DHT11.h"
   4          #include "oled.h"
   5          uchar i,humidity,temperature;

   6          void DHT11_delay_ms(uchar c)   //誤差 0us
   7          {
   8   1          unsigned char a,b;
   9   1          for(;c>0;c--)
  10   1              for(b=142;b>0;b--)
  11   1                  for(a=2;a>0;a--);
  12   1      }
  13         
  14            void DHT11_delay_us(uchar n)
  15          {
  16   1          while(--n);
  17   1      }
  18         
  19          void DHT11_Rst(void)// 主機(jī)發(fā)出起始信號(hào)
  20          {
  21   1         Data=1;
  22   1          DHT11_delay_us(2);
  23   1          Data=0;       //拉低DQ
  24   1          DHT11_delay_ms(20);     //拉低至少18ms
  25   1          Data=1;       //DQ=1
  26   1          DHT11_delay_us(30);       //主機(jī)拉高20~40us
  27   1      }
  28         
  29          /*  返回0: retry為0,則存在
  30              返回1:未檢測(cè)到DHT11的存在
  31          */
  32         
  33          uchar DHT11_Check(void)//等待DHT11響應(yīng)
  34          {
  35   1         uchar retry=0;
  36   1         while (Data&&(retry<100))//DHT11會(huì)拉低40~80us
  37   1        {
  38   2          retry++;  
  39   2          DHT11_delay_us(1);
  40   2        }  
  41   1        if(retry>=100)
  42   1          return 1;
  43   1          else retry=0;
  44   1         while ((!Data)&&(retry<100))//DHT11拉低后會(huì)再次拉高40~80us
  45   1        {
  46   2            retry++;
  47   2            DHT11_delay_us(1);
  48   2        }
  49   1        if(retry>=100)
  50   1           return 1;   
  51   1          else   return 0;
  52   1      }
  53         
  54          uchar DHT11_Read_Bit(void)//讀取一位  
  55          {
  56   1            uchar retry=0;
  57   1            while(Data&&(retry<60))//等待變?yōu)榈碗娖?br />   58   1            {
  59   2                   retry++;   
  60   2                   DHT11_delay_us(1);
  61   2             }
  62   1             retry=0;
  63   1            while((!Data)&&(retry<100))//等待變高電平
  64   1             {
  65   2                    retry++;  
  66   2                    DHT11_delay_us(1);
  67   2             }  
  68   1               DHT11_delay_us(50);//等待40us
  69   1               if(Data)
  70   1                 return 1;
  71   1               else            
  72   1                  return 0;
  73   1      
  74   1        
  75   1      
  76   1      }
  77         
  78         
  79          uchar DHT11_Read_Byte(void)//讀取一個(gè)字節(jié)  用前面讀取的每8位,組成一個(gè)字節(jié)
  80          {
  81   1            uchar i,dat;
  82   1          dat=0;
  83   1         for (i=0;i<8;i++)
  84   1          {
  85   2            dat<<=1;
  86   2           dat|=DHT11_Read_Bit();
  87   2          }           
  88   1          return dat;
  89   1      
  90   1      }
  91         
  92          uchar DHT11_Read_Data(void)  //解析所讀取的溫度和濕度
  93          {
  94   1         uchar buff[5];
  95   1          DHT11_Rst();//主機(jī)發(fā)出起始信號(hào)
  96   1         if(DHT11_Check()==0)//等待DHT11響應(yīng),如果返回0,則主機(jī)檢測(cè)到DHT11的響應(yīng)信號(hào)
  97   1         {
  98   2                for(i=0;i<5;i++)//讀取40位數(shù)據(jù)
  99   2          {      
100   3                buff[ i]=DHT11_Read_Byte();//讀取數(shù)據(jù)(8位)
101   3          }
102   2         
103   2          if((buff[0]+buff[1]+buff[2]+buff[3])==buff[4])//檢驗(yàn)
104   2         {
105   3              humidity=buff[0];//8bit濕度整數(shù)數(shù)據(jù)
106   3              temperature =buff[2];//8bit溫度整數(shù)數(shù)據(jù)
107   3         }
108   2       }
109   1         else return 1;
110   1         return 0;      
111   1      }


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:164602 發(fā)表于 2018-5-10 07:24 | 只看該作者
為什么要從STM32移植,直接用51的不好嗎?
給你一個(gè):
/****************************************************************
//           DHT21使用范例
//單片機(jī) AT89S52 或 STC89C52RC
//功能   串口發(fā)送溫濕度數(shù)據(jù) 晶振 11.0592M 波特率 4800
//硬件   P2.0口為通訊口連接DHT11,DHT11的電源和地連接單片機(jī)的電源和地,單片機(jī)串口加MAX232連接電腦
//公司  雁凌電子   
****************************************************************/

#include <reg51.h>
#include <intrins.h>

sbit  P2_0  = P2^0 ;//溫濕度傳感器的數(shù)據(jù)接口

sbit SMG_q = P1^0;        //定義數(shù)碼管陽級(jí)控制腳(千位)
sbit SMG_b = P1^1;        //定義數(shù)碼管陽級(jí)控制腳(百位)
sbit SMG_s = P1^2;        //定義數(shù)碼管陽級(jí)控制腳(十位)
sbit SMG_g = P1^3;        //定義數(shù)碼管陽級(jí)控制腳(個(gè)位)

unsigned char ly_disdate[4]={0,0,0,0};
//----------------------------------------------//
//----------------定義區(qū)--------------------//
//----------------------------------------------//
unsigned char  U8FLAG;
unsigned char  U8temp;
unsigned char  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
unsigned char  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
unsigned char  U8comdata;
unsigned char  outdata[5];  //定義發(fā)送的字節(jié)數(shù)          
unsigned char  indata[5];
unsigned char  count, count_r=0;
unsigned char str[5]={"RS232"};

code unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
                                                        0x88,0x83,0xc6,0xa1,0x86,0x8e};        //共陽數(shù)碼管段值表 0-9 a-f

void delay(void)//延時(shí)35.5us
{               
        unsigned char i=10;
        while(i--);
}


void Delay(unsigned int j)//延時(shí)888.1725us
{
        unsigned char i;
        for(;j>0;j--)
        {        
                for(i=0;i<27;i++);
        }
}

void  Delay_10us(void)
{
        unsigned char i;
        i--;
        i--;
        i--;
        i--;
        i--;
        i--;
}
       
void COM (void)//讀數(shù)據(jù)
{
        unsigned char i;
        for(i=0;i<8;i++)          
        {
                U8FLAG=2;       
                while((!P2_0)&&U8FLAG++);
                Delay_10us();
                Delay_10us();                               
                Delay_10us();
                U8temp=0;
                if(P2_0)U8temp=1;
                U8FLAG=2;
                while((P2_0)&&U8FLAG++);
                   //超時(shí)則跳出for循環(huán)                  
                if(U8FLAG==1)break;
                   //判斷數(shù)據(jù)位是0還是1         
                // 如果高電平高過預(yù)定0高電平值則數(shù)據(jù)位為 1
                U8comdata<<=1;
                U8comdata|=U8temp;        //0
        }//rof
}

        //--------------------------------
        //-----濕度讀取子程序 ------------
        //--------------------------------
        //----以下變量均為全局變量--------
        //----溫度高8位== U8T_data_H------
        //----溫度低8位== U8T_data_L------
        //----濕度高8位== U8RH_data_H-----
        //----濕度低8位== U8RH_data_L-----
        //----校驗(yàn) 8位 == U8checkdata-----
        //----調(diào)用相關(guān)子程序如下----------
        //---- Delay();, Delay_10us();,COM();
        //--------------------------------
void RH (void)
{       
        //主機(jī)拉低18ms
        P2_0=0;
        Delay(180);
        P2_0=1;
        //總線由上拉電阻拉高 主機(jī)延時(shí)20us
        Delay_10us();
        Delay_10us();
        Delay_10us();
        Delay_10us();            
        //主機(jī)設(shè)為輸入 判斷從機(jī)響應(yīng)信號(hào)
        P2_0=1;
        //判斷從機(jī)是否有低電平響應(yīng)信號(hào) 如不響應(yīng)則跳出,響應(yīng)則向下運(yùn)行          
        if(!P2_0)                 //T !          
        {
                U8FLAG=2;
                //判斷從機(jī)是否發(fā)出 80us 的低電平響應(yīng)信號(hào)是否結(jié)束         
                while((!P2_0)&&U8FLAG++);
                U8FLAG=2;
                //判斷從機(jī)是否發(fā)出 80us 的高電平,如發(fā)出則進(jìn)入數(shù)據(jù)接收狀態(tài)
                while((P2_0)&&U8FLAG++);
                //數(shù)據(jù)接收狀態(tài)                 
                COM();
                U8RH_data_H_temp=U8comdata;
                COM();
                U8RH_data_L_temp=U8comdata;
                COM();
                U8T_data_H_temp=U8comdata;
                COM();
                U8T_data_L_temp=U8comdata;
                COM();
                U8checkdata_temp=U8comdata;
                P2_0=1;
                //數(shù)據(jù)校驗(yàn)
                U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
                if(U8temp==U8checkdata_temp)
                {
                        U8RH_data_H=U8RH_data_H_temp;
                        U8RH_data_L=U8RH_data_L_temp;
                        U8T_data_H=U8T_data_H_temp;
                        U8T_data_L=U8T_data_L_temp;
                        U8checkdata=U8checkdata_temp;
                }//fi
        }//fi
}
       

void display()//采用的掃描法使數(shù)碼管動(dòng)態(tài)顯示,即,讓一位數(shù)碼管顯示、關(guān)閉,再讓下一位顯示、
                          //關(guān)閉,時(shí)間很短,人眼通過“視覺暫留”就可以看到全部數(shù)碼管都在亮了
{
        SMG_q=0;                        //選擇千位數(shù)碼管(亮)
        P0=table[ly_disdate[0]];        //
        delay();                        //
        P0=0XFF;                        //
        SMG_q=1;                        //(滅)

        SMG_b=0;                        //選擇百位數(shù)碼管
        P0=table[ly_disdate[1]]-0x80;        //加上小數(shù)點(diǎn)
        delay();                        //延時(shí)
        P0=0XFF;                        //
        SMG_b=1;                        //

        SMG_s=0;                        //選擇十位數(shù)碼管
        P0=table[ly_disdate[2]];        //
        delay();                        //
        P0=0XFF;                        //
        SMG_s=1;                        //

        SMG_g=0;                        //選擇個(gè)位數(shù)碼管
        P0=table[ly_disdate[3]];        //
        delay();                        //
        P0=0XFF;                        //
        SMG_g=1;                        //
}

//----------------------------------------------
//main()功能描述:  AT89C51  11.0592MHz         串口發(fā)
//送溫濕度數(shù)據(jù),波特率 9600
//----------------------------------------------
void main()
{       
        unsigned int n=0,i=20000;

        /* 系統(tǒng)初始化 */
        TMOD = 0x20;          //定時(shí)器T1使用工作方式2
        TH1 = 243;        // 設(shè)置初值
        TL1 = 243;
        TR1 = 1;          // 開始計(jì)時(shí)
        SCON = 0x50;          //工作方式1,波特率4800bps,允許接收   
        PCON=0x80;
        ES = 1;
        EA = 1;           // 打開所以中斷   
        TI = 0;
        RI = 0;
//        SendData(str) ;   //發(fā)送到串口
        Delay(10);         //延時(shí)100US(12M晶振)
        while(1)
        {  
                //------------------------
                //調(diào)用溫濕度讀取子程序
                RH();
                //串口顯示程序
                //--------------------------
                str[0]=U8RH_data_H;
                str[1]=U8RH_data_L;
                str[2]=U8T_data_H;
                str[3]=U8T_data_L;
                str[4]=U8checkdata;
                        Delay(200);
                        SBUF=str[0];//濕度值,十六進(jìn)制數(shù)
                        Delay(200);       
                        SBUF=str[2];//溫度值,十六進(jìn)制數(shù)
                        Delay(200);
                       
                //讀取模塊數(shù)據(jù)周期不宜小于 2S
                i=10000;
                while (i)//3.69s掃描一次
                {
                        if (n<5000)//1.845s換一次顯示,先顯示濕度,后顯示溫度
                        {
                                ly_disdate[0]=str[0]/16;//前兩位是十六進(jìn)制數(shù)
                                ly_disdate[1]=str[0]%16;
                                ly_disdate[2]=str[0]/10;//后兩位是十進(jìn)制數(shù)
                                ly_disdate[3]=str[0]%10;
                        }
                        else
                        {
                                ly_disdate[0]=str[2]/16;
                                ly_disdate[1]=str[2]%16;
                                ly_disdate[2]=str[2]/10;
                                ly_disdate[3]=str[2]%10;
                        }
                        n++;
                        i--;
                        if (n==10000)
                        {
                                n=0;
                        }
                        display();
                }
//                        Delay(20000);
        }//elihw
}// main

void RSINTR() interrupt 4 using 2
{
        unsigned char InPut3;
        if(TI==1) //發(fā)送中斷          
        {
                TI=0;
                if(count!=5) //發(fā)送完5位數(shù)據(jù)         
                {
                        SBUF= outdata[count];
                        count++;
                }
        }
        if(RI==1)         //接收中斷                  
        {       
                InPut3=SBUF;
                indata[count_r]=InPut3;
                count_r++;
                RI=0;                                                                 
                if (count_r==5)//接收完4位數(shù)據(jù)
                {
                        //數(shù)據(jù)接收完畢處理。
                        count_r=0;
                        str[0]=indata[0];
                        str[1]=indata[1];
                        str[2]=indata[2];
                        str[3]=indata[3];
                        str[4]=indata[4];
                        P0=0;
                }
        }
}

評(píng)分

參與人數(shù) 1黑幣 +60 收起 理由
admin + 60 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

板凳
ID:326504 發(fā)表于 2018-5-10 08:46 | 只看該作者
#include "dht11.h"   void delay(uchar ms) //延時(shí)模塊//   {     uchar i;     while(ms--)                              for(i=0;i<100;i++);   }    void delay1()//一個(gè)for循環(huán)大概需要8個(gè)多機(jī)器周期一個(gè)機(jī)器周期為1us晶振為12MHz也就是說本函數(shù)延時(shí)8us多此延時(shí)函數(shù)必須德稍微精確一點(diǎn)   {     uchar i;     for(i=0;i<1;i++);   }  void Delay5ms()                //@12.000MHz {         unsigned char i, j;          i = 10;         j = 183;         do         {                 while (--j);         } while (--i); } void Delay20ms()                //@11.0592MHz {         unsigned char i, j;          i = 36;         j = 217;         do         {                 while (--j);         } while (--i); }   void Delay30us()                //@11.0592MHz {         unsigned char i;          i = 11;         while (--i); }  void Delay27us()                //@11.0592MHz {         unsigned char i;          _nop_();         i = 9;         while (--i); }  void start()//開始信號(hào)   {     io=1;     delay1();     io=0;     Delay20ms();// 主機(jī)把總線拉低必須大于18ms保證DHT11能檢測(cè)到起始信號(hào)     io=1;    //發(fā)送開始信號(hào)結(jié)束后拉高電平延時(shí)20-40us    Delay30us();//以下三個(gè)延時(shí)函數(shù)差不多為24us符合要求      }      uchar receive_byte()//接收一個(gè)字節(jié)//   {     uchar i,temp;     for(i=0;i<8;i++)//接收8bit的數(shù)據(jù)     {            while(!io);//等待50us的低電平開始信號(hào)結(jié)束    Delay27us();//開始信號(hào)結(jié)束之后延時(shí)26us-28us以下三個(gè)延時(shí)函數(shù)              temp=0;//時(shí)間為26us-28us表示接收的為數(shù)據(jù)'0'            if(io==1)            temp=1; //如果26us-28us之后還為高電平則表示接收的數(shù)據(jù)為'1'       while(io);//等待數(shù)據(jù)信號(hào)高電平'0'為26us-28us'1'為70us            data_byte<<=1;//接收的數(shù)據(jù)為高位在前右移            data_byte|=temp;     }     return data_byte;   }         void receive()//接收數(shù)據(jù)//   {     uchar T_H,T_L,R_H,R_L,check,num_check;     start();//開始信號(hào)//     io=1;   //主機(jī)設(shè)為輸入判斷從機(jī)DHT11響應(yīng)信號(hào)     if(!io)//判斷從機(jī)是否有低電平響應(yīng)信號(hào)//     {           while(!io);//判斷從機(jī)發(fā)出 80us 的低電平響應(yīng)信號(hào)是否結(jié)束//           while(io);//判斷從機(jī)發(fā)出 80us 的高電平是否結(jié)束如結(jié)束則主機(jī)進(jìn)入數(shù)據(jù)接收狀態(tài)           R_H=receive_byte();//濕度高位            R_L=receive_byte();//濕度低位           T_H=receive_byte();//溫度高位           T_L=receive_byte();//溫度低位           check=receive_byte();//校驗(yàn)位           io=0; //當(dāng)最后一bit數(shù)據(jù)接完畢后從機(jī)拉低電平50us//   Delay27us();//差不多50us的延時(shí)   Delay27us();           io=1;//總線由上拉電阻拉高進(jìn)入空閑狀態(tài)           num_check=R_H+R_L+T_H+T_L;           if(num_check==check)//判斷讀到的四個(gè)數(shù)據(jù)之和是否與校驗(yàn)位相同            {      RH=R_H;      RL=R_L;      TH=T_H;      TL=T_L;      check=num_check;            }     }   }
回復(fù)

使用道具 舉報(bào)

地板
ID:311407 發(fā)表于 2018-5-10 09:26 | 只看該作者
時(shí)序的時(shí)間很重要,延時(shí)函數(shù)看是否正確
回復(fù)

使用道具 舉報(bào)

5#
ID:116263 發(fā)表于 2018-5-10 10:30 | 只看該作者
HC6800-ES-V2.0 發(fā)表于 2018-5-10 07:24
為什么要從STM32移植,直接用51的不好嗎?
給你一個(gè):
/********************************************** ...

因?yàn)橐郧靶枰?2檢測(cè)DHT11,根據(jù)時(shí)序圖來看,F(xiàn)在需要51,所以就移植過去,卻有問題,我只是想知道問題出在哪里,所以才沒用51的
回復(fù)

使用道具 舉報(bào)

6#
ID:232585 發(fā)表于 2018-5-10 15:59 | 只看該作者
延時(shí)函數(shù)不對(duì)吧
回復(fù)

使用道具 舉報(bào)

7#
ID:275894 發(fā)表于 2019-4-14 17:38 | 只看該作者
今天調(diào)試,也出現(xiàn)類似的問題,數(shù)據(jù)接收不對(duì),校驗(yàn)和出錯(cuò)(很詭異,DTH11輸出校驗(yàn)和與實(shí)際計(jì)算值偏差10以內(nèi)),
回復(fù)

使用道具 舉報(bào)

8#
ID:275894 發(fā)表于 2019-4-14 17:41 | 只看該作者
調(diào)試中也出現(xiàn)類似問題,最后發(fā)現(xiàn)問題出在DTH11應(yīng)答位延時(shí)時(shí)間不準(zhǔn)。
DTH11應(yīng)答位,輸出高/低電平為80us;如果不符合這個(gè)值,將會(huì)造成接收數(shù)據(jù)與時(shí)間值不符,校驗(yàn)和不對(duì);
我將應(yīng)答位的判斷,全部換用while循環(huán),才解決該問題;見備注處;

void DTH_rec_all()
{
     DTH_start();
     if(dat==0)
         {
         while(dat==0);
         while(dat==1);
/*
此處非常不建議使用延時(shí)函數(shù)delay80us來代替該while循環(huán),
否則容易導(dǎo)致后面采集的數(shù)據(jù)不準(zhǔn),并且校驗(yàn)和不對(duì)
*/
         R_H=Rec_DTH();
         R_L=Rec_DTH();
         T_H=Rec_DTH();
         T_L=Rec_DTH();
         sum=Rec_DTH();
         }  
}
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表