標(biāo)題: 51單片機(jī)延時(shí) [打印本頁]

作者: sirius2015    時(shí)間: 2017-6-28 10:46
標(biāo)題: 51單片機(jī)延時(shí)
void delay(unsigned int n)
{
    while(n--);
}

void main()
{
   delay(10);       
}

delay(10)是延時(shí)多長時(shí)間的?在晶振是12M的情況下


我用KEIL 查,轉(zhuǎn)成的匯編如下:

main 函數(shù)

C:0x0020    7F03     MOV      R7,#0x03
C:0x0022    7E00     MOV      R6,#0x00
C:0x0024    020003   LJMP     delay(C:0003)
C:0x0027    00       NOP      
C:0x0028    00       NOP   


     3: void delay(unsigned int n)
     4: {
     5:         while(n--);
C:0x000F    EF       MOV      A,R7
C:0x0010    1F       DEC      R7
C:0x0011    AC06     MOV      R4,0x06
C:0x0013    7001     JNZ      C:0016
C:0x0015    1E       DEC      R6
C:0x0016    4C       ORL      A,R4
C:0x0017    70F6     JNZ      delay(C:000F)
     6: }
     7:  
C:0x0019    22       RET      


從上述匯編中可以看到,n每次執(zhí)行一遍,需要大概4條單周期指令+2條雙周期指令,也就沒每次延時(shí) 8μ秒
所以10次的話,那就是 8*10 + 4 + 2
其中4為函數(shù)參數(shù)入棧和跳轉(zhuǎn),2位函數(shù)返回。

問題
1)不知道這樣理解對不對?
2)另外,不知道KEIL生產(chǎn)hex的時(shí)候,會不會對匯編再進(jìn)行優(yōu)化?
2)C:0x0011    AC06     MOV      R4,0x06 沒看明白這條匯編有什么用,為什么將0x06放入R4,為什么是0x06,為什么是R4?
     C:0x0016    4C       ORL      A,R4. 這條也不明白,直接判斷A是否為0不就得了,為什么還要與R4或呢?
     



作者: hzlsw1    時(shí)間: 2017-6-28 13:04
你簡單問題復(fù)雜化,你用調(diào)試模式直接可以看大概延時(shí)多久有必要這樣嗎
作者: zhczlzhang    時(shí)間: 2017-6-28 16:11
1)delay(10)是延時(shí)多長時(shí)間的,首先我可以告訴你,不知道。
為什么呢?那是因?yàn)樵谀愕倪@個(gè)程序中,delay是做變量運(yùn)算的,你的單片機(jī)是高速單片機(jī),這個(gè)delay10就快,是低速單片機(jī)就慢。
所以它不是精確延時(shí),只能說是模糊延時(shí),想精確延時(shí),就用定時(shí)器,這樣可以算出來具體時(shí)間。
2)KEIL生產(chǎn)hex的時(shí)候,會不會對匯編再進(jìn)行優(yōu)化?這個(gè)問題keil只是對你的程序進(jìn)行匯編,至于優(yōu)化在51版本里,我沒聽說過,在MDK版本里我聽說過。所以要看版本。
3)你的匯編我不太懂,建議你去看匯編語言這本書,里面有詳細(xì)講解。
作者: ahshmj    時(shí)間: 2017-6-28 16:59
keil轉(zhuǎn)的匯編有些是真的很麻煩。
作者: adidlas    時(shí)間: 2017-6-28 17:01
可能是編的程序不對
作者: 夢孤城    時(shí)間: 2017-6-28 17:43
延時(shí)要根據(jù)晶振頻率來計(jì)算,12M的晶振也即是時(shí)鐘周期為83.3ns,然后再根據(jù)數(shù)據(jù)的讀取延時(shí)來計(jì)算準(zhǔn)確的延時(shí)時(shí)間。在單片機(jī)中,一個(gè)時(shí)鐘節(jié)拍執(zhí)行一條代碼,執(zhí)行10次也即是833ns,再根據(jù)板上布線延時(shí),所以延時(shí)時(shí)間還會更長一些。但是在51中想要知道確切的延時(shí)的話,使用仿真芯片在Keil中進(jìn)行仿真就可以了
作者: 柳千刀    時(shí)間: 2017-6-28 18:01
//延時(shí) void Delay(WORD n){              WORD x;          while(n--)           {      x=500;   while(x--);  }         }
作者: sirius2015    時(shí)間: 2017-6-29 10:40
夢孤城 發(fā)表于 2017-6-28 17:43
延時(shí)要根據(jù)晶振頻率來計(jì)算,12M的晶振也即是時(shí)鐘周期為83.3ns,然后再根據(jù)數(shù)據(jù)的讀取延時(shí)來計(jì)算準(zhǔn)確的延時(shí) ...

嗯,12M晶振的話,對于C51來說,一個(gè)指令周期=一個(gè)機(jī)器周期=12個(gè)時(shí)鐘周期,也就是1μs。加上些線的延時(shí),可能稍微延長些。
作者: sirius2015    時(shí)間: 2017-6-29 10:47
zhczlzhang 發(fā)表于 2017-6-28 16:11
1)delay(10)是延時(shí)多長時(shí)間的,首先我可以告訴你,不知道。
為什么呢?那是因?yàn)樵谀愕倪@個(gè)程序中,delay ...

我其實(shí)也沒要求很精確,就一個(gè)模糊的值,就行。我再看吳鑒英C51開發(fā)板里面的DS18B20的代碼,里面有很多關(guān)于時(shí)序的操作,要延時(shí)多長時(shí)間。

delay(5); 說是延時(shí)大概44us
delay(20); 說是延時(shí)大概140us
delay(80); 說是延時(shí)大概530us

我感覺每一個(gè)是6-9之間的樣子,相差是不是有點(diǎn)大。我原以為應(yīng)該在8-9之間。

作者: yzwzfyz    時(shí)間: 2017-6-30 01:18
關(guān)于“MOV      R4,0x06”
因?yàn)闆]有:MOV   R4, R6 這條指令,而0x06在CPU復(fù)位后,與R6是等價(jià)的。

關(guān)于“ORL      A,R4. 這條也不明白,直接判斷A是否為0不就得了,為什么還要與R4或呢?”
因?yàn)?前面A取的是R7,如果直接判斷A,就是看R7是否為0,“與R4或”之后,就是判斷R7、R4同時(shí)為0。

C在編譯時(shí)(轉(zhuǎn)匯編)是很“蠢”的,不如自己寫的爽。




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