微控制器彙編延時程式的理解
微控制器彙編實現延遲的程式程式碼:
DELAY: MOV R7,#250 ;
D1: MOV R6,#250 ;
D2: DJNZ R6,D2 ;
DJNZ R7,D1 ;
RET
如果用高階語言程式設計,只需要簡單地呼叫延時函式就可以實現,但是計算機具體是怎麼實現的呢?要想知其所以然,還得從彙編開始學起。
冒號前面的“DELAY”、“D1”、“D2”為語句行的名字,是為了程式的條件語句跳轉用的,分號後面為註釋,計算機執行時將過濾掉這些資訊,最大限度減少程式碼長度,提高效率。
DELAY: MOV R7,#250 ; 名字為“DELAY”的語句:意思是將CPU內部記憶體RAM的R7位置填寫為250(原來為0,為什麼是0呢?因為任何程式開始執行前都要復位,就像我們打算盤要將運算元復位一樣,或者我們用沙盤寫字,要將沙盤抹平類似)
D1: MOV R6,#250 ; 名字為“D1”的語句:將R6位置填寫為250
D2: DJNZ R6,D2 ; 名字為“D2”的語句:將R6位置的250減1,如果為0就繼續執行下一條,不為0就繼續執行D2這一句,因為R6=250,所以這個語句要原地踏步執行250次!
DJNZ R7,D1 ; 這句沒有名字,因為沒有別的語句要跳到這裡,所以就省略了。R7同樣等於250,但它不是原地踏步,而是跳回了D1,這麼幹,D!、D2和本句將被迴圈執行250遍,需要強調的是:D2語句自身每次都要執行250遍,也就是執行了250*250=62500遍!
RET ;子程式結束(因為延時程式一般不作為獨立程式存在,它只是一個子程式,也就是高階語言中的一個函式,看到這個字元,子程式將跳回到母程式,進行下一步)。
這個子程式這麼反覆地迴圈指令,到底有什麼意義呢?又是怎麼實現的延時程式呢?說起來計算機真是有點笨,它是*數程式執行的次數來累加時間的!也就是說語句本身就是為了浪費時間!哈哈,可笑吧?這就像你沒有鐘錶,但是你知道你跑操場一圈是一分鐘,然後就繞著操場跑了60圈,時間過了正好一小時一樣。
如果是人的話,誰也不會笨到幹這麼累的活兒來計時,但計算機不一樣,它不論靜止還是運動,程式總是一拍一拍地執行著,所以它不累。
那麼,計算機執行一個語句耗費的時間是多少呢?
以51型微控制器為例:如果採用12MHz的晶振,執行一個機器週期為1微秒,具體為什麼暫時不管。微控制器的指令系統分為單週期、雙週期和三週期指令(三週期實際上佔用四個週期,多餘一個週期浪費掉),這是有指令的內容決定的,內容多的單週期執行不完,肯定要延長了。子程式裡面的MOV是單週期、DJNZ是雙週期。
這樣,我們就可以算算這個子程式累計進行了多少個週期,然後乘以1微秒,就算出它佔用的時間,也就是延時的時長了!
第一句:DELAY: MOV R7,#250 ;執行了一次,沒有任何語句跳轉給它,單週期。1
第二句:D1: MOV R6,#250 ;執行了250次,全部是第四句跳過來的,單週期。250
第三句:D2: DJNZ R6,D2 ;原地執行了250次,從第二句順延(第二句執行完,沒有其它跳轉的話肯定要執行第三句)過來250次,也就是250*250=62500次,雙週期*2。125000
第四句:DJNZ R7,D1 ; 從第三句順延過來250次,雙週期*2。500
總計:1+250+125000+500=1257501次,乘以1微秒,換算約為0.13秒。
我們可以通過調整R6、R7的數值來調整延時的長度。事實上,8位計算機中,R6之類的工作暫存器地址最大隻能放下255的十進位制數值,因此要通過上述程式達到更長的延時是辦不到的。
那怎麼辦呢?
我們可以再增加一個R4,讓上述的程式最多可以迴圈255遍,這樣,0.13秒的200多倍就是30秒上下了,不夠的話再增加迴圈,又可以擴大200多倍,當然,工作暫存器的數量是有限的,因此這個延時程式也是有限的,如果還不夠用怎麼辦呢,就目前我所學的知識,只能在母程式裡面設定迴圈了,也就是讓這個子程式在母程式裡面繼續迴圈......