在應用單片機編制各種程序時,經常會遇到實現精確延時的問題,時間從幾十微秒到幾秒,甚至更高的精度。單片機實現延時通常有兩種方法:一種是用定時器/計數器硬件延時,這種方法可以提高CPU的工作效率,也能做到精確延時,另一種是采用循環(huán)體進行軟件延時。
一、使用定時器/計數器
單片機系統(tǒng)若使用頻率為12MHz的晶振,一個機器周期為1μs,最長的延時時間可達2的16次方。在實際應用中,定時常采用中斷方式,如進行適當的循環(huán)可實現幾秒甚至更長時間的延時。使用定時器/計數器延時,從程序的執(zhí)行效率和穩(wěn)定性兩方面考慮,都是最佳的方案,但需要注意的是,用C51編寫的中斷服務程序,編譯后會自動加上PUSH ACC、PUSH PSW、POP PSW和POP ACC語句,執(zhí)行時將占用4個機器周期,如程序中還有計數值加1語句,則又會占用1個機器周期。這些語句所消耗的時間要從初值中減去,以達到最小誤差的目的。
二、使用軟件嵌套循環(huán)程序
在很多情況下,定時器/計數器經常被用作其他用途,這時候就只能用軟件方法延時。常用的軟件延時的方法有:
1. 短暫延時
通過使用帶_NOP_( )語句的函數實現,定義一系列不同的延時函數,如Delay10μs( )、Delay25μs( )等存放在一個自定義的文件中,需要時在主程序中直接調用。如延時10μs可編寫如下:
void Delay10μs ( ) {
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
}
上面函數中共用了6個_NOP_( )語句,每個語句執(zhí)行時間為1μs。主函數調用Delay 10μs( )時,先執(zhí)行一個LCALL指令(2 μs),然后執(zhí)行6個_NOP_( )語句(6μs),最后執(zhí)行了一個RET指令(2μs),所以執(zhí)行上述函數時共需要10μs??梢园堰@一函數當做基本延時函數,在其他函數中調用,即嵌套調用,以實現較長時間的延時。
2. C51中嵌套匯編程序段實現延時
在C51中通過嵌套匯編語言語句,實現多次循環(huán)達到延時的目的。例1:50ms 延時子程序:
DELAY:MOVR7,#200①
LOOP1:MOVR6,#125 ②
LOOP2:DJNZR6,L00P2③
DJNZR7,LOOP1④
RET⑤
精確延時時間為:1+(1×200)+(2×125×200)+(2×200)+2=(2×125+3)×200+3 =50603us≈50ms⑥
由⑥整理出公式:延時時間=(2×內循環(huán)+3)×外循環(huán)+3 ⑦
詳解:DELAY這個子程序共有五條指令,現在分別就每一條指令被執(zhí)行的次數和所耗時間進行分析。第一句:MOVR7,#200在整個子程序中只被執(zhí)行一次,且為單周期指令,所以耗時1us。第二句:MOVR6,#125從②看到④只要R7-1不為0,就會返回到這句,共執(zhí)行了R7次,共耗時200us。第三句:DJNZ R6,LOOP2,只要R6-1不為0,就反復執(zhí)行此句(內循環(huán)R6次),又受外循環(huán)R7控制,所以共執(zhí)行R6×R7次,因是雙周期指令,所以耗時2×R6×R7us。
例2:1秒延時子程序:
DELAY:MOV R7,#10 ①
LOOP1:MOV R6,#200②
LOOP2:MOV R5,#248③
DJNZ R5,$ ④
DJNZ R6,LOOP2 ⑤
DJNZ R7,LOOP1 ⑥
RET⑦
對每條指令進行計算得出精確延時時間為:1+(1×10)+(1×200×10)+(2×248×200×10)+(2×200×10)+(2×10)+2=[(2×248+3)×200+3]×10+3=998033us≈1s ⑧
由⑧整理得:延時時間=[(2×第一層循環(huán)+3)×第二層循環(huán)+3]×第三層循環(huán)+3 ⑨
此式適用三層循環(huán)以內的程序,也驗證了例1中式⑦(第三層循環(huán)相當于1)的成立。注意,要實現較長時間的延時,一般采用多重循環(huán),有時會在程序里加入NOP指令。
三、使用其他方法實現延時
如示波器、反匯編工具、性能分析器等確定延時時間。
四、總結
中職學生對單片機編程掌握較為薄弱。本文所介紹的多種實現并計算延時程序執(zhí)行時間的方法,使用定時器進行延時是最佳的選擇,可以提高MCU工作效率。編寫延時程序是一項很煩瑣的任務,需要多次修改才能滿足要求。
?。ê幽鲜〗洕芾韺W校)
注:“本文中所涉及到的圖表、公式、注解等請以PDF格式閱讀”