余巧書
摘 要:本文從實際應(yīng)用出發(fā),探討一種通用精確延時程序設(shè)計方法,并給出使用的詳細步驟,以便開發(fā)者能很好的理解和掌握。
關(guān)鍵詞:Keil C51;精確延時;C語言與匯編語言混合編程
單片機因具有體積小、功能強、成本低以及便于實現(xiàn)分布式控制而有非常廣泛的應(yīng)用領(lǐng)域。單片機開發(fā)者在編制各種應(yīng)用程序時經(jīng)常會遇到實現(xiàn)精確延時的問題。用匯編語言編制程序時,這種問題比較容易解決,而目前開發(fā)單片機應(yīng)用系統(tǒng)的主流工具為C語言。相對匯編語言來說,C語言有很多優(yōu)點,但缺點就是實時性沒有保證,因而在實時性要求高的場合,還需要匯編語言和C語言的聯(lián)合應(yīng)用。
使用C語言編寫單片機程序時,生成的機器代碼、代碼大小和效率,除了與C語言代碼本身有關(guān)外,還與編譯器有非常重要的關(guān)系。本文以Keil C51為例,探討如何編制通用精確的延時程序。為獲得通用精確的延時程序,可通過編譯器合理配置和優(yōu)化代碼編寫兩方面來達到目的。
一、模塊化編程
采用模塊化編程,將常用延時函數(shù)程序封裝為獨立模塊。項目中需要時僅需調(diào)用延時程序頭文件并將C語言源文件添加到項目中即可,便于修改和維護。同時模塊化也有利于在配置編譯器時有針對性對該模塊進行相應(yīng)配置。
二、合理配置編譯器
對于Keil C51編譯器來說,可以從“存儲器類型及存儲器模型、代碼優(yōu)化”兩方面來配置。
(一)存儲器類型
Keil C51編譯器提供對所有8051內(nèi)存區(qū)域的訪問。變量可以顯式地分配給特定的內(nèi)存空間(通過在聲明中包含存儲器類型說明符)或隱式地分配(基于存儲器模型)。
(二)存儲器模型
存儲器模型用于確定函數(shù)參數(shù)、自動變量和不包含顯式存儲器類型的聲明的默認存儲器類型。Keil C51編譯器提供三種存儲器模型。
Keil C51編譯器在CPU寄存器中最多可傳遞三個函數(shù)自變量。參數(shù)的傳遞可通過“REGPARMS”和“NOREGPARMS”控制命令進行控制。如果沒有寄存器可用于參數(shù)傳遞或包含的參數(shù)太多,使用固定存儲器位置傳遞超出部分的參數(shù)。
(三)代碼優(yōu)化
Keil C51編譯器提供了多層次、多種類的優(yōu)化配置,高級別優(yōu)化包含低級別優(yōu)化。優(yōu)化配置作用范圍有項目級(全局)、文件級(私有)和函數(shù)級(私有)。優(yōu)化設(shè)置包括優(yōu)化級別(用數(shù)字表示,數(shù)字越大級別越高)和優(yōu)化偏好(關(guān)鍵字為“SIZE”和“SPEED”)。
項目級優(yōu)化可在項目選項的“C51”標簽中進行配置,具有全局性,若項目中的文件或函數(shù)沒有進行單獨優(yōu)化配置,則繼承項目級優(yōu)化。
文件級優(yōu)化可在該文件選項的“C51”標簽中進行配置,配置后不受項目級優(yōu)化的影響;若選擇“Default”表示文件繼承項目級優(yōu)化。另外,也可以在文件的頭部使用“#pragma OPTIMIZE(9,SPEED)”指定文件級優(yōu)化。
函數(shù)級優(yōu)化是在函數(shù)前使用“#pragma OT(9,SPEED)”指定函數(shù)的優(yōu)化。
三、優(yōu)化代碼編寫
對于短暫延時(通常10微秒以下),可以直接調(diào)用Keil C51頭文件“Intrins.h”,使用“_nop_();”函數(shù)獲得一個機器周期的延時時間。
為保證延時的精確性,代碼采用匯編語言編寫,這樣每一條指令都有固定的機器周期。為了使延時程序具有一定的通用性和使用方便,采用C語言函數(shù)封裝。在Keil C51中通過預(yù)處理指令“#pragma asm”和“#pragma endasm”可以嵌套匯編語言語句。也可以采用“__asm”進行匯編的嵌入。為計算延時時間方便,函數(shù)參數(shù)數(shù)據(jù)類型選擇“unsigned char”。
四、程序編寫范例
五、仿真及實踐檢驗
使用Proteus進行仿真,編寫測試程序如下:
對測試程序進行反匯編,從匯編代碼中可以看出,測試程序IO端口電平的變化時間比延時時間多了3個機器周期(測試程序本身引入的時間),即一個脈沖周期多了6個機器周期時間。
使用高精度示波器測量脈沖周期為206微秒,延時時間實際為(206微秒-6微秒),誤差為0,符合設(shè)計預(yù)期目的。
六、歸納總結(jié)
保障延時程序延時精確性和程序的通用性的關(guān)鍵:
(1)采用模塊化編程并指定模塊私有優(yōu)化級,不受編譯器全局優(yōu)化級影響;
(2)指定變量、函數(shù)存儲模式,避免因編譯器編譯模式影響;
(3)延時程序核心采用匯編語言編寫,每條指令有確定的指令周期;
(4)為保證程序通用、方便性,采用C語言函數(shù)封裝。