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

QQ登錄

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

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

整理STC單片機(jī)延時(shí)函數(shù)時(shí)遇到的玄學(xué)問(wèn)題

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
  1. void Delay  

  2. {  

  3.     unsigned char i, j;  

  4.     i = 11;  

  5.     j = 190;  

  6.     do  

  7.     {  

  8.         while (--j);  

  9.     } while (--i);  

  10. }  

  11.   

  12.   

  13.   

  14. void Delay  

  15. {  

  16.     unsigned char i, j;  

  17.     i = 11;  

  18.     j = 190;  

  19.     while(i--)  

  20.     {  

  21.         while (--j);  

  22.     }  

  23. }  



復(fù)制代碼


以上兩段代碼,第一段為STCISP提供的1ms延時(shí)函數(shù),第二段為改編版。按照個(gè)人對(duì)C語(yǔ)言的理解,這兩種寫(xiě)法所得到的結(jié)果應(yīng)該是一致的,最起碼在Dev-C++上以下兩端代碼輸出結(jié)果相同,均為2739:


  1. int main(int argc, char *argv[])

  2. {

  3.     unsigned char i, j;

  4.     int num = 0;

  5.     i = 11;

  6.     j = 190;

  7.     while(i--)

  8.     {

  9.         while (--j)

  10.         {

  11.             num++;

  12.         }

  13.     }

  14.     printf("num=%d\n",num);

  15.     return 0;

  16. }







  17. int main(int argc, char *argv[])

  18. {

  19.     unsigned char i, j;

  20.     int num = 0;

  21.     i = 11;

  22.     j = 190;

  23.     do

  24.     {

  25.         while (--j)

  26.         {

  27.             num++;

  28.         }

  29.     } while (--i);

  30.     printf("num=%d\n",num);

  31.     return 0;

  32. }

復(fù)制代碼



但開(kāi)頭提到的兩段代碼,在STC15F104(11.0592M)單片機(jī)上跑起來(lái)其延時(shí)結(jié)果卻截然不同。實(shí)測(cè)在預(yù)設(shè)延時(shí)500ms時(shí)(即重復(fù)運(yùn)行上述函數(shù)500次),第一段代碼比較符合實(shí)際,第二段要比第一段要慢一倍左右,即將第二段代碼中的11改為6后可以得到大體相同的延時(shí)結(jié)果。

造成這種現(xiàn)象的原因,到現(xiàn)在也沒(méi)搞清楚,我發(fā)表在開(kāi)源電子網(wǎng)的提問(wèn)貼截止到目前也沒(méi)有收到合理的解釋。我不打算再耗下去,只能強(qiáng)行解釋一波了:

造成延時(shí)結(jié)果不同的原因是單片機(jī)在執(zhí)行 while()...; 和 do...while(); 時(shí)的效率不同。





這解釋很有道理,因?yàn)樵?while()...; 和 do...while(); 在匯編代碼中的長(zhǎng)度的確相差一倍左右。但仍不能很好解釋延時(shí)結(jié)果相差之大。因?yàn)闊o(wú)論是 while()...; 和 do...while(); ,在延時(shí)函數(shù)中僅僅執(zhí)行了11次而已,真正起決定性作用的應(yīng)該是中間那段 while (--j); ,在如此大基數(shù)的循環(huán)下, while()...; 和 do...while();  相差的那點(diǎn)時(shí)間應(yīng)該顯得微不足道才對(duì)啊。

算了,這件事告一段落了,不打算再在這上面浪費(fèi)時(shí)間了。下面附上 while()...; 和 do...while(); 的匯編代碼。代碼來(lái)源于網(wǎng)絡(luò),其實(shí)我也不懂。


  1. /**** while 語(yǔ)句 pseudo-code ********/

  2. while ( condition )

  3. {  

  4.   body of loop;

  5. }

  6. /****while 語(yǔ)句 assembly language *******/

  7. while:

  8. ; code to set FLAGS based on condition

  9. jxx   endwhile

  10. ; body of loop

  11. jmp while

  12. endwhile:

  13. /****while 語(yǔ)句 assembly language (end) ***/  



  14. /**** Do while 語(yǔ)句 pseudo-code ********/

  15. do

  16. {

  17.   body of loop;

  18. }while ( condition )

  19. /****Do while 語(yǔ)句 assembly language *******/

  20. do_while:

  21. ; body of loop

  22. ; code to set FLAGS based on condition

  23. jxx   do_while

  24. /****Do while 語(yǔ)句 assembly language (end) ***/
復(fù)制代碼





評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

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

使用道具 舉報(bào)

沙發(fā)
ID:462827 發(fā)表于 2019-4-29 08:30 | 只看該作者
樓主提到Dev-C++,你這是在PC上編譯且運(yùn)行的吧。

你得在51上把那兩個(gè)delay調(diào)試轉(zhuǎn)成匯編,認(rèn)認(rèn)真真計(jì)算它們的具體所用指令周期,相信你會(huì)有所發(fā)現(xiàn)的。
回復(fù)

使用道具 舉報(bào)

板凳
ID:522450 發(fā)表于 2019-4-29 09:56 | 只看該作者
摘錄了一本書(shū)中的內(nèi)容,應(yīng)該可以很好解釋你的問(wèn)題,至少,是你的代碼產(chǎn)生差別的主要原因,你找的原因可能有影響,但應(yīng)該不是主因。


回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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