發覺微控制器必用的 延時程式 詳細

2021-05-25 11:32:30 字數 2905 閱讀 3767

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...