久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

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

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 7857|回復(fù): 29
收起左側(cè)

誤人子弟的程序分析

  [復(fù)制鏈接]
ID:65751 發(fā)表于 2014-10-6 22:36 | 顯示全部樓層 |閱讀模式
本帖最后由 codenew 于 2014-10-6 22:42 編輯

       下面程序是我從別的地方搞來(lái)的,最后發(fā)現(xiàn)很多錯(cuò)誤。為了避免誤人子弟,特地作了一下分析,開(kāi)頭部分for分析是我寫(xiě)的,程序中紅色的部分我是加上去的。
        在軟件仿真環(huán)境下,把晶振改成12.0Mhz,C51標(biāo)簽代碼優(yōu)化設(shè)為0,見(jiàn)圖附件,測(cè)得for語(yǔ)句的延時(shí)為:
   for(time=0;time<1;time++);  //15us
   for(time=0;time<2;time++);  //23us
   for(time=0;time<3;time++);  //31us
   for(time=0;time<4;time++);  //39us
   for(time=0;time<5;time++);  //47us
   for(time=0;time<6;time++);  //55us
   for(time=0;time<7;time++);  //63us
   for(time=0;time<8;time++);  //71us
   for(time=0;time<9;time++);  //79us
   for(time=0;time<10;time++); //87us
   for(time=0;time<20;time++); //167us
   for(time=0;time<60ime++);  //487us
   for(time=0;time<70ime++);  //567us
   for(time=0;time<80ime++);  //647us
   for(time=0;time<100;time++);  //807us
   for(time=0;time<200;time++); //1607us
    由上可看出,成等差數(shù)列,公差d=8。一般地,如果n>man=am+8*(n-m)。



/*****************************************************
函數(shù)功能:將DS18B20傳感器初始化,讀取應(yīng)答信號(hào)
出口參數(shù):flag
***************************************************/
bit Init_DS18B20(void)
{
       bitflag;         //儲(chǔ)存DS18B20是否存在的標(biāo)志,flag=0,表示存在;flag=1,表示不存在
       DQ= 1;           //先將數(shù)據(jù)線(xiàn)拉高
       for(time=0;time<2;time++);//略微延時(shí)約6微秒。實(shí)際是延時(shí)23us。
       DQ= 0;           //再將數(shù)據(jù)線(xiàn)從高拉低,要求保持480~960us
       for(time=0;time<200;time++);//略微延時(shí)約600微秒,以向DS18B20發(fā)出一持續(xù)480~960us的低電平復(fù)位脈沖。實(shí)際是延時(shí)1607us,重大錯(cuò)誤,都超過(guò)960us了。
       DQ= 1;           //釋放數(shù)據(jù)線(xiàn)(將數(shù)據(jù)線(xiàn)拉高)
       for(time=0;time<10;time++);//延時(shí)約30us(釋放總線(xiàn)后需等待15~60usDS18B20輸出存在脈沖)。實(shí)際是延時(shí)87us,延時(shí)多過(guò)60us,反而能保證讀到存在脈沖,這點(diǎn)誤撞了。
       flag=DQ;          //讓單片機(jī)檢測(cè)是否輸出了存在脈沖(DQ=0表示存在)      
       for(time=0;time<200;time++);  //延時(shí)足夠長(zhǎng)時(shí)間,等待存在脈沖輸出完畢
       return(flag);    //返回檢測(cè)成功標(biāo)志
}
/*****************************************************
函數(shù)功能:從DS18B20讀取一個(gè)字節(jié)數(shù)據(jù)
出口參數(shù):dat
***************************************************/
unsigned char ReadOneChar(void)
{
       unsignedchar i=0;  
       unsignedchar dat;            //儲(chǔ)存讀出的一個(gè)字節(jié)數(shù)據(jù)
       for(i=0;i<8;i++)
       {
              DQ=1;                    //先將數(shù)據(jù)線(xiàn)拉高
              _nop_();               //等待一個(gè)機(jī)器周期   
              DQ= 0;        //單片機(jī)從DS18B20讀書(shū)據(jù)時(shí),將數(shù)據(jù)線(xiàn)從高拉低即啟動(dòng)讀時(shí)序
              dat>>=1;
              _nop_();        //等待一個(gè)機(jī)器周期                 
              DQ= 1;        //將數(shù)據(jù)線(xiàn)"人為"拉高,為單片機(jī)檢測(cè)DS18B20的輸出電平作準(zhǔn)備
              for(time=0;time<2;time++);//延時(shí)約6us,使主機(jī)在15us內(nèi)采樣。實(shí)際是延時(shí)23us,超過(guò)了15us。
              if(DQ==1)
              dat|=0x80;                //如果讀到的數(shù)據(jù)是1,則將1存入dat
              else
              dat|=0x00;/如果讀到的數(shù)據(jù)是0,則將0存入dat,將單片機(jī)檢測(cè)到的電平信號(hào)DQ、r
              for(time=0;time<8;time++);//延時(shí)3us,兩個(gè)讀時(shí)序之間必須有大于1us的恢復(fù)期。實(shí)際是延時(shí)71us。思路根本不對(duì),讀時(shí)隙至少延時(shí)60us,這里又誤撞對(duì)了,把至少延時(shí)和讀時(shí)隙間隔至少1us都包含進(jìn)了。
           }                        
              return(dat);    //返回讀出的十進(jìn)制數(shù)據(jù)
}
/*****************************************************
函數(shù)功能:向DS18B20寫(xiě)入一個(gè)字節(jié)數(shù)據(jù)
入口參數(shù):dat
***************************************************/  
WriteOneChar(unsigned char dat)
{
       unsignedchar i=0;
       for(i=0; i<8; i++)
       {
              DQ=1;         // 先將數(shù)據(jù)線(xiàn)拉高
              _nop_();     //等待一個(gè)機(jī)器周期        
              DQ=0;          //將數(shù)據(jù)線(xiàn)從高拉低時(shí)即啟動(dòng)寫(xiě)時(shí)序      
              DQ=dat&0x01;   //利用與運(yùn)算取出要寫(xiě)的某位二進(jìn)制數(shù)據(jù),并將其送到數(shù)據(jù)線(xiàn)上等待DS18B20采樣   
              for(time=0;time<10;time++);//延時(shí)約30usDS18B20在拉低后的約15~60us期間從數(shù)據(jù)線(xiàn)上采樣。實(shí)際是延時(shí)87us
              DQ=1;          //釋放數(shù)據(jù)線(xiàn)            
              for(time=0;time<1;time++);//延時(shí)3us,兩個(gè)寫(xiě)時(shí)序間至少需要1us的恢復(fù)期 。實(shí)際是延時(shí)15us。
              dat>>=1;       //dat中的各二進(jìn)制位數(shù)據(jù)右移1
       }
       for(time=0;time<4;time++);//稍作延時(shí),給硬件一點(diǎn)反應(yīng)時(shí)間。延時(shí)39us   
}
/*****************************************************
函數(shù)功能:做好讀溫度的準(zhǔn)備
***************************************************/
void ReadyReadTemp(void)
{
       Init_DS18B20();             //DS18B20初始化
       WriteOneChar(0xCC);         // 跳過(guò)讀序號(hào)列號(hào)的操作
       WriteOneChar(0x44);         // 啟動(dòng)溫度轉(zhuǎn)換        
       for(time=0;time<100;time++);//溫度轉(zhuǎn)換需要一點(diǎn)時(shí)間。延時(shí)807us。
       Init_DS18B20();     //DS18B20初始化
       WriteOneChar(0xCC);//跳過(guò)讀序號(hào)列號(hào)的操作
       WriteOneChar(0xBE);//讀取溫度寄存器,前兩個(gè)分別是溫度的低位和高位   
}
/*****************************************************
函數(shù)功能:延時(shí)若干毫秒
入口參數(shù):n
***************************************************/
voiddelaynms(unsigned char n)
{
  unsigned char i;
       for(i=0;i<n;i++)
          delay1ms();
}
     照理說(shuō)void delaynms(unsigned char n),參數(shù)n的取值范圍是0~255,因是是無(wú)符號(hào)數(shù)。但在主函數(shù)中卻調(diào)用delaynms(1000),明顯錯(cuò)誤,超出取值范圍。

C51代碼優(yōu)化

C51代碼優(yōu)化

評(píng)分

參與人數(shù) 1黑幣 +30 收起 理由
dww465757120 + 30 贊一個(gè)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 08:47 | 顯示全部樓層
程序的注釋?zhuān)皇峭耆珜?duì)。
程序通過(guò)返復(fù)調(diào)整得到正確代碼,這是每一個(gè)程序員編程過(guò)程,
在這過(guò)程中不可能總是修改注釋?zhuān)?br /> 這樣就導(dǎo)致注釋的不同步。
延時(shí)函數(shù)一般情況下是線(xiàn)性。
原程序的運(yùn)行機(jī)器周期可能不是1us
回復(fù)

使用道具 舉報(bào)

ID:65751 發(fā)表于 2014-10-7 10:54 | 顯示全部樓層
樓上,我敢保證我的想法是對(duì)的。因?yàn)榘言闯绦蛟獠粍?dòng)寫(xiě)入芯片,測(cè)溫是正常顯示的,晶振是12Mhz。當(dāng)然引腳也是對(duì)應(yīng)的。
回復(fù)

使用道具 舉報(bào)

ID:65751 發(fā)表于 2014-10-7 11:13 | 顯示全部樓層
這要?jiǎng)幽X再想想哪程序錯(cuò)了,為什么還能正常用,的確運(yùn)氣很好。例如源程序的另一個(gè)延時(shí)程序又是錯(cuò)的,其注釋思路肯定不對(duì),但其實(shí)際效果還是接近1ms的:
/*****************************************************
函數(shù)功能:延時(shí)1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認(rèn)為是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 15:37 | 顯示全部樓層
codenew 發(fā)表于 2014-10-7 10:54
樓上,我敢保證我的想法是對(duì)的。因?yàn)榘言闯绦蛟獠粍?dòng)寫(xiě)入芯片,測(cè)溫是正常顯示的,晶振是12Mhz。當(dāng)然引腳 ...

DS18B20的讀寫(xiě)操作需要一段時(shí)間,是不能短于時(shí)順規(guī)定的時(shí)間,如果延時(shí)長(zhǎng)了,只是浪費(fèi)時(shí)間而已。
可以長(zhǎng),但是不能短
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 15:40 | 顯示全部樓層
codenew 發(fā)表于 2014-10-7 11:13
這要?jiǎng)幽X再想想哪程序錯(cuò)了,為什么還能正常用,的確運(yùn)氣很好。例如源程序的另一個(gè)延時(shí)程序又是錯(cuò)的,其注釋 ...

如果晶振是12Mhz。那么
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}
這個(gè)就不能認(rèn)為是1ms,相差不只一倍
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 15:48 | 顯示全部樓層
你延時(shí)這樣計(jì)算就有錯(cuò)誤
看看 delay1ms()
編譯出來(lái)的內(nèi)碼,精算一下:
delay1ms:   CLR   A                  //1T
                   MOV   R7,A            //1T
D1:             CLR   A                   //1T
                   MOV   R6,A             //1T
D2:              INC   R6                 //1T
                   CJNE  R6,#21H,D2 //2T
                   INC   R7                  //1T
                   CJNE  R7,#04H,D1 //2T
                   RET                        //2T
2T + [( 2T + 33 * 3T) + 1T + 2T ] * 4 + 2T
= 2T + [ 101T + 1T + 2T ] * 4 + 2T
= 2T + [ 104 T] * 4 + 2T
= 2T + [ 104 T] * 4 + 2T
= 420T
再加上調(diào)用delay1ms()時(shí)間,需要的LCALL兩個(gè)機(jī)器周期,就是:
422us
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 16:12 | 顯示全部樓層
   for(time=0;time<1;time++);  //15us
   for(time=0;time<2;time++);  //23us
   for(time=0;time<3;time++);  //31us
   for(time=0;time<4;time++);  //39us
   for(time=0;time<5;time++);  //47us
   for(time=0;time<6;time++);  //55us
   for(time=0;time<7;time++);  //63us
   for(time=0;time<8;time++);  //71us
   for(time=0;time<9;time++);  //79us
   for(time=0;time<10;time++); //87us
   for(time=0;time<20;time++); //167us
   for(time=0;time<60ime++);  //487us
   for(time=0;time<70ime++);  //567us
   for(time=0;time<80ime++);  //647us
   for(time=0;time<100;time++);  //807us
   for(time=0;time<200;time++); //1607us
這些原地延時(shí)是沒(méi)有可變性的(當(dāng)然是排除中斷的騷擾),
編譯出來(lái)的機(jī)器碼是有固定模式的:
START:        CLR   A       //1T
                   MOV   R7,A  //1T
LOOP:         INC   R7      //1T
                   CJNE  R7,#02H,LOOP     //2T
所以延時(shí)時(shí)間:2T+time*(1T+2T)=2T+time*3T=(2+time*3)T
如果一個(gè)機(jī)器周期為:1us
  an=am+8*(n-m)。這跟:
    =2+3*time差別大不大?
   for(time=0;time<1;time++);  //15us-------5us
   for(time=0;time<2;time++);  //23us-------8us
   for(time=0;time<3;time++);  //31us-------11us
   for(time=0;time<4;time++);  //39us-------14us
   for(time=0;time<5;time++);  //47us-------17us
   for(time=0;time<6;time++);  //55us-------20us
   for(time=0;time<7;time++);  //63us-------23us
   for(time=0;time<8;time++);  //71us-------26us
   for(time=0;time<9;time++);  //79us-------29us
   for(time=0;time<10;time++); //87us-------32us
   for(time=0;time<20;time++); //167us-------62us
   for(time=0;time<60ime++);  //487us-------182us
   for(time=0;time<70ime++);  //567us-------212us
   for(time=0;time<80ime++);  //647us-------242us
   for(time=0;time<100;time++);  //807us-------302us
   for(time=0;time<200;time++); //1607us-------602us
回復(fù)

使用道具 舉報(bào)

ID:65751 發(fā)表于 2014-10-7 20:31 | 顯示全部樓層
本帖最后由 codenew 于 2014-10-7 20:37 編輯

樓上算錯(cuò)了吧。見(jiàn)附圖,運(yùn)行完359行指令res=0;時(shí)的時(shí)間點(diǎn)為631us;運(yùn)行完360行指令 for(time=0;time<1;time++);  時(shí)的時(shí)間點(diǎn)為646us,注意黃色箭頭指向下一條。646us-631us=15us,即為 運(yùn)行for(time=0;time<1;time++); 的時(shí)間。
我反匯編 for(time=0;time<1;time++);  代碼如下:
   360:         for(time=0;time<1;time++);
C:0x0005    752E00   MOV      time(0x2E),#0x00
C:0x0008    E52E     MOV      A,time(0x2E)
C:0x000A    C3       CLR      C
C:0x000B    9401     SUBB     A,#0x01
C:0x000D    5004     JNC      C:0013
C:0x000F    052E     INC      time(0x2E)
C:0x0011    80F5     SJMP     C:0008
   361:         res=0;
C:0x0013    C20B     CLR      0x21.3
d1.jpg
d2.jpg
回復(fù)

使用道具 舉報(bào)

ID:65751 發(fā)表于 2014-10-7 20:50 | 顯示全部樓層
本帖最后由 codenew 于 2014-10-7 21:01 編輯

看看delay1ms(),1774us-647us=1127us,接近1ms。
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}

d3.jpg

d4.jpg



回復(fù)

使用道具 舉報(bào)

ID:44262 發(fā)表于 2014-10-7 22:15 來(lái)自手機(jī) | 顯示全部樓層
我靠 太牛了 ,樓主的這個(gè)帖子對(duì)我的幫助非常大 ,佩服得五體投地 阿
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 22:19 | 顯示全部樓層
本帖最后由 明白 于 2014-10-7 23:59 編輯

剛才我也仿真一下:

for(time=0;time<1;time++);的話(huà):
396-391=5個(gè)機(jī)器周期
參數(shù)1結(jié)束.png
參數(shù)1開(kāi)始.png
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-7 23:16 | 顯示全部樓層
本帖最后由 明白 于 2014-10-8 00:25 編輯

for(time=0;time<2;time++);的話(huà):
399-391=8個(gè)機(jī)器周期
參數(shù)2結(jié)束.png
參數(shù)2開(kāi)始.png
原地延時(shí)機(jī)器碼.jpg
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-8 00:06 | 顯示全部樓層
本帖最后由 明白 于 2014-10-8 00:37 編輯

delay1ms()延時(shí)函數(shù):
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}

834-412=422
看看delay1ms(),跟我上面精度計(jì)算結(jié)果也是422,一模一樣。
函數(shù)調(diào)用結(jié)束.jpg
函數(shù)調(diào)用開(kāi)始.jpg
函數(shù)調(diào)用延時(shí)機(jī)器碼.jpg
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-8 00:30 | 顯示全部樓層
全部的機(jī)器碼
全部代碼.jpg
回復(fù)

使用道具 舉報(bào)

ID:19715 發(fā)表于 2014-10-8 00:36 | 顯示全部樓層
本帖最后由 明白 于 2014-10-8 00:42 編輯

你篡改了別人原c語(yǔ)言程序的本意,
到此為止,你也應(yīng)該知道源程序哪里被你改了吧
回復(fù)

使用道具 舉報(bào)

ID:67070 發(fā)表于 2014-10-8 10:21 | 顯示全部樓層
沒(méi)看懂的說(shuō)
回復(fù)

使用道具 舉報(bào)

ID:65751 發(fā)表于 2014-10-8 17:14 | 顯示全部樓層
本帖最后由 codenew 于 2014-10-8 17:31 編輯

     認(rèn)真看了一下存在的爭(zhēng)議,主要是代碼優(yōu)化和全局變量出了問(wèn)題。我之前發(fā)的貼,代碼優(yōu)化是設(shè)為0的,由于代碼沒(méi)有優(yōu)化,存在冗余部分,所以執(zhí)行時(shí)間較長(zhǎng)。另外全局變量和局部變量也會(huì)影響執(zhí)行時(shí)間。
     新建的工程代碼優(yōu)化默認(rèn)為8,見(jiàn)下圖所示。     

優(yōu)化為8

優(yōu)化為8


     1.晶振設(shè)為12Mhz時(shí),代碼優(yōu)化為8 ,time為全局變量時(shí),主程序如下:
#include <reg52.h>#include <intrins.h>
unsigned char time;//設(shè)置全局變量,專(zhuān)門(mén)用于嚴(yán)格延時(shí)
void main()
{
bit res;
res=1;
while(1)
{
  res=0;
  for(time=0;time<1;time++);
  res=0;
  }
}
     測(cè)得  for(time=0;time<1;time++);時(shí)間如下:
   c1.jpg

c2.jpg    


      397us-391us=6us,即for(time=0;time<1;time++);為6us。同理time<2時(shí),為10us;time<3時(shí),為14us。一般地,n>m,time<n,n為正整數(shù),an=am+4*(n-m)。m=1時(shí),an=6+4*(n-1)=4n+2。
        for(time=0;time<1;time++);  //6us
        for(time=0;time<2;time++);  //10us
       for(time=0;time<3;time++);  //14us
       for(time=0;time<4;time++);  //18us
       for(time=0;time<5;time++);  //22us
       for(time=0;time<6;time++);  //26us
       for(time=0;time<7;time++);  //30us
       for(time=0;time<8;time++);  //34us
       for(time=0;time<9;time++);  //38us
       for(time=0;time<10;time++); //42us
       for(time=0;time<20;time++); //82us
       for(time=0;time<60ime++);  //242us
       for(time=0;time<70ime++);  //282us
      for(time=0;time<80ime++);  //322us
      for(time=0;time<100;time++);  //402us
      for(time=0;time<200;time++); //802us


      2.晶振設(shè)為12Mhz時(shí),代碼優(yōu)化為8 ,time為局部變量時(shí),主程序如下:
#include <reg52.h>
#include <intrins.h>
void main()
{
unsigned char time;//設(shè)置局部變量
bit res;
res=1;
while(1)
{
  res=0;
  for(time=0;time<1;time++);
  res=0;
  }
}
         測(cè)得  for(time=0;time<1;time++);時(shí)間如下:
c3.jpg


c4.jpg


        396us-391us=5us,即for(time=0;time<1;time++);為5us。同理time<2時(shí),為8us;time<3時(shí),為11us。一般地,n>m,time<n,n為正整數(shù),an=am+3*(n-m)。m=1時(shí),an=5+3*(n-1)=3n+2。
        for(time=0;time<1;time++);  //5us
        for(time=0;time<2;time++);  //8us
       for(time=0;time<3;time++);  //11us
       for(time=0;time<4;time++);  //14us
       for(time=0;time<5;time++);  //17us
       for(time=0;time<6;time++);  //20us
       for(time=0;time<7;time++);  //23us
       for(time=0;time<8;time++);  //26us
       for(time=0;time<9;time++);  //29us
       for(time=0;time<10;time++); //32us
       for(time=0;time<20;time++); //62us
       for(time=0;time<60ime++);  //182us
       for(time=0;time<70ime++);  //212us
      for(time=0;time<80ime++);  //242us
      for(time=0;time<100;time++);  //302us
      for(time=0;time<200;time++); //602us      
      這點(diǎn)和8樓的一致。                  3.重要說(shuō)明,源程序的time是全局變量!當(dāng)優(yōu)化代碼為默認(rèn)的級(jí)別8時(shí),再回頭看源程序的注釋。void delay1ms()正如7樓所說(shuō),是422us,不是源程序注釋所說(shuō)的1ms,其它的可參照第1點(diǎn)全局變量time所羅列的延時(shí)時(shí)間。





回復(fù)

使用道具 舉報(bào)

ID:65751 發(fā)表于 2014-10-9 09:50 | 顯示全部樓層
本帖最后由 codenew 于 2014-10-9 09:58 編輯

//下面的time在源程序中都是全局變量!
/*****************************************************
函數(shù)功能:將DS18B20傳感器初始化,讀取應(yīng)答信號(hào)
出口參數(shù):flag
***************************************************/
bit Init_DS18B20(void)
{
       bitflag;         //儲(chǔ)存DS18B20是否存在的標(biāo)志,flag=0,表示存在;flag=1,表示不存在
       DQ= 1;           //先將數(shù)據(jù)線(xiàn)拉高
       for(time=0;time<2;time++);//略微延時(shí)約6微秒。實(shí)際是延時(shí)10us,局部變量時(shí)為8us,不是注釋所說(shuō)的6us。
       DQ= 0;           //再將數(shù)據(jù)線(xiàn)從高拉低,要求保持480~960us
       for(time=0;time<200;time++);//略微延時(shí)約600微秒,以向DS18B20發(fā)出一持續(xù)480~960us的低電平復(fù)位脈沖。實(shí)際是延時(shí)802us,time為局部變量時(shí)才為602us,即約600us。這點(diǎn)作者明顯誤撞了,幸好802us還在范圍內(nèi)。
       DQ= 1;           //釋放數(shù)據(jù)線(xiàn)(將數(shù)據(jù)線(xiàn)拉高)
       for(time=0;time<10;time++);//延時(shí)約30us(釋放總線(xiàn)后需等待15~60us讓DS18B20輸出存在脈沖)。實(shí)際是延時(shí)42us,time為局部變量時(shí)才為 32us,即約32us。明顯作者又錯(cuò)了,把time當(dāng)作局部變量了,幸好 42us還在范圍內(nèi)。實(shí)際最好延時(shí)60us,確保能讀到存在脈沖。
       flag=DQ;          //讓單片機(jī)檢測(cè)是否輸出了存在脈沖(DQ=0表示存在)      
       for(time=0;time<200;time++);  //延時(shí)足夠長(zhǎng)時(shí)間,等待存在脈沖輸出。延時(shí)802us。
       return(flag);    //返回檢測(cè)成功標(biāo)志
}
/*****************************************************
函數(shù)功能:從DS18B20讀取一個(gè)字節(jié)數(shù)據(jù)
出口參數(shù):dat
***************************************************/
unsigned char ReadOneChar(void)
{
       unsignedchar i=0;  
       unsignedchar dat;            //儲(chǔ)存讀出的一個(gè)字節(jié)數(shù)據(jù)
       for(i=0;i<8;i++)
       {
              DQ=1;                    //先將數(shù)據(jù)線(xiàn)拉高
              _nop_();               //等待一個(gè)機(jī)器周期   
              DQ= 0;        //單片機(jī)從DS18B20讀書(shū)據(jù)時(shí),將數(shù)據(jù)線(xiàn)從高拉低即啟動(dòng)讀時(shí)序
              dat>>=1;
              _nop_();        //等待一個(gè)機(jī)器周期                 
              DQ= 1;        //將數(shù)據(jù)線(xiàn)"人為"拉高,為單片機(jī)檢測(cè)DS18B20的輸出電平作準(zhǔn)備
              for(time=0;time<2;time++);//延時(shí)約6us,使主機(jī)在15us內(nèi)采樣。實(shí)際是延時(shí)10us,局部變量時(shí)為8us,都不是注釋的6us。
              if(DQ==1)
              dat|=0x80;                //如果讀到的數(shù)據(jù)是1,則將1存入dat
              else
              dat|=0x00;/如果讀到的數(shù)據(jù)是0,則將0存入dat,將單片機(jī)檢測(cè)到的電平信號(hào)DQ、r
              for(time=0;time<8;time++);//延時(shí)3us,兩個(gè)讀時(shí)序之間必須有大于1us的恢復(fù)期。實(shí)際是延時(shí)34us,與3us差很多。
           }                        
              return(dat);    //返回讀出的十進(jìn)制數(shù)據(jù)
}
/*****************************************************
函數(shù)功能:向DS18B20寫(xiě)入一個(gè)字節(jié)數(shù)據(jù)
入口參數(shù):dat
***************************************************/  
WriteOneChar(unsigned char dat)
{
       unsignedchar i=0;
       for(i=0; i<8; i++)
       {
              DQ=1;         // 先將數(shù)據(jù)線(xiàn)拉高
              _nop_();     //等待一個(gè)機(jī)器周期        
              DQ=0;          //將數(shù)據(jù)線(xiàn)從高拉低時(shí)即啟動(dòng)寫(xiě)時(shí)序      
              DQ=dat&0x01;   //利用與運(yùn)算取出要寫(xiě)的某位二進(jìn)制數(shù)據(jù),并將其送到數(shù)據(jù)線(xiàn)上等待DS18B20采樣   
              for(time=0;time<10;time++);//延時(shí)約30us,DS18B20在拉低后的約15~60us期間從數(shù)據(jù)線(xiàn)上采樣。實(shí)際是延時(shí)42us,局部變量時(shí)才為32us。
              DQ=1;          //釋放數(shù)據(jù)線(xiàn)            
              for(time=0;time<1;time++);//延時(shí)3us,兩個(gè)寫(xiě)時(shí)序間至少需要1us的恢復(fù)期 。實(shí)際是延時(shí)6us,局部變量時(shí)才為5us。
              dat>>=1;       //將dat中的各二進(jìn)制位數(shù)據(jù)右移1位
       }
       for(time=0;time<4;time++);//稍作延時(shí),給硬件一點(diǎn)反應(yīng)時(shí)間。延時(shí)18us。   
}
/*****************************************************
函數(shù)功能:做好讀溫度的準(zhǔn)備
***************************************************/
void ReadyReadTemp(void)
{
       Init_DS18B20();             //將DS18B20初始化。既然Init_DS18B20();有返回值flag,不判斷其值是否成功就寫(xiě)命令了,又筆誤。
       WriteOneChar(0xCC);         // 跳過(guò)讀序號(hào)列號(hào)的操作
       WriteOneChar(0x44);         // 啟動(dòng)溫度轉(zhuǎn)換        
       for(time=0;time<100;time++);//溫度轉(zhuǎn)換需要一點(diǎn)時(shí)間。延時(shí)402us。
       Init_DS18B20();     //將DS18B20初始化
       WriteOneChar(0xCC);//跳過(guò)讀序號(hào)列號(hào)的操作
       WriteOneChar(0xBE);//讀取溫度寄存器,前兩個(gè)分別是溫度的低位和高位   
}
/*****************************************************
函數(shù)功能:延時(shí)若干毫秒
入口參數(shù):n
***************************************************/
voiddelaynms(unsigned char n)
{
  unsigned char i;
       for(i=0;i<n;i++)
          delay1ms();
}
    // 照理說(shuō)void delaynms(unsigned char n),參數(shù)n的取值范圍是0~255,因是是無(wú)符號(hào)數(shù)。但在主函數(shù)中卻調(diào)用delaynms(1000),明顯錯(cuò)誤,超出取值范圍。/*****************************************************
函數(shù)功能:延時(shí)1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認(rèn)為是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}
//實(shí)際延時(shí)422us,代碼優(yōu)化為0時(shí)才接近1ms。


回復(fù)

使用道具 舉報(bào)

ID:92810 發(fā)表于 2015-10-18 14:20 | 顯示全部樓層
好的,謝謝分享了。。。
回復(fù)

使用道具 舉報(bào)

ID:99672 發(fā)表于 2015-12-28 10:09 | 顯示全部樓層
有沒(méi)有完整的對(duì)的程序u
回復(fù)

使用道具 舉報(bào)

ID:101595 發(fā)表于 2016-1-10 21:04 來(lái)自手機(jī) | 顯示全部樓層
18b20有時(shí)候跟硬件關(guān)系很大,不同硬件程序跑出來(lái)不一樣,還有中斷也會(huì)影響到它的測(cè)量
回復(fù)

使用道具 舉報(bào)

ID:134697 發(fā)表于 2016-7-23 12:13 | 顯示全部樓層
樓主人好,技術(shù)不錯(cuò)。
回復(fù)

使用道具 舉報(bào)

ID:141210 發(fā)表于 2016-10-3 15:54 | 顯示全部樓層
看不懂呀,有完整程序啊


回復(fù)

使用道具 舉報(bào)

ID:196669 發(fā)表于 2017-5-5 10:54 | 顯示全部樓層
完整的有嗎?
回復(fù)

使用道具 舉報(bào)

ID:149451 發(fā)表于 2017-5-10 09:52 | 顯示全部樓層
欽佩做事認(rèn)真的人,因?yàn)樵袀ト苏f(shuō)過(guò),“世界上怕就怕認(rèn)真二字”,科學(xué)來(lái)不得半點(diǎn)馬虎。
回復(fù)

使用道具 舉報(bào)

ID:450849 發(fā)表于 2020-4-1 08:29 | 顯示全部樓層
阻塞式延時(shí)都是垃圾,,哈哈
回復(fù)

使用道具 舉報(bào)

ID:675145 發(fā)表于 2020-4-1 10:44 | 顯示全部樓層
神仙打架
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲视频一区在线观看 | 欧美午夜精品久久久久久浪潮 | 国产精品久久久久久久久污网站 | 精品视频一区二区三区在线观看 | 爱爱小视频 | 一区二区三区在线免费观看 | 91精品国产综合久久久动漫日韩 | 亚洲国产精品一区二区第一页 | 国产一区二区成人 | 欧美精三区欧美精三区 | www国产成人免费观看视频,深夜成人网 | 成人小视频在线免费观看 | 日日日操 | 亚洲日本一区二区三区四区 | 亚洲精彩免费视频 | 黄色片在线观看网址 | 99精品国产一区二区三区 | 久久久久久久久蜜桃 | 99久久久99久久国产片鸭王 | 亚洲国产精品精华素 | 成人免费淫片aa视频免费 | 久久午夜视频 | 色婷婷久久久久swag精品 | 欧美美女二区 | 欧美精品国产一区二区 | 国产成人在线一区二区 | 国色天香成人网 | 热99精品视频 | 欧美 日韩 在线播放 | 国产日韩久久 | 成年人免费网站 | 亚洲精品91 | 亚洲九九 | 久久国产成人精品国产成人亚洲 | 成人毛片在线视频 | 午夜一区| 亚洲草草视频 | 一本岛道一二三不卡区 | 午夜影院在线 | 亚洲欧美日韩电影 | 日韩在线小视频 |