void delay0.2s(void)
;((k*2)+3)*2+3)*i+5
我們用組合語言寫微控制器延時10ms的程式(用的是12mhz晶振的 mcs-51),可以編寫下面的程式來實現:
mov r5,#5 ①
d1: mov r6,#4 ②
d2: mov r7,#248 ③
djnz r7,$ ④
djnz r6,d2 ⑤
djnz r5,d1 ⑥
ret ⑦
這個延時程式共有七條指令,現在就每一條指令執行的次數和所耗時間進行分析:
第一條, mov r5,#5 在整個程式中只執行一次,且為單週期指令,所以耗時1μs,
第二條, mov r6,#4 看⑥的指令可知,只要r5-1不為0,就會返回執行這條指令,共執行了r5次,共耗時5μs,
第三條, mov r7,#248 同第二條類似,只要r6-1不為0,就會返回執行這條指令,同時受到外部迴圈r5的控制,共耗時r5*r6*1=20μs,
第四條, djnz r7,$ 只要r7-1不為0,就執行這條指令,同時受到外部迴圈的控制,由於該指令是雙週期指令,共耗時為r7*r6*r5*2=9920μs,
第五條, djnz r6,d2 只要r6-1不為0,就反覆執行此條指令(內迴圈r6次),又受外迴圈r7的控制,共耗時r6*r5*2=40μs,
第六條, djnz r5,d1 只要r5-1不為0,就反覆執行此條指令,耗時為r5*2=10μs,
第七條, ret 此指令為雙週期指令,耗時為2μs,
我們也要考慮在呼叫子程式時用到lcall指令,耗時2μs,最後可以得到總的延時為:1+5+20+9920+40+10+2+2=10000μs=10ms
我們可以總結延時總時間的公式:
延時總時間=[(2*一層迴圈次數+3)*二層迴圈次數+3]*三層迴圈次數+5
注意此公式只適用於三層以內的迴圈。
dly10s : mov r5,100 ;2指令 4us
dly10s1: mov r6,200 ;2指令 4us
dly10s2: mov r7,248 ;2指令 4us
dly10s3:
djnz r7,dly10s3;248*2+4----------------->2指令a = 248*2*2us
djnz r6,dly10s2;(248*2+4)*200+4 -------->2指令b =(a+2a+2b)*200*2us
djnz r5,dly10s1;[(248*2+4)*200+4]*100+4->2指令c =(b+2a+2a+2b)*100*2us
ret ;1指令 2us
總時間=c+1*2us;此處的+1是「ret」的時間;上述注釋中的「+2a」是mov指令週期,注意對應的迴圈;上述注釋的「+2b」是djnz本身的2個機器週期;應該是這樣的吧,你的程式可能有問題。
1 使用定時器/計數器實現精確延時
微控制器系統一般常選用11.059 2 mhz、12 mhz或6 mhz晶振。第一種更容易產生各種標準的波特率,後兩種的乙個機器週期分別為1 μs和2 μs,便於精確延時。本程式中假設使用頻率為12 mhz的晶振。最長的延時時間可達216=65 536 μs。若定時器工作在方式2,則可實現極短時間的精確延時;如使用其他定時方式,則要考慮重灌定時初值的時間(重灌定時器初值占用2個機器週期)。
在實際應用中,定時常採用中斷方式,如進行適當的迴圈可實現幾秒甚至更長時間的延時。使用定時器/計數器延時從程式的執行效率和穩定性兩方面考慮都是最佳的方案。但應該注意,c51編寫的中斷服務程式編譯後會自動加上push acc、push psw、pop psw和pop acc語句,執行時占用了4個機器週期;如程式中還有計數值加1語句,則又會占用1個機器週期。這些語句所消耗的時間在計算定時初值時要考慮進去,從初值中減去以達到最小誤差的目的。
2 軟體延時與時間計算
在很多情況下,定時器/計數器經常被用作其他用途,這時候就只能用軟體方法延時。下面介紹幾種軟體延時的方法。資訊**"歲月聯盟"
2.1 短暫延時
資訊來自"歲月聯盟"
可以在c檔案中通過使用帶_nop_( )語句的函式實現,定義一系列不同的延時函式,如delay10us( )、delay25us( )、delay40us( )等存放在乙個自定義的c檔案中,需要時在主程式中直接呼叫。如延時10 μs的延時函式可編寫如下:
void delay10us( )
delay10us( )函式中共用了6個_nop_( )語句,每個語句執行時間為1 μs。主函式呼叫delay10us( )時,先執行乙個lcall指令(2 μs),然後執行6個_nop_( )語句(6 μs),最後執行了乙個ret指令(2 μs),所以執行上述函式時共需要10 μs。 可以把這一函式當作基本延時函式,在其他函式中呼叫,即巢狀呼叫/[4/],以實現較長時間的延時;但需要注意,如在delay40us( )中直接呼叫4次delay10us( )函式,得到的延時時間將是42 μs,而不是40 μs。這是因為執行delay40us( )時,先執行了一次lcall指令(2 μs),然後開始執行第乙個delay10us( ),執行完最後乙個delay10us( )時,直接返回到主程式。依此類推,如果是兩層巢狀呼叫,如在delay80us( )中兩次呼叫delay40us( ),則也要先執行一次lcall指令(2 μs),然後執行兩次delay40us( )函式(84 μs),所以,實際延時時間為86 μs。簡言之,只有最內層的函式執行ret指令。該指令直接返回到上級函式或主函式。如在delay80μs( )中直接呼叫8次delay10us( ),此時的延時時間為82 μs。通過修改基本延時函式和適當的組合呼叫,上述方法可以實現不同時間的延時。
微控制器基礎學習 延時程式
拿到微控制器第乙個程式肯定是驅動led燈,這裡便要用到延時函式。標準的c語言沒有空語句,要靠迴圈語句來實現延遲。下面是我看了別人的講解後,自己寫的一段 void delay ms 這是乙個延時500ms的程式,精確度很高,只是太單一。計算分析 程式共有三層迴圈 一層迴圈n r5 2 81 2 162...
51微控制器延時程式的理解
微控制器的基本時序與 組合語言 中講的一致,分為振盪週期,時鐘週期 狀態週期 機器週期,指令週期。晶振相當於提供給微控制器乙個基礎時鐘單元,在這個基礎上進行一系列電子元器件的動作。微控制器常見的晶振有12mhz,11.0592mhz,6mhz。t指令 1 4 t機器 6t時鐘 12t振盪 軟體實現 ...
微控制器中段程式 微控制器程式的存放
1 對於燒錄在微控制器裡面的程式,程式的 段,data段,bss段,rodata段等都存放在微控制器的flash中。當微控制器上電後,初始化彙編 將data段,bss段,複製到微控制器的ram中,並建立好堆疊,開始呼叫程式的main函式。以後,便有了程式儲存器和資料儲存器之分,程式執行時從flash...