微控制器C51學習心得_02
阿新 • • 發佈:2019-02-06
開發系統基本知識
Keil C51是美國Keil Software公司出品的51系列相容微控制器C語言軟體開發系統,與彙編相比,C語言在功能上、結構性、可讀性、可維護性上有明顯的優勢,因而易學易用。用過組合語言後再使用C來開發,體會更加深刻。
Keil C51軟體提供豐富的庫函式和功能強大的整合開發除錯工具,全Windows介面。另外重要的一點,只要看一下編譯後生成的彙編程式碼,就能體會到Keil C51生成的目的碼效率非常之高,多數語句生成的彙編程式碼很緊湊,容易理解。在開發大型軟體時更能體現高階語言的優勢。
下面詳細介紹Keil C51開發系統各部分功能和使用。
C51工具包的整體結構,如圖(1)所示,其中uVision與Ishell分別是C51 for Windows和for Dos的整合開發環境(IDE),可以完成編輯、編譯、連線、除錯、模擬等整個開發流程。開發人員可用IDE本身或其它編輯器編輯C或彙編原始檔。然後分別由C51及A51編譯器編譯生成目標檔案(.OBJ)。目標檔案可由LIB51建立生成庫檔案,也可以與庫檔案一起經L51連線定位生成絕對目標檔案(.ABS)。ABS檔案由OH51轉換成標準的Hex檔案,以供偵錯程式dScope51或tScope51使用進行原始碼級除錯,也可由模擬器使用直接對目標板進行除錯,也可以直接寫入程式存貯器如EPROM中。
在Windows下直接執行軟體包中DOS/C51DOS.exe然後選擇安裝目錄即可。完畢後欲使系統正常工作須進行以下操作(設C:/C51為安裝目錄):
修改Autoexec.bat,加入
path=C:/C51/Bin
Set C51LIB=C:/C51/LIB
Set C51INC=C:/C51/INC
然後執行Autoexec.bat
在Windows下執行軟體包中WIN/Setup.exe,最好選擇安裝目錄與C51 for Dos相同,這樣設定最簡單(設安裝於C:/C51目錄下)。然後將軟體包中crack目錄中的檔案拷入C:/C51/Bin目錄下。
(1) C51
C51是C語言編譯器,其使用方法為:
C51 sourcefile[編譯控制指令]
或者
C51 @ commandfile
其中sourcefile為C原始檔(.C)。大量的編譯控制指令完成C51編譯器的全部功能。包控C51輸出檔案C.LST,.OBJ,.I和.SRC檔案的控制。原始檔(.C)的控制等,詳見第五部分的具體介紹。
而Commandfile為一個連線控制檔案其內容包括:.C原始檔及各編譯控制指令,它沒有固定的名字,開發人員可根據自己的習慣指定,它適於用控制指令較多的場合。
(2) A51
A51是組合語言編譯器,使用方法為:
A51 sourcefile[編譯控制指令]
或A51 @ commandfile
其中sourcefile為彙編原始檔(.asm或.a51),而編譯控制指令的使用與其它彙編如ASM語言類似,可參考其他組合語言材料。
Commandfile同C51中的Commandfile類似,它使A51使用和修改方便。
(1) L51
L51是Keil C51軟體包提供的連線/定位器,其功能是將編譯生成的OBJ檔案與庫檔案連線定位生成絕對目標檔案(.ABS),其使用方法為:
L51 目標檔案列表[庫檔案列表] [to outputfile] [連線控制指令]
或 L51 @Commandfile
源程式的多個模組分別經C51與A51編譯後生成多個OBJ檔案,連線時,這些檔案全列於目標檔案列表中,作為輸入檔案,如果還需與庫檔案(.LiB)相連線,則庫檔案也必須列在其後。outputfile為輸檔名,缺少時為第一模組名,字尾為.ABS。連線控制指令提供了連線定位時的所有控制功能。Commandfile為連線控制檔案,其具體內容是包括了目標檔案列表,庫檔案列表及輸出檔案、連線控制命令,以取代第一種繁瑣的格式,由於目標模組庫檔案大多不止1個,因而第2種方法較多見,這個檔名字也可由使用者隨意指定。
(2) Bl51
BL51也是C51軟體包的連線/定位器,其具有L51的所有功能,此外它還具有以下3點特別之處:
a. 可以連線定位大於64kBytes的程式。
b. 具有程式碼域及域切換功能(CodeBanking & Bank Switching)
c. 可用於RTX51作業系統
RTX51是一個實時多工作業系統,它改變了傳統的程式設計模式,甚至不必用main( )函式,微控制器系統軟體向RTOS發展是一種趨勢,這種趨勢對於186和386及68K系列CPU更為明顯和必須,對8051因CPU較為簡單,程式結構等都不太複雜,RTX51作用顯得不太突出,其專業版軟體PK51軟體包甚至不包括RTX51Full,而只有一個RTX51TINY版本的RTOS。RTX51 TINY適用於無外部RAM的微控制器系統,因而可用面很窄,在本文中不作介紹。Bank switching技術因使用很少也不作介紹。
(1) dScope51
dScope51是一個源級偵錯程式和模擬器,它可以除錯由C51編譯器、A51彙編器、PL/M-51編譯器及ASM-51彙編器產生的程式。它不需目標板(for windows也可通過mon51接目標板),只能進行軟體模擬,但其功能強大,可模擬CPU及其外圍器件,如內部串列埠,外部I/O及定時器等,能對嵌入式軟體功能進行有效測試。
其使用方法為:
DS51[debugfile][INIT(initfile)]
其中debugfile是一個Hex格式的8051檔案,即待除錯的檔案其為可選的,可在進入dScope51後用load命令裝入。
Initfile為一個初使化檔案,它在啟動dScope51後,在debugfile裝入前裝入,裝有一些dScope的初使化引數及常用除錯函式等。下面是一個dScope.ini檔案(for dos)的內容:
Load ../../ds51/8051.iof
Map 0,0xffff
dScope51 for Windows則直接用滑鼠進入,然後用load裝入待調檔案。
(2) tScope51
與dScope51不同的是Scope51必須帶目標板,目前它可以通過兩種方式訪問目標板。(1) 通過EMul51線上模擬器,tScope51為該模擬器準備了一個動態連線檔案EMUL51.IOT,但該方法必須配合該模擬器。(2) 通過Monitov51監控程式,這種方法是可行的,tScope51為訪問Monitor51專門帶有MON51.IOT連線程式,使用時可通過串列埠及監控程式來除錯目標板。
其使用方法為:
TS51[INIT(file_name.ini)]
其中file_name.ini為一個初使化檔案。
進入TS51後,必須裝入IOT檔案,可用的有MON51.IOT及EMUL51.IOT兩種,如裝入MON51.IOT:
Load.C:/C51/TS51/MON51.IOT CPUTYPE(80517)
可惜的是tScope51只有for Dos的版本。
(3) Monitor 51
Monitor51是一個監控程式通過PC機的串列埠與目標板進行通訊,Monitor操作需要MON51或dScope51 for Windows,後面部分將對Monitor51做較為詳細的介紹。
(1) Ishell for Dos
這是一個for Dos的IDE,直接在命令列鍵入Ishell,則進入該環境,它使用簡單方便。其命令列與DOS命令列具有同樣的功能,對單模組的Project直接由選單進行編譯連線,對多模組的project。則通過批處理,BAT檔案進行編譯連線,然後通過選單控制由dScope51或tScope51對程式進行除錯,因為是for dos的,不做太詳細介紹。
(2) uVision for Windows
uVision for Windows是一個標準的Windows應用程式,它是C51的一個整合軟體開發平臺,具有原始碼編輯、project管理、整合的make等功能,它的人機介面友好,操作方便,是開發者的首選,具體配置及使用見第五部分。
[dvnews_page=第二章 Keil C51軟體使用詳解 ]
C51編譯器的控制指令分為三類:原始檔控制類,目標檔案控制類及列表控制類。
NOEXTEND:C51原始檔不允許使用ANSI C擴充套件功能。
DEFINE(DF):定義預處理(在C51命令列)。
COMPACT LARGE SMALL 選編譯模式
DEBUG(DB) 包含除錯資訊,以供模擬器或dSCope51使用。
NOAMAKE(NOAM) 禁止AutoMake資訊記錄
NOREGPARMS 禁止用暫存器傳遞引數
OBJECTEXTEND(OE) Object檔案包含附加變數型別資訊
OPTIMIZE(OT) 指定優化級別
REGFILE(RF) 指定一個暫存器使用的檔案以供整體優化用
REGISTERBANK(RB) 指定一個供絕對暫存器訪問的暫存器區名
SRC 不生成目標檔案只生成彙編原始檔
其它控制元件不常用。
CODE(CD):向列表檔案加入彙編列表
LISTINCLUDE(LC):顯示indude檔案
SYMBOLS(SB):列表檔案包括模組內所有符號的列表
WARNINGLEVEL(WL):選擇“警告”級別
[dvnews_page=第二節 dScope51的使用]
總的來說dScope51具有以下特性:
l 高階語言顯示模式
l 整合硬體環境模擬
l 單步或“GO”執行模式
l 儲存器、暫存器及變數訪問
l Watch表示式之值
l 函式與訊號功能
下面,具體說明在進入dScope51 for Dos之後,如何實現上述功能,dScope51採用下拉選單格式和視窗顯示控制,共有language、serial、exe、register四個視窗,其中exe為命令列視窗,language為程式視窗,serial為串列埠窗,register為暫存器窗。
(1) 高階語言顯示模式
單擊主選單中的“View”,第一欄中的三條命令“Highlevel”、“Mixed”、“Assembly”分別對所裝入的程式按照“高階”、“混合級”及“彙編級”三種方式顯示,以方便除錯使用。
(2) 整合硬體環境模擬顯示
主選單中“Peripheral”各條能顯示模擬硬體環境的狀態,其中:
i/o Port:顯示各I/O口之值,對8031而言SFR中的P1、P2、P3、P0與引腳之值分別列出:
Interrupt:顯示5箇中斷源的入口模式是否允許,優先順序等中斷狀態。
Timer:顯示各定時/計數器的模式,初始值狀態等。
int Message:中斷資訊允許,如為允許(“>>”出現),則當中斷申請時,顯示中斷源資訊。比如當中斷髮生時會顯示:
“interrupt Timer 0 occured”等
A/D converter:
顯示A/D轉換器狀態無時,則提示“無”。
Serial:串列埠資訊顯示,包括串列埠模式、波特產等
Other:其它器件,如為8031則顯示“ 無”
(3) 單步或“Go”執行
“F8”單步執行,“F5”全速執行到斷點。或選主選單中Trace單步執行CPU中的Go全速執行。
(4) 儲存器暫存器及變數訪問
外部儲存器管理MAP選單:設定(set)、取消(reset)、顯示(Display)處理可用儲存空間。
修改Code程式碼:ASM命令
儲存器顯示命令:D 類別為(X、D、I、B、C)
修改儲存器命令:E 有以下幾種命令EB、EC、EI、EL、EF、EP
複雜資料型別顯示:Object命令;用以顯示結構或陣列的內容。欲使此命令有效,C51編譯器必須有DB及OBJECTEXTEND兩條。
反彙編命令:U
(5) “Watch”表示式之值
在View選單的“Watch”一欄中有四項:其中包括定義Watch Point(Define)、刪除Watch Point(remove,kill all),及自動更新選項。
也可用WS、WK等命令代替,下面具體看“表示式”型別:
dScope51一次最多可設16個WtchPoint表示式,顯示於Watch Window之中,表示式可以是簡單變數,也可是複雜資料型別如結構、陣列和指向結構的指標等,例如:
>WS *ptime
>WS ptime→hour
>WS some_record[o],analog等等
(6) 關於.IOF檔案
啟動DS51後必須裝入.IOF檔案才能使CPU及Peripheral各項起作用,這個函式的使用是依據8051系列CPU的不同特點,裝入8051各CPU硬體裝置模擬驅動檔案,比如8031CPU就必須load DS51目錄下的8051.IOF。
dScope for windows具有dScope for dos的全部功能,此外,它還具有以下明顯的優點:
(1) 標準的Windows介面,操作更容易更簡單;
(2) 常用操作多用對話方塊,而非Dos的行命令方式;
(3) 視窗資源更加豐富:儲存器視窗、覆蓋率分析、執行狀態分析視窗,加強了除錯功能;
因為dScope for Windows功能強大,具體操作在第八章詳細介紹。
[dvnews_page=第三節 Monitor51及其使用 ]
(1) 硬體系統為51系列CPU;
(2) 帶5K外部程式儲存器(從O地址開始),存放Monitor51程式;
(3) 256Bytes的外部資料儲存器以及5K的跟蹤緩衝區,此外,外部資料儲存器必須足夠容納所有應用程式程式碼及資料,且所有外部資料儲存器必須為馮·諾伊曼儲存器,即能一致訪問XDATA與Code空間。
(4) 一個定時器作為波特率發生器供串列埠使用;
(5) 6 Bytes的空餘堆疊。
Mon51的使用途徑有三種方式:
(1) Dos行命令方式
即先用install對MON51進行配置,然後用MON51進入Monitor狀態,啟用各種命令對Monitor51進行除錯。
(2) tScope51方式
啟動tScope51裝入TS51目錄下的MON51.IOT驅動檔案,與目標板通訊。
(3) dScope51 for Windows方式
在選CPU驅動檔案時,選“MON51.dll”,則檢查目標板並進入MON51狀態。
(1) MON51 for Dos的配置
執行install檔案(在MON51目錄下),不同的引數可以配置不同的硬體環境。INSTALL Serialtype [xdstastart[codestart[bank][PROMCHECK]]],具體說明見MON51幫助檔案或使用手冊。
(2) MON51 for Windows的配置
在啟用MON51.dll時,會使得系統自動檢查目標板連線,如配置不對,則彈出“Configuration”對話方塊,設定PC串列埠,波特率等,完畢單擊“apply”有效。
收發交叉互連,RTS、CTS直連,DSR、DTR直連,具體引腳排列參考串列埠資料。
詳細的MON51命令可參閱幫助。
[dvnews_page=第四節 整合開發環境(IDE)的使用 ]
進入Ishell之後看到兩個視窗:一個是檔案視窗,一個是Dos命令列視窗,視窗上方是下拉式的命令選單,其中的Files控制檔案視窗的顯隱。
使用Ishell,第一步就是配置系統,即要學習兩個檔案的修改與建立:
(1) Ishell.CFG檔案
每一個project都有一個Ishell.CFG,其中存放有“Option選單和Setup選單下的部分資訊;Bell enabled、Monochrome enabled、Editor Selected、CRT Lines、target enviroment、name of user edit、Automatic load for configuration enabled、file window enabled、file specification for file window、translate command line controls、project name等。
對每個project都必須設定以上資訊,然後存檔“setup”的的“save”,這樣才可正式開始下面工作。
(2) IShell.col檔案
對IDE顏色設定,如不改動,可以預設為主。
(3) CDF檔案
該檔案位於BIN目錄下,每一檔案定義一組外部函式工具包,即定義外部環境如8051.CDF,USER.CDF等,開發者可修改CDF檔案,供自己使用,至於CDF檔案內容可檢視一下8051.CDF即可知道。注意.CDF檔案是Ishell系統的核心所在,不同的CDF檔案可使本IDE適用於不同的編譯、連線系統,即本IDE並不僅適於C51。
下面談一談Automake工具:
C51的Automake是一個project管理器,在8051工具包中以OBJECT檔案形式保留了一個project的資訊,AutoMake用這些資訊來進行project管理,一旦手工建立一個project,Automake可生成一個新的OBJECT,AutoMake利用此檔案來編譯那些修改過的檔案。
Automake支援C51、A51、L51/BL51、C166、A166、L166等編譯聯結器。點中主選單中的Automake即執行本工具。
Ishell for Dos使用比較繁瑣,推薦使用uVision for windows。
uVision是一個標準的windows應用程式,其編譯功能、檔案處理功能、project處理功能、視窗功能以及工具引用功能(如A51、C51、PL/M41、BL51 dScope等)等都較Ishell for Dos要強得多。
uVision採用BL51作聯結器,因為BL51相容L51,所以一切能在Dos下工作的project都可以到uVision中進行連線除錯。
uVision採用dScope for windows作偵錯程式,該偵錯程式支援MON51及系統模擬兩種方式,功能較for DOS要強大好用,除錯功能強大。
注意:
(1) Option選單下的各項要會使用,其中A51、C51、PL/M51、BL51定義各檔案所使用的編譯、連線控制指令,dScope定義一個dScope初始化檔案。Make則是定義一個make檔案。
(2) 進入除錯是在RUN選單下執行dScope。
(3) project中包括新建、開啟、修改、更新、編譯、連線等poject處理,具體使用可參考後面的例子。
[dvnews_page=第三章 Keil C51 vs 標準C ]
深入理解並應用C51對標準ANSIC的擴充套件是學習C51的關鍵之一。因為大多數擴充套件功能都是直接針對8051系列CPU硬體的。大致有以下8類:
l 8051儲存型別及儲存區域
l 儲存模式
l 儲存器型別宣告
l 變數型別宣告
l 位變數與位定址
l 特殊功能暫存器(SFR)
l C51指標
l 函式屬性
具體說明如下(8031為預設CPU)。
C51 V4.0版本有以下擴充套件關鍵字(共19個):
_at_ idata sfr16 alien interrupt small
bdata large _task_ Code bit pdata
using reentrant xdata compact sbit data sfr
[dvnews_page=第三節 儲存模式]
儲存模式決定了沒有明確指定儲存型別的變數,函式引數等的預設儲存區域,共三種:
所有預設變數引數均裝入內部RAM,優點是訪問速度快,缺點是空間有限,只適用於小程式。
所有預設變數均位於外部RAM區的一頁(256Bytes),具體哪一頁可由P2口指定,在STARTUP.A51檔案中說明,也可用pdata指定,優點是空間較Small為寬裕速度較Small慢,較large要快,是一種中間狀態。
所有預設變數可放在多達64KB的外部RAM區,優點是空間大,可存變數多,缺點是速度較慢。
提示:儲存模式在C51編譯器選項中選擇。
[dvnews_page=第三節 儲存模式]
儲存模式決定了沒有明確指定儲存型別的變數,函式引數等的預設儲存區域,共三種:
所有預設變數引數均裝入內部RAM,優點是訪問速度快,缺點是空間有限,只適用於小程式。
所有預設變數均位於外部RAM區的一頁(256Bytes),具體哪一頁可由P2口指定,在STARTUP.A51檔案中說明,也可用pdata指定,優點是空間較Small為寬裕速度較Small慢,較large要快,是一種中間狀態。
所有預設變數可放在多達64KB的外部RAM區,優點是空間大,可存變數多,缺點是速度較慢。
提示:儲存模式在C51編譯器選項中選擇
[dvnews_page=第七節 Keil C51指標]
C51支援一般指標(Generic Pointer)和儲存器指標(Memory_Specific Pointer).
一般指標的宣告和使用均與標準C相同,不過同時還可以說明指標的儲存型別,例如:
long * state;為一個指向long型整數的指標,而state本身則依儲存模式存放。
char * xdata ptr;ptr為一個指向char資料的指標,而ptr本身放於外部RAM區,以上的long,char等指標指向的資料可存放於任何儲存器中。
一般指標本身用3個位元組存放,分別為儲存器型別,高位偏移,低位偏移量。
基於儲存器的指標說明時即指定了存貯型別,例如:
char data * str;str指向data區中char型資料
int xdata * pow; pow指向外部RAM的int型整數。
這種指標存放時,只需一個位元組或2個位元組就夠了,因為只需存放偏移量。
即指標在上兩種型別之間轉化:
l 當基於儲存器的指標作為一個實參傳遞給需要一般指標的函式時,指標自動轉化。
l 如果不說明外部函式原形,基於儲存器的指標自動轉化為一般指標,導致錯誤,因而請用“#include”說明所有函式原形。
l 可以強行改變指標型別。
[dvnews_page=第八節 Keil C51函式]
C51函式宣告對ANSI C作了擴充套件,具體包括:
中斷宣告方法如下:
void serial_ISR () interrupt 4 [using 1]
{
/* ISR */
}
為提高程式碼的容錯能力,在沒用到的中斷入口處生成iret語句,定義沒用到的中斷。
/* define not used interrupt, so generate "IRET" in their entrance */
void extern0_ISR() interrupt 0{} /* not used */
void timer0_ISR () interrupt 1{} /* not used */
void extern1_ISR() interrupt 2{} /* not used */
void timer1_ISR () interrupt 3{} /* not used */
void serial_ISR () interrupt 4{} /* not used */
由small compact 及large說明,例如:
void fun1(void) small { }
提示:small說明的函式內部變數全部使用內部RAM。關鍵的經常性的耗時的地方可以這樣宣告,以提高執行速度。
在函式前宣告,只對一個函式有效。該函式呼叫過程中將不可被中斷。
在主程式和中斷中都可呼叫的函式,容易產生問題。因為51和PC不同,PC使用堆疊傳遞引數,且靜態變數以外的內部變數都在堆疊中;而51一般使用暫存器傳遞引數,內部變數一般在RAM中,函式重入時會破壞上次呼叫的資料。可以用以下兩種方法解決函式重入:
a、在相應的函式前使用前述“#pragma disable”宣告,即只允許主程式或中斷之一呼叫該函式;
b、將該函式說明為可重入的。如下:
void func(param...) reentrant;
KeilC51編譯後將生成一個可重入變數堆疊,然後就可以模擬通過堆疊傳遞變數的方法。
由於一般可重入函式由主程式和中斷呼叫,所以通常中斷使用與主程式不同的R暫存器組。
另外,對可重入函式,在相應的函式前面加上開關“#pragma noaregs”,以禁止編譯器使用絕對暫存器定址,可生成不依賴於暫存器組的程式碼。
由alien指定。
[dvnews_page=第四章 Keil C51高階程式設計]
本章討論以下內容:
l 絕對地址訪問
l C與彙編的介面
l C51軟體包中的通用檔案
l 段名轉換與程式優化
C51提供了三種訪問絕對地址的方法:
在程式中,用“#include<absacc.h>”即可使用其中定義的巨集來訪問絕對地址,包括:
CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD
具體使用可看一看absacc.h便知
例如:
rval=CBYTE[0x0002];指向程式存貯器的0002h地址
rval=XWORD [0x0002];指向外RAM的0004h地址
直接在資料定義後加上_at_ const即可,但是注意:
(1)絕對變數不能被初使化;
(2)bit型函式及變數不能用_at_指定。
例如:
idata struct link list _at_ 0x40;指定list結構從40h開始。
xdata char text[25b] _at_0xE000;指定text陣列從0E000H開始
提示:如果外部絕對變數是I/O埠等可自行變化資料,需要使用volatile關鍵字進行描述,請參考absacc.h。
此法是利用連線控制指令code xdata pdata /data bdata對“段”地址進行,如要指定某具體變數地址,則很有侷限性,不作詳細討論。
方法是用#pragma語句具體結構是:
#pragma asm
彙編行
#pragma endasm
這種方法實質是通過asm與ndasm告訴C51編譯器中間行不用編譯為彙編行,因而在編譯控制指令中有SRC以控制將這些不用編譯的行存入其中。
C模組與彙編模組的介面較簡單,分別用C51與A51對原始檔進行編譯,然後用L51將obj檔案連線即可,關鍵問題在於C函式與彙編函式之間的引數傳遞問題,C51中有兩種引數傳遞方法。
(1) 通過暫存器傳遞函式引數
最多隻能有3個引數通過暫存器傳遞,規律如下表:
引數數目
char
int
long,float
一般指標
1
2
3
R7
R5
R3
R6 & R7
R4 & R5
R2 & R3
R4~R7
R4~R7
R1~R3
R1~R3
R1~R3
(2) 通過固定儲存區傳遞(fixed memory)
這種方法將bit型引數傳給一個儲存段中:
?function_name?BIT
將其它型別引數均傳給下面的段:?function_name?BYTE,且按照預選順序存放。
至於這個固定儲存區本身在何處,則由儲存模式預設。
(3) 函式的返回值
函式返回值一律放於暫存器中,有如下規律:
return type
Registev
說明
bit
標誌位
由具體標誌位返回
char/unsigned char 1_byte指標
R7
單位元組由R7返回
int/unsigned int 2_byte指標
R6 & R7
雙位元組由R6和R7返回,MSB在R6
long&unsigned long
R4~R7
MSB在R4, LSB在R7
float
R4~R7
32Bit IEEE格式
一般指標
R1~R3
儲存型別在R3 高位R2 低R1
(4) SRC控制
該控制指令將C檔案編譯生成彙編檔案(.SRC),該彙編檔案可改名後,生成彙編.ASM檔案,再用A51進行編譯。
在C51/LiB目錄下有幾個C原始檔,這幾個C原始檔有非常重要的作用,對它們稍事修改,就可以用在自己的專用系統中。
init_mem.C:此檔案是初始化動態記憶體區的程式原始碼。它可以指定動態記憶體的位置及大小,只有使用了init_mem( )才可以調回其它函式,諸如malloc calloc,realloc等。
calloc.c:此檔案是給陣列分配記憶體的原始碼,它可以指定單位資料型別及該單元數目。
malloc.c:此檔案是malloc的原始碼,分配一段固定大小的記憶體。
realloc.c:此檔案是realloc.c原始碼,其功能是調整當前分配動態記憶體的大小。
啟動檔案STARTUP.A51中包含目標板啟動程式碼,可在每個project中加入這個檔案,只要復位,則該檔案立即執行,其功能包括:
l 定義內部RAM大小、外部RAM大小、可重入堆疊位置
l 清除內部、外部或者以此頁為單元的外部儲存器
l 按儲存模式初使化重入堆疊及堆疊指標
l 初始化8051硬體堆疊指標
l 向main( )函式交權
開發人員可修改以下資料從而對系統初始化
常數名 意義
IDATALEN 待清內部RAM長度
XDATA START 指定待清外部RAM起始地址
XDATALEN 待清外部RAM長度
IBPSTACK 是否小模式重入堆疊指標需初始化標誌,1為需要。預設為0
IBPSTACKTOP 指定小模式重入堆疊頂部地址
XBPSTACK 是否大模式重入堆疊指標需初始化標誌,預設為0
XBPSTACKTOP 指定大模式重入堆疊頂部地址
PBPSTACK 是否Compact重入堆疊指標,需初始化標誌,預設為0
PBPSTACKTOP 指定Compact模式重入堆疊頂部地址
PPAGEENABLE P2初始化允許開關
PPAGE 指定P2值
PDATASTART 待清外部RAM頁首址
PDATALEN 待清外部RAM頁長度
提示:如果要初始化P2作為緊湊模式高階地址,必須:PPAGEENAGLE=1,PPAGE為P2值,例如指定某頁1000H-10FFH,則PPAGE=10H,而且連線時必須如下:
L51<input modules> PDATA(1080H),其中1080H是1000H-10FFH中的任一個值。
以下是STARTUP.A51程式碼片斷,紅色是經常可能需要修改的地方:
;------------------------------------------------------------------------------
; This file is part of the C51 Compiler package
; Copyright KEIL ELEKTRONIK GmbH 1990
;------------------------------------------------------------------------------
; STARTUP.A51: This code is executed after processor reset.
;
; To translate this file use A51 with the following invocation:
;
; A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the following
; L51 invocation:
;
; L51 <your object file list>, STARTUP.OBJ <controls>
;
;------------------------------------------------------------------------------
;
; User-defined Power-On Initialization of Memory
;
; With the following EQU statements the initialization of memory
; at processor reset can be defined:
;
; ; the absolute start-address of IDATA memory is always 0
IDATALEN EQU 80H ; the length of IDATA memory in bytes.
;
XDATASTART EQU 0H ; the absolute start-address of XDATA memory
XDATALEN EQU 0H ; the length of XDATA memory in bytes.
;
PDATASTART EQU 0H ; the absolute start-address of PDATA memory
PDATALEN EQU 0H ; the length of PDATA memory in bytes.
;
; Notes: The IDATA space overlaps physically the DATA and BIT areas of the
; 8051 CPU. At minimum the memory space occupied from the C51
; run-time routines must be set to zero.
;------------------------------------------------------------------------------
;
; Reentrant Stack Initilization
;
; The following EQU statements define the stack pointer for reentrant
; functions and initialized it:
;
; Stack Space for reentrant functions in the SMALL model.
IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.
;
; Stack Space for reentrant functions in the LARGE model.
XBPSTACK EQU 0 ; set to 1 if large reentrant is used.
XBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
;
; Stack Space for reentrant functions in the COMPACT model.
PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
PBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
;
;------------------------------------------------------------------------------
;
; Page Definition for Using the Compact Model with 64 KByte xdata RAM
;
; The following EQU statements define the xdata page used for pdata
; variables. The EQU PPAGE must conform with the PPAGE control used
; in the linker invocation.
;
PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
PPAGE EQU 0 ; define PPAGE number.
;
;------------------------------------------------------------------------------
putchar.c
putchar.c是一個低階字元輸出子程,開發人員可修改後應用到自己的硬體系統上,例如向CLD或LEN輸出字元。
預設:putchar.c是向串列埠輸出一個字元XON|XOFF是流控標誌,換行符“/*n”自動轉化為回車/換行“/r/n”。
getkey.c
getkey函式是一個低階字元輸入子程,該程式可用到自己硬體系統,如矩陣鍵盤輸入中,預設時通過串列埠輸入字元。
還包括對Watch-Dog有獨特功能的INIT.A51函式以及對8×C751適用的函式,可參考原始碼。
C51編譯器生成的目標檔案存放於許多段中,這些段是程式碼空間或資料空間的一些單元,一個段可以是可重定位的,也可以是絕對段,每一個可重定位的段都有一個型別和名字,C51段名有以下規定:
每個段名包括字首與模組名兩部分,字首表示儲存型別,模組名則是被編譯的模組的名字,例如:
?CO?main1 :表示main1模組中的程式碼段中的常數部分
?PR?function1?module 表module模組中函式function1的可執行段,具體規定參閱手冊。
C51編譯器是一個具有優化功能的編譯器,它共提供六級優化功能。確保生成目的碼的最高效率(程式碼最少,執行速度最快)。具體六級優化的內容可參考幫助。
在C51中提供以下編譯控制指令控制程式碼優化:
OPTIMIZE(SJXE):儘量採用子程式,使程式程式碼減少。
NOAREGS:不使用絕對暫存器訪問,程式程式碼與暫存器段獨立。
NOREGPARMS:引數傳遞總是在區域性資料段實現,程式程式碼與低版本C51相容。
OPTIMIZE(SIZE)AK OPTIMIZE(speed)提供6級優化功能,預設為: OPTIMIZE(6,SPEED)。
[dvnews_page=第五章 Keil C51庫函式參考]
C51強大功能及其高效率的重要體現之一在於其豐富的可直接呼叫的庫函式,多使用庫函式使程式程式碼簡單,結構清晰,易於除錯和維護,下面介紹C51的庫函式系統。
C51提供的本徵函式是指編譯時直接將固定的程式碼插入當前行,而不是用ACALL和LCALL語句來實現,這樣就大大提供了函式訪問的效率,而非本徵函式則必須由ACALL及LCALL呼叫。
C51的本徵庫函式只有9個,數目雖少,但都非常有用,列如下:
_crol_,_cror_:將char型變數迴圈向左(右)移動指定位數後返回
_iror_,_irol_:將int型變數迴圈向左(右)移動指定位數後返回
_lrol_,_lror_:將long型變數迴圈向左(右)移動指定位數後返回
_nop_: 相當於插入NOP
_testbit_: 相當於JBC bitvar測試該位變數並跳轉同時清除。
_chkfloat_: 測試並返回源點數狀態。
使用時,必須包含#inclucle <intrins.h>一行。
如不說明,下面談到的庫函式均指非本徵庫函式。
例如8031、8051均為REG51.h其中包括了所有8051的SFR及其位定義,一般系統都必須包括本檔案。
該檔案中實際只定義了幾個巨集,以確定各儲存空間的絕對地址。
其中包括拷貝比較移動等函式如:
memccpy memchr memcmp memcpy memmove memset
這樣很方便地對緩衝區進行處理。
流函式通8051的串列埠或使用者定義的I/O口讀寫資料,預設為8051串列埠,如要修改,比如改為LCD顯示,可修改lib目錄中的getkey.c及putchar.c原始檔,然後在庫中替換它們即可。
bit isalnum(char c);
bit isalpha(char c);
bit iscntrl(char c);
bit isdigit(char c);
bit isgraph(char c);
bit islower(char c);
bit isprint(char c);
bit ispunct(char c);
bit isspace(char c);
bit isupper(char c);
bit isxdigit(char c);
bit toascii(char c);
bit toint(char c);
char tolower(char c);
char __tolower(char c);
char toupper(char c);
char __toupper(char c);
unsigned char _crol_(unsigned char c,unsigned char b);
unsigned char _cror_(unsigned char c,unsigned char b);
unsigned char _chkfloat_(float ual);
unsigned int _irol_(unsigned int i,unsigned char b);
unsigned int _iror_(unsigned int i,unsigned char b);
unsigned long _irol_(unsigned long l,unsigned char b);
unsigned long _iror_(unsigned long L,unsigned char b);
void _nop_(void);
bit _testbit_(bit b);
char getchar(void);
char _getkey(void);
char *gets(char * string,int len);
int printf(const char * fmtstr[,argument]…);
char putchar(char c);
int puts (const char * string);
int scanf(const char * fmtstr.[,argument]…);
int sprintf(char * buffer,const char *fmtstr[;argument]);
int sscanf(char *buffer,const char * fmtstr[,argument]);
char ungetchar(char c);
void vprintf (const char *fmtstr,char * argptr);
void vsprintf(char *buffer,const char * fmtstr,char * argptr);
float atof(void * string);
int atoi(void * string);
long atol(void * string);
void * calloc(unsigned int num,unsigned int len);
void free(void xdata *p);
void init_mempool(void *data *p,unsigned int size);
void *malloc (unsigned int size);
int rand(void);
void *realloc (void xdata *p,unsigned int size);
void srand (int seed);
void *memccpy (void *dest,void *src,char c,int len);
void *memchr (void *buf,char c,int len);
char memcmp(void *buf1,void *buf2,int len);
void *memcopy (void *dest,void *SRC,int len);
void *memmove (void *dest,void *src,int len);
void *memset (void *buf,char c,int len);
char *strcat (char *dest,char *src);
char *strchr (const char *string,char c);
char strcmp (char *string1,char *string2);
char *strcpy (char *dest,char *src);
int strcspn(char *src,char * set);
int strlen (char *src);
char *strncat (char 8dest,char *src,int len);
char strncmp(char *string1,char *string2,int len);
char strncpy (char *dest,char *src,int len);
char *strpbrk (char *string,char *set);
int strpos (const char *string,char c);
char *strrchr (const char *string,char c);
char *strrpbrk (char *string,char *set);
int strrpos (const char *string,char c);
int strspn(char *string,char *set);
[dvnews_page=第六章 Keil C51例子:Hello.c]
Hello位於/C51/excmples/Hello/目錄,其功能是向串列埠輸出“Hello,world”整個程式如下:
#pragma DB OE CD
#indule <reg51.h>
#include<stdio.h>
void main(void)
{
SCOn=0x50;
TMOD=0x20
TH1=0xf3;
Tri=1;
TI=1;
printf(“Hello,world /n”);
while(1) { }
}
(1) file_new新建一個hello.c檔案,輸入如上內容或直接用目錄下原始檔。
(2) file_save或工具欄將檔案存檔。
(3) project_new project建立一個project名為hello,並在其中加入hello.c。
這時該project已是開啟狀態,或用open project開啟已存在的project。
(4) option_C51 compiler中選出至少包括兩項DB OE。
(5) option_dscope Debugger選中hello/DS51.INI
檢視DS51.INI看其是否為:
“load…/…/BIN/8051.DLL
map 0, 0xffff”
否則修改。
(6) 在option_make選make檔案順序。
(7) project選Build project,看是否有語法錯誤,若無則生成HEX檔案,若有則修改原始檔後重復以上部分步驟。
(8) run_dScope debugger進入dScope51後裝入hello則可用go直接執行看serial視窗有無輸出,正常每系統執行一次,serial視窗均出現一個“Hello,world”表明執行無誤。
(1) 進入Ishell 用Setup editer選擇編輯器。
然後單擊Edit或用Edit命令編輯hello.c原始檔,存檔,也可以在files視窗中直接選中hello.c。
(2) 用cd改換project目錄至hello目錄。
(3) 在setup_target一專案選8051。
(4) 在setup_C51中輸出DB OE。
(5) 在setup_project輸入project名hello。
(6) 在setup_save儲存Ishell.CFG檔案。
(7) 編輯一個Link檔案hello.lin中有“hell.obj”一行。
(8) 由游標落在files選單中的Hello.c上,單擊“translate”,如無語法錯,再擊“link”,則Hex檔案生成。
(9) 單擊Simulate如在8051.CDF中選Simulate為dScope則進入dScope除錯直接“Go”,看serial視窗輸出為“Hello.world”。
(10) 如程式有誤修改原始碼後不必再translate或link了,只要一步Amake即可。
若project中包括不止一個檔案,在DOS的Ishell中不能用Translate編譯,而應建立bat檔案,直接在命令窗編譯,然後link連線。
如還需用Translate則只能多個檔案分別編譯,然後連線。
[dvnews_page=第七章 Keil C51的程式碼效率]
C51程式編譯生成彙編程式碼的效率,是由許多因素共同決定的,對於Keil C51,主要受以下兩種因素影響:
儲存模式決定了預設變數的儲存空間,而訪問各空間變數的彙編程式碼的繁簡程度決定了程式碼率的高低。
例如:一個整形變數i,如放於記憶體18H、19H空間,則++i的操作編譯成四條語句:
INC 0x19
MOV A,0x19
JNZ 0x272D
INC 0x18
0x272D:
而如果放於外存空間0000H、0001H則++i的操作編譯成九條語句:
MOV DPTR,0001
MOVX A,@ DPTR
INC A
MOVX @ DPTR,A
JNz #5
MOV OPTR,#0000
MOVX A,@DPTR
INC A
MOVX @ DPTR,A
就彙編之後的語句而言,對外部儲存器的操作較內部儲存器操作程式碼率要低得多,生成的語句為記憶體的兩倍以上,而程式中有大量的這種操作,可見儲存模式對程式碼率的響了。
因此程式設計的原則是
1、儲存模式從small-Compact-large依次選擇,實在是變數太多,才選large模式。
2、即使選擇了large模式,對一些常用的區域性的或者可放於記憶體中的變數,最好放於記憶體中,以儘量提高程式的程式碼率。
程式的結構單元包括模組、函式等等。同樣的功能,如果結構越複雜,其所涉及的操作、變數、功能模組函式等就越多,較之結構性好,程式碼簡單的程式其程式碼率自然就低得多。
此外程式的執行控制語句,也是影響程式碼率的關鍵因素,例如:switch -case語句,許多編譯器都把它們譯得非常複雜,Keil C51也不例外,相對較為簡易的Switch-case語句,編譯成跳轉指令形式,程式碼率較高,但對較為複雜的Switch-Case,則要呼叫一個系統庫函式?C?ICASE進行處理,非常複雜。
再如if( ),while( ),等語句也是程式碼相對較低的語句,但編譯以後比switch-case要高得多。
因此建議設計者儘量少用switch-case之類語句來控制程式結構,以提高程式碼率。
除以上兩點外,其它因素也會對程式碼率產生影響,例如:
是否用暫存器傳遞引數 即NOAREGS選項是否有
是否包括除錯資訊:即DEBUG選項
是否包括擴充套件的除錯資訊:即BJECTEXTEND
[dvnews_page=第八章 dScope for Windows使用詳解]
可設定其它各種除錯視窗,設定斷點、觀察點,修改地址空間,載入檔案等等;
支援使用者程式的各種顯示方式,可連續執行,單步執行使用者程式,並可線上 彙編;
支援命令列的輸入;
可設定所要觀察的變數、表示式等;
顯示內部暫存器的內容,程式執行次數等;
顯示串列埠接收和傳送的資料;
顯示所要觀察的各程式段佔用CPU的空間;
顯示所選擇的記憶體中的資料;
顯示各種符號名稱,包括專有符號,使用者自定義符號(函式名、變數、標號)等;
動態顯示當前執行的程式段的函式呼叫關係;
提供當前模組內各程式段中被執行程式碼的比率;。
可顯示I/O口,定時器,中斷,串列埠等外圍裝置狀態;
在uVision的Option選單dScope Debugger中指定dScope的初始化檔案,用uVision的RUN啟動dScope將自動載入此初始化檔案,自動執行其中命令;
下面是一個例子,可以看出調入一個除錯程式碼的過程。Ds51.ini:
load 8051.dll
load test
slog>>test.log
xtal=11.0592
define button "go to main","g,main"
ws RevCounter
ws rm.r
g,main
PA RESET
PA serial
PA timer0
方法1:命令列
WS expression [, numberbase ] [ LINE ]
其中numberbase為顯示數制,10對應10進位制,16對應16進位制,預設為16進位制。LINE為單行顯示,預設為多行顯示。
方法2:setup->Watchpoints,在對話方塊中輸入變數
d i(x,d):起始地址,終止地址
d 變數名
View->Call-stack->Show invocation,可以跟蹤呼叫過程;
在裝入8051.dll後,在dScope的主選單中將增加Peripherial,其有4個字選單:
I/0 port:Pi埠狀態
Interrupt:中斷設定
Timer:定時器中斷狀態
Serial:串列埠中斷狀態
設定相應的中斷請求標誌位即可產生中斷。
PA用來分析一段程式碼執行佔用CPU的百分比。定義:
命令列 PA func_name
dScope除了用命令列的方式進行除錯以外,還可將各種除錯命令彙集於一個除錯檔案中,然後呼叫該檔案,就可達到自動測試使用者原始碼的目的。dScope的命令檔案支援C/PL/M的格式,因而編制除錯命令檔案與編制C語言程式有些類似。
(1) 地址空間分段
dScope提供的最大可用空間為16M,實際上我們只用以下三段:
① 內部資料空間段(0X00段或D段)
0X00:0X0000~0X00:0XFFFF(對MSC51而言為0X00:0X00FF)
② 外部資料空間段(0X01段式或X段)
0X01:0X0000~0X01~0XFFFF
③ 程式空間段(0XFF段或C段)
0XFF:0X0000~0XFF:0XFFFF
(2) 地址空間型別
C:程式碼空間
D:內部直接定址空間
I: 內部間接定址空間
X:外部資料空間
B:位定址空間
P:I/O口
EB:擴充套件的位定址空間(MCS251專有)
ED:擴充套件的資料空間(MCS251專有)
CO:常數空間(MCS251專有)
HC:正常數空間(MCS251專有)
dScope支援十六進位制、八進位制、十進位制、二進位制常數,其後綴分別為H、Q(O)、T(或無)、Y;
dScope不區分常量的大、小寫。
(1) 整型常量
分為整型(int),無符號整型(uint,00rd),長整型(long),無符號長整型(Wlong、Word)。
(2) 浮點型常量
與ANSI C相同。
(3) 字串常量
與ANSI C相同
(4) 字元常量
分為字元型(Char)和無符號字元型(Uchar)一種。
(5) 行號常數
指使用者程式中的行號,實際上是個地址
(6) 位常量(Bit):
0和1
(7) 地址常數
地址常數的種類很多,地址常數不同於行號常數,行號常數就是一個地址,而地址數被引用時,實際上是取該地址中的資料。
C:程式碼地址常數,如C:0X0012或0XFF:0X0012
D:內部直接定址地址常數,如D:0X0068或0X00:0X0068
I:內部間按定址地址常數,如I:0X0010或0X00:0X0010
X:外部資料空間地址常數,如X:0X0028或0X01:0X0028
B:位地址常數,如B:0X20或B:0X24.0
EB:擴充套件的位地址常數(MCS251專有),
ED:擴充套件的資料空間地址常數(MCS251專有)
CO:常數空間地址常數(MCS251專有)
HC:正常數空間地址常數(MCS251專有)
(8) 識別符號常量
即使用者源程式中的標號、函式名等,實際上代表某一地址。
(9) 使用者源程式中定義的常數
dScope所支援的變數名或識別符號最多可由31個字元組成,第一個字母為A~Z,a~z,下劃線或問號,後續字元可為字母、數字、下劃線和問號。除CPU變數和系統變數外,dScope不支援全域性變數,但可視“define”命令定義的變數為全域性變數。
Dscope所支援的變數分為以下幾種(變數名稱不區分大、小寫),支援型別轉換:
(1) 整型變數
分為整型變數(int)、無符號整型變數(uint/word),長整型(Long) 、無符號長整型(Ulong/dword)。
(2) 浮點型變數(float)
與ANSI C相同。
(3) 字元型變數L
分為字元型(char)變數和無符號字元型(Uchar)
(4) 位變數(Bit)
(5) 系統變數
dScope自己定義了一系列內部變數,使用者可對這些變數進行讀或讀/寫操作, 可被使用者自定義數所引用。
a. Cycles (Read Only)
32位變數(Ulong),指示當前程式執行已花費的指令週期(cycle)。
b. Ramsize(R/W)
16位變數(Uint),指示內部可直接定址的資料空間大小。
c. Radix(R/N)
8位變數(Uchar),決定輸出的數制
Radix=0X0A (10進位制),Radix=0X10 (16進位制)
d. -IIP-(R/W)
8位變數(Uchar),指示當前的中斷巢狀數目。
e. $ (R/W)
32位變數(Ulong),指出PC值,通過對其進行寫操作,可改變程式執行的流程。
f. Itrace (R/W)
8位變數(Uchar),決定是否對程式執行情況進行記錄
Itrace=1,使能記錄操作
Itrace=0,根本上記錄操作
g. __Break__(R/W)
8位變數(Uchar) __Break__=1,中止程式的執行
h. __Mode__和__Frame size__是MCS 251專有的變數。
(6) CPU變數
即R0~R7、A、C(位變數)、B、DPTR及特殊功能暫存器變數,對這些變數均可進行讀、寫操作。
(7) 使用者源程式中定義的變數、陣列、結構等
dScope支援ANSI C的運算子,包括算術運算子,邏輯運算子,關係運算符。
以運算子將dScope所支援的常量、變數、函式等連線在一起,就構成了dScope的表示式。
dScope不支援在命令檔案中定義陣列,但可引用使用者程式中的陣列,引用方式如同C。
dScope不支援在命令檔案中定義結構和聯合,但可引用使用者程式中的結構和聯合,引用方式如同C,但如要輸出整個結構或聯合的結果,就要用命令“OBJ”。
不可自定義指標,但支援使用者源程式中的指標變數。
dScope提供了一系列除錯命令。在命令檔案中,dScope只支援這些語句及前述定義的表示式,C語言的語句均不被支援,但在命令檔案所包含的使用者自定義函式(非使用者源程式中的函式)中支援C語句,但使用者自定義函式中同樣不支援陣列、結構、聯合和指標。
(1) ASM
線上彙編命令,格式如下:
ASM C:0Xnnnn (或標號);設定插入彙編指令的地址
ASM 彙編指令
ASM 彙編指令
插入完畢後,在debug視窗內選擇“Assemble->Assemble”完成編譯。
(2) Assign
序列口分配指令,格式如下:
Assign channel<unreg>outreg
對MCS51為:Assign Win<SOIN> Soot
但目前的dScope版本並未提供完整串列埠視窗功能。
(3) Define
使用者自定義變數指令,格式如下:
Define <型別> <變數名>
型別一為如前所述的變數型別,Define指令定義的變數可能為全域性變數,可為使用者自定義函式所引用。
(4) Display
記憶體顯示命令,格式如下二:
D 起始地址,結束地址
地址如前所述的地址常數,識別符號常量。
(5) Enter
記憶體修改指令,格式如下:
E 型別地址=表示式 [表示式2],[……]
型別如前所述,地址如前所述的地址常數。表示式如前所述,但如果是函式名稱(含標號、指標變數),則關鍵字E→EP
(6) Map/Reset map
Map為記憶體段修改指令,Reset map將記憶體段復位或預設值。
(7) Object
用以引用使用者源程式中的結構(聯合)、陣列、格式如下:
Obj表示式 [n,],[Line]
表示式為使用者源程式中的陣列,結構(聯合)名稱。當Line預設時,數目、結構(聯合)的內容按n行輸出;如有Line,則單行輸出。
(8) U
反彙編命令,格式如下:
U [地址]
地址包括地址常 數及識別符號常量,指明反彙編的起始地址。
(9) WK
觀察點刪除命令,格式如下:
WK n1[n2 ],[……] ;刪除指定的觀察點,n為字元型,整型
常數
WK * ;刪除所有的觀察點
(10) WS
觀察點設定命令,格式如下:
WS 表示式[,n][LINE]
關鍵字LINE存在時,觀察點表示式單行輸出
LINE預設時,觀察點表示式n行輸出。
(11) G
連續執行命令,格式如下:
G [起始地址],[終止地址]
地址為識別符號常量或地址常數,地址預設時,為連續執行。
(12) T/P
單步執行指令,格式如下:
T/P n ;n指至單行執行的步數,P指給使用者當呼叫某函式時,把它作為一步處理,並不進入該函式執行。
(13) PA
效能分析操作指令,其分以下幾種:
PA
顯示當前所設定的效能分析程度段
PA Kill *
刪除當前所設定的所有效能分析程式段
PA Kill n1 [,n2],[……]
刪除指定的效能分析程式段
PA 地址範圍
設定效能分析程式段,地址範圍可以起始地址和結束地址的方式給出,也可給出函式名,行號範圍。
PA Reset
復位效能分析視窗(PA Windows),清除所有的記錄。
(14) BD
斷點失效命令,格式如下:
BD n1 [,n2],[,……] ;disable指定的斷點
DB * ;disable所有的斷點
(15) BE
斷點使能命令,格式如下:
BE M [,n2],[,……] ;使能指定的斷點
BE * ;使能所有的斷點
(16) BK
斷點刪除指令,格式如下:
BK M[,n2],[,……] ;刪除指定的斷點
BK * ;刪除所有的斷點
(17) BL
斷點顯示指令,顯示所有被定義的斷點。
(18) BS
斷點定義指令,dScope支援多達40個斷點,具體格式如下:
a.BS 表示式[,count] [,“cmd”]
count:經過該斷點的次數 [選項]
“cmd”:斷點到達後附帶執行的dScope命令(連項)
表示式一個條件表示式,此時該斷點稱為條件斷點(運算子為&.&&,<<=>,>=,= =,!=)
BS READ 表示式 [,count] [,“cmd”]
BS WRITE 表示式 [,count] [“cmd”]
BS READWRITE 表示式 [,count] [,“cmd”]
以上三種斷點稱訪問式(Access斷點),當某一址或變數被訪問(R/W)或某些值被讀寫時,程式被中斷。
(19) Define button
圖示定義指令,用於當視窗(Toolbox)
(20) !
DOS視窗Open命令,以“EXIT”命令退出DOS視窗。
(21) Include
檔案包含命令,格式如下:
Include [路徑] 檔名
dScope支援以檔案包含的方式調入並執行除錯命令檔案,使用者自定義函式檔案,除錯命令檔案可以有後綴,也可無後綴。
(22) Load
載入命令,格式如下:
Load [路徑] 檔名
Load指令能夠載入的檔案必須具有以下格式之一。
Intel Hex/Hex 386格式
Intel Object (OMF_51) 格式
Intel Object (OMF-251) 格式
dScope的CPU驅動檔案(.DLL)
(23) LOG
Command Window存檔指令,用於將Command Windows中的內容輸出到指定的檔案中,格式如下:
LOG > [路徑]檔名 ;建立一個新檔案
LOG >> [路徑]檔名 ;將Command Windows的內容輸出到某個已
存在的檔案中。
LOG OFF 完成輸出操作並開閉該檔案
LOG指令只將LOG>或LOG>>與LOG OFF指令之間的操作命令存入該指定檔案。
(24) Reset
復位指令,具體格式如下:
Reset ;執行dScope的復位
Reset Map ;復位外部資料空間
Reset Var ;復位SET指令定義的變數
(25) Save
該指令將一段記憶體映象以19EX386/HEX的格式存檔,具體格式如下:
Save 路徑 檔名:地址1、地址2
地址1、地址2指所要儲存的空間範圍,既可是識別符號,也可是址常數。
(26) SET
該指令回來定義dScope目的碼預定義變數的含義,這些預定義變數包括以下二種:
SRC ;指出所在的路徑
F1~F12;對應於鍵盤上的12個功能鍵,定義這些功能鍵的
含義。
SET指令的格式為:
SET 變數=“字串”
SET 變數
dScope支援三種函式,即dScope預定義函式,使用者自定義函式和訊號函式,分別詳述如下:
(1) dScope預定義函式
dScope號提供8個預定義函式(可視為dScope的庫函式)
①Void Printf(“String”,輸出表列)
螢幕列印函式,與ANSI C的Printf ( ) 函式相同
②Void exec(“Command__String”)
Command__String為一有效的命令字串,此函式用於在執行使用者自定義函式的過程中執行dScope命令,這個函式提供了一個很重要的編制測試命令檔案的方法。
③int getint(“Prompt__String”);從鍵盤輸入一個整數
int getlong (“Prompt__String”);從鍵盤輸入一個長整數
float getfloat (“Prompt__String”);從鍵盤輸入一個浮點數
以上這三個函式被執行時,dScope會彈出一個dialog box等待使用者輸入資料,其標題欄上是“Prompt__String”,利用這個函式,不僅可以為變數賦值,也可使使用者得以看清前一階段的測試結果。
④int rand (int seed)
該函式會輸出一個隨機數(-32768~32768)
⑤Void memeset (ulorg start , ulong end ,uchar val)
該函式用於給地址範圍(Start__end)內的記憶體賦值(Val)
⑥Void twatch (Long cycles)
定時函式,時間由(Long cycles)決定,它是以指令週期計數的,它也 用於產生一個訊號波形,該函式必須用於訊號函式中。
(2) 使用者自定義函式
這類函式不同於使用者源程式中的數函,其定義格式為
Func 返回型別 函式名(引數序列)
{
語句
}
返回型別如前所述的變數型別
使用者自定義函式中的語句與ANSI C相似,只是不支援陣列結構、聯合、指標,可引用dScope系統變數,define語句定義的變數和使用者源程式變數,不支援dScope命令,如想在函式中執行dScope命令,要藉助於exec(“Command__String”)函式,可引用dScope預定義的函式(除了twatch ( )函式),不支援ANSI C的庫函式。
(3) 訊號函式
用於產生具有某一波形的訊號,定義格式為:
Signal返回型別函式名(引數長列){
語句
}
訊號函式主要是利用twatch ( )函式,目前dScope版本在提供這一功能上面還有一定問題。
(4) dScope函式與ANSI函式的區別
① 不支援條件彙編
② 不支援標頭檔案
③ 無變數的初始化
④ 不支援陣列、結構、指標
⑤ 呼叫方式不同,自定義函式和訊號函式首先要包含一個函式檔案之中,然而在測試命令檔案中以Inclule指令呼叫該函式檔案,最後才能以函式名呼叫之。
⑥ 函式呼叫只支援傳值方式。
Keil C51是美國Keil Software公司出品的51系列相容微控制器C語言軟體開發系統,與彙編相比,C語言在功能上、結構性、可讀性、可維護性上有明顯的優勢,因而易學易用。用過組合語言後再使用C來開發,體會更加深刻。
Keil C51軟體提供豐富的庫函式和功能強大的整合開發除錯工具,全Windows介面。另外重要的一點,只要看一下編譯後生成的彙編程式碼,就能體會到Keil C51生成的目的碼效率非常之高,多數語句生成的彙編程式碼很緊湊,容易理解。在開發大型軟體時更能體現高階語言的優勢。
下面詳細介紹Keil C51開發系統各部分功能和使用。
C51工具包的整體結構,如圖(1)所示,其中uVision與Ishell分別是C51 for Windows和for Dos的整合開發環境(IDE),可以完成編輯、編譯、連線、除錯、模擬等整個開發流程。開發人員可用IDE本身或其它編輯器編輯C或彙編原始檔。然後分別由C51及A51編譯器編譯生成目標檔案(.OBJ)。目標檔案可由LIB51建立生成庫檔案,也可以與庫檔案一起經L51連線定位生成絕對目標檔案(.ABS)。ABS檔案由OH51轉換成標準的Hex檔案,以供偵錯程式dScope51或tScope51使用進行原始碼級除錯,也可由模擬器使用直接對目標板進行除錯,也可以直接寫入程式存貯器如EPROM中。
在Windows下直接執行軟體包中DOS/C51DOS.exe然後選擇安裝目錄即可。完畢後欲使系統正常工作須進行以下操作(設C:/C51為安裝目錄):
修改Autoexec.bat,加入
path=C:/C51/Bin
Set C51LIB=C:/C51/LIB
Set C51INC=C:/C51/INC
然後執行Autoexec.bat
在Windows下執行軟體包中WIN/Setup.exe,最好選擇安裝目錄與C51 for Dos相同,這樣設定最簡單(設安裝於C:/C51目錄下)。然後將軟體包中crack目錄中的檔案拷入C:/C51/Bin目錄下。
(1) C51
C51是C語言編譯器,其使用方法為:
C51 sourcefile[編譯控制指令]
或者
C51 @ commandfile
其中sourcefile為C原始檔(.C)。大量的編譯控制指令完成C51編譯器的全部功能。包控C51輸出檔案C.LST,.OBJ,.I和.SRC檔案的控制。原始檔(.C)的控制等,詳見第五部分的具體介紹。
而Commandfile為一個連線控制檔案其內容包括:.C原始檔及各編譯控制指令,它沒有固定的名字,開發人員可根據自己的習慣指定,它適於用控制指令較多的場合。
(2) A51
A51是組合語言編譯器,使用方法為:
A51 sourcefile[編譯控制指令]
或A51 @ commandfile
其中sourcefile為彙編原始檔(.asm或.a51),而編譯控制指令的使用與其它彙編如ASM語言類似,可參考其他組合語言材料。
Commandfile同C51中的Commandfile類似,它使A51使用和修改方便。
(1) L51
L51是Keil C51軟體包提供的連線/定位器,其功能是將編譯生成的OBJ檔案與庫檔案連線定位生成絕對目標檔案(.ABS),其使用方法為:
L51 目標檔案列表[庫檔案列表] [to outputfile] [連線控制指令]
或 L51 @Commandfile
源程式的多個模組分別經C51與A51編譯後生成多個OBJ檔案,連線時,這些檔案全列於目標檔案列表中,作為輸入檔案,如果還需與庫檔案(.LiB)相連線,則庫檔案也必須列在其後。outputfile為輸檔名,缺少時為第一模組名,字尾為.ABS。連線控制指令提供了連線定位時的所有控制功能。Commandfile為連線控制檔案,其具體內容是包括了目標檔案列表,庫檔案列表及輸出檔案、連線控制命令,以取代第一種繁瑣的格式,由於目標模組庫檔案大多不止1個,因而第2種方法較多見,這個檔名字也可由使用者隨意指定。
(2) Bl51
BL51也是C51軟體包的連線/定位器,其具有L51的所有功能,此外它還具有以下3點特別之處:
a. 可以連線定位大於64kBytes的程式。
b. 具有程式碼域及域切換功能(CodeBanking & Bank Switching)
c. 可用於RTX51作業系統
RTX51是一個實時多工作業系統,它改變了傳統的程式設計模式,甚至不必用main( )函式,微控制器系統軟體向RTOS發展是一種趨勢,這種趨勢對於186和386及68K系列CPU更為明顯和必須,對8051因CPU較為簡單,程式結構等都不太複雜,RTX51作用顯得不太突出,其專業版軟體PK51軟體包甚至不包括RTX51Full,而只有一個RTX51TINY版本的RTOS。RTX51 TINY適用於無外部RAM的微控制器系統,因而可用面很窄,在本文中不作介紹。Bank switching技術因使用很少也不作介紹。
(1) dScope51
dScope51是一個源級偵錯程式和模擬器,它可以除錯由C51編譯器、A51彙編器、PL/M-51編譯器及ASM-51彙編器產生的程式。它不需目標板(for windows也可通過mon51接目標板),只能進行軟體模擬,但其功能強大,可模擬CPU及其外圍器件,如內部串列埠,外部I/O及定時器等,能對嵌入式軟體功能進行有效測試。
其使用方法為:
DS51[debugfile][INIT(initfile)]
其中debugfile是一個Hex格式的8051檔案,即待除錯的檔案其為可選的,可在進入dScope51後用load命令裝入。
Initfile為一個初使化檔案,它在啟動dScope51後,在debugfile裝入前裝入,裝有一些dScope的初使化引數及常用除錯函式等。下面是一個dScope.ini檔案(for dos)的內容:
Load ../../ds51/8051.iof
Map 0,0xffff
dScope51 for Windows則直接用滑鼠進入,然後用load裝入待調檔案。
(2) tScope51
與dScope51不同的是Scope51必須帶目標板,目前它可以通過兩種方式訪問目標板。(1) 通過EMul51線上模擬器,tScope51為該模擬器準備了一個動態連線檔案EMUL51.IOT,但該方法必須配合該模擬器。(2) 通過Monitov51監控程式,這種方法是可行的,tScope51為訪問Monitor51專門帶有MON51.IOT連線程式,使用時可通過串列埠及監控程式來除錯目標板。
其使用方法為:
TS51[INIT(file_name.ini)]
其中file_name.ini為一個初使化檔案。
進入TS51後,必須裝入IOT檔案,可用的有MON51.IOT及EMUL51.IOT兩種,如裝入MON51.IOT:
Load.C:/C51/TS51/MON51.IOT CPUTYPE(80517)
可惜的是tScope51只有for Dos的版本。
(3) Monitor 51
Monitor51是一個監控程式通過PC機的串列埠與目標板進行通訊,Monitor操作需要MON51或dScope51 for Windows,後面部分將對Monitor51做較為詳細的介紹。
(1) Ishell for Dos
這是一個for Dos的IDE,直接在命令列鍵入Ishell,則進入該環境,它使用簡單方便。其命令列與DOS命令列具有同樣的功能,對單模組的Project直接由選單進行編譯連線,對多模組的project。則通過批處理,BAT檔案進行編譯連線,然後通過選單控制由dScope51或tScope51對程式進行除錯,因為是for dos的,不做太詳細介紹。
(2) uVision for Windows
uVision for Windows是一個標準的Windows應用程式,它是C51的一個整合軟體開發平臺,具有原始碼編輯、project管理、整合的make等功能,它的人機介面友好,操作方便,是開發者的首選,具體配置及使用見第五部分。
[dvnews_page=第二章 Keil C51軟體使用詳解 ]
C51編譯器的控制指令分為三類:原始檔控制類,目標檔案控制類及列表控制類。
NOEXTEND:C51原始檔不允許使用ANSI C擴充套件功能。
DEFINE(DF):定義預處理(在C51命令列)。
COMPACT LARGE SMALL 選編譯模式
DEBUG(DB) 包含除錯資訊,以供模擬器或dSCope51使用。
NOAMAKE(NOAM) 禁止AutoMake資訊記錄
NOREGPARMS 禁止用暫存器傳遞引數
OBJECTEXTEND(OE) Object檔案包含附加變數型別資訊
OPTIMIZE(OT) 指定優化級別
REGFILE(RF) 指定一個暫存器使用的檔案以供整體優化用
REGISTERBANK(RB) 指定一個供絕對暫存器訪問的暫存器區名
SRC 不生成目標檔案只生成彙編原始檔
其它控制元件不常用。
CODE(CD):向列表檔案加入彙編列表
LISTINCLUDE(LC):顯示indude檔案
SYMBOLS(SB):列表檔案包括模組內所有符號的列表
WARNINGLEVEL(WL):選擇“警告”級別
[dvnews_page=第二節 dScope51的使用]
總的來說dScope51具有以下特性:
l 高階語言顯示模式
l 整合硬體環境模擬
l 單步或“GO”執行模式
l 儲存器、暫存器及變數訪問
l Watch表示式之值
l 函式與訊號功能
下面,具體說明在進入dScope51 for Dos之後,如何實現上述功能,dScope51採用下拉選單格式和視窗顯示控制,共有language、serial、exe、register四個視窗,其中exe為命令列視窗,language為程式視窗,serial為串列埠窗,register為暫存器窗。
(1) 高階語言顯示模式
單擊主選單中的“View”,第一欄中的三條命令“Highlevel”、“Mixed”、“Assembly”分別對所裝入的程式按照“高階”、“混合級”及“彙編級”三種方式顯示,以方便除錯使用。
(2) 整合硬體環境模擬顯示
主選單中“Peripheral”各條能顯示模擬硬體環境的狀態,其中:
i/o Port:顯示各I/O口之值,對8031而言SFR中的P1、P2、P3、P0與引腳之值分別列出:
Interrupt:顯示5箇中斷源的入口模式是否允許,優先順序等中斷狀態。
Timer:顯示各定時/計數器的模式,初始值狀態等。
int Message:中斷資訊允許,如為允許(“>>”出現),則當中斷申請時,顯示中斷源資訊。比如當中斷髮生時會顯示:
“interrupt Timer 0 occured”等
A/D converter:
顯示A/D轉換器狀態無時,則提示“無”。
Serial:串列埠資訊顯示,包括串列埠模式、波特產等
Other:其它器件,如為8031則顯示“ 無”
(3) 單步或“Go”執行
“F8”單步執行,“F5”全速執行到斷點。或選主選單中Trace單步執行CPU中的Go全速執行。
(4) 儲存器暫存器及變數訪問
外部儲存器管理MAP選單:設定(set)、取消(reset)、顯示(Display)處理可用儲存空間。
修改Code程式碼:ASM命令
儲存器顯示命令:D 類別為(X、D、I、B、C)
修改儲存器命令:E 有以下幾種命令EB、EC、EI、EL、EF、EP
複雜資料型別顯示:Object命令;用以顯示結構或陣列的內容。欲使此命令有效,C51編譯器必須有DB及OBJECTEXTEND兩條。
反彙編命令:U
(5) “Watch”表示式之值
在View選單的“Watch”一欄中有四項:其中包括定義Watch Point(Define)、刪除Watch Point(remove,kill all),及自動更新選項。
也可用WS、WK等命令代替,下面具體看“表示式”型別:
dScope51一次最多可設16個WtchPoint表示式,顯示於Watch Window之中,表示式可以是簡單變數,也可是複雜資料型別如結構、陣列和指向結構的指標等,例如:
>WS *ptime
>WS ptime→hour
>WS some_record[o],analog等等
(6) 關於.IOF檔案
啟動DS51後必須裝入.IOF檔案才能使CPU及Peripheral各項起作用,這個函式的使用是依據8051系列CPU的不同特點,裝入8051各CPU硬體裝置模擬驅動檔案,比如8031CPU就必須load DS51目錄下的8051.IOF。
dScope for windows具有dScope for dos的全部功能,此外,它還具有以下明顯的優點:
(1) 標準的Windows介面,操作更容易更簡單;
(2) 常用操作多用對話方塊,而非Dos的行命令方式;
(3) 視窗資源更加豐富:儲存器視窗、覆蓋率分析、執行狀態分析視窗,加強了除錯功能;
因為dScope for Windows功能強大,具體操作在第八章詳細介紹。
[dvnews_page=第三節 Monitor51及其使用 ]
(1) 硬體系統為51系列CPU;
(2) 帶5K外部程式儲存器(從O地址開始),存放Monitor51程式;
(3) 256Bytes的外部資料儲存器以及5K的跟蹤緩衝區,此外,外部資料儲存器必須足夠容納所有應用程式程式碼及資料,且所有外部資料儲存器必須為馮·諾伊曼儲存器,即能一致訪問XDATA與Code空間。
(4) 一個定時器作為波特率發生器供串列埠使用;
(5) 6 Bytes的空餘堆疊。
Mon51的使用途徑有三種方式:
(1) Dos行命令方式
即先用install對MON51進行配置,然後用MON51進入Monitor狀態,啟用各種命令對Monitor51進行除錯。
(2) tScope51方式
啟動tScope51裝入TS51目錄下的MON51.IOT驅動檔案,與目標板通訊。
(3) dScope51 for Windows方式
在選CPU驅動檔案時,選“MON51.dll”,則檢查目標板並進入MON51狀態。
(1) MON51 for Dos的配置
執行install檔案(在MON51目錄下),不同的引數可以配置不同的硬體環境。INSTALL Serialtype [xdstastart[codestart[bank][PROMCHECK]]],具體說明見MON51幫助檔案或使用手冊。
(2) MON51 for Windows的配置
在啟用MON51.dll時,會使得系統自動檢查目標板連線,如配置不對,則彈出“Configuration”對話方塊,設定PC串列埠,波特率等,完畢單擊“apply”有效。
收發交叉互連,RTS、CTS直連,DSR、DTR直連,具體引腳排列參考串列埠資料。
詳細的MON51命令可參閱幫助。
[dvnews_page=第四節 整合開發環境(IDE)的使用 ]
進入Ishell之後看到兩個視窗:一個是檔案視窗,一個是Dos命令列視窗,視窗上方是下拉式的命令選單,其中的Files控制檔案視窗的顯隱。
使用Ishell,第一步就是配置系統,即要學習兩個檔案的修改與建立:
(1) Ishell.CFG檔案
每一個project都有一個Ishell.CFG,其中存放有“Option選單和Setup選單下的部分資訊;Bell enabled、Monochrome enabled、Editor Selected、CRT Lines、target enviroment、name of user edit、Automatic load for configuration enabled、file window enabled、file specification for file window、translate command line controls、project name等。
對每個project都必須設定以上資訊,然後存檔“setup”的的“save”,這樣才可正式開始下面工作。
(2) IShell.col檔案
對IDE顏色設定,如不改動,可以預設為主。
(3) CDF檔案
該檔案位於BIN目錄下,每一檔案定義一組外部函式工具包,即定義外部環境如8051.CDF,USER.CDF等,開發者可修改CDF檔案,供自己使用,至於CDF檔案內容可檢視一下8051.CDF即可知道。注意.CDF檔案是Ishell系統的核心所在,不同的CDF檔案可使本IDE適用於不同的編譯、連線系統,即本IDE並不僅適於C51。
下面談一談Automake工具:
C51的Automake是一個project管理器,在8051工具包中以OBJECT檔案形式保留了一個project的資訊,AutoMake用這些資訊來進行project管理,一旦手工建立一個project,Automake可生成一個新的OBJECT,AutoMake利用此檔案來編譯那些修改過的檔案。
Automake支援C51、A51、L51/BL51、C166、A166、L166等編譯聯結器。點中主選單中的Automake即執行本工具。
Ishell for Dos使用比較繁瑣,推薦使用uVision for windows。
uVision是一個標準的windows應用程式,其編譯功能、檔案處理功能、project處理功能、視窗功能以及工具引用功能(如A51、C51、PL/M41、BL51 dScope等)等都較Ishell for Dos要強得多。
uVision採用BL51作聯結器,因為BL51相容L51,所以一切能在Dos下工作的project都可以到uVision中進行連線除錯。
uVision採用dScope for windows作偵錯程式,該偵錯程式支援MON51及系統模擬兩種方式,功能較for DOS要強大好用,除錯功能強大。
注意:
(1) Option選單下的各項要會使用,其中A51、C51、PL/M51、BL51定義各檔案所使用的編譯、連線控制指令,dScope定義一個dScope初始化檔案。Make則是定義一個make檔案。
(2) 進入除錯是在RUN選單下執行dScope。
(3) project中包括新建、開啟、修改、更新、編譯、連線等poject處理,具體使用可參考後面的例子。
[dvnews_page=第三章 Keil C51 vs 標準C ]
深入理解並應用C51對標準ANSIC的擴充套件是學習C51的關鍵之一。因為大多數擴充套件功能都是直接針對8051系列CPU硬體的。大致有以下8類:
l 8051儲存型別及儲存區域
l 儲存模式
l 儲存器型別宣告
l 變數型別宣告
l 位變數與位定址
l 特殊功能暫存器(SFR)
l C51指標
l 函式屬性
具體說明如下(8031為預設CPU)。
C51 V4.0版本有以下擴充套件關鍵字(共19個):
_at_ idata sfr16 alien interrupt small
bdata large _task_ Code bit pdata
using reentrant xdata compact sbit data sfr
[dvnews_page=第三節 儲存模式]
儲存模式決定了沒有明確指定儲存型別的變數,函式引數等的預設儲存區域,共三種:
所有預設變數引數均裝入內部RAM,優點是訪問速度快,缺點是空間有限,只適用於小程式。
所有預設變數均位於外部RAM區的一頁(256Bytes),具體哪一頁可由P2口指定,在STARTUP.A51檔案中說明,也可用pdata指定,優點是空間較Small為寬裕速度較Small慢,較large要快,是一種中間狀態。
所有預設變數可放在多達64KB的外部RAM區,優點是空間大,可存變數多,缺點是速度較慢。
提示:儲存模式在C51編譯器選項中選擇。
[dvnews_page=第三節 儲存模式]
儲存模式決定了沒有明確指定儲存型別的變數,函式引數等的預設儲存區域,共三種:
所有預設變數引數均裝入內部RAM,優點是訪問速度快,缺點是空間有限,只適用於小程式。
所有預設變數均位於外部RAM區的一頁(256Bytes),具體哪一頁可由P2口指定,在STARTUP.A51檔案中說明,也可用pdata指定,優點是空間較Small為寬裕速度較Small慢,較large要快,是一種中間狀態。
所有預設變數可放在多達64KB的外部RAM區,優點是空間大,可存變數多,缺點是速度較慢。
提示:儲存模式在C51編譯器選項中選擇
[dvnews_page=第七節 Keil C51指標]
C51支援一般指標(Generic Pointer)和儲存器指標(Memory_Specific Pointer).
一般指標的宣告和使用均與標準C相同,不過同時還可以說明指標的儲存型別,例如:
long * state;為一個指向long型整數的指標,而state本身則依儲存模式存放。
char * xdata ptr;ptr為一個指向char資料的指標,而ptr本身放於外部RAM區,以上的long,char等指標指向的資料可存放於任何儲存器中。
一般指標本身用3個位元組存放,分別為儲存器型別,高位偏移,低位偏移量。
基於儲存器的指標說明時即指定了存貯型別,例如:
char data * str;str指向data區中char型資料
int xdata * pow; pow指向外部RAM的int型整數。
這種指標存放時,只需一個位元組或2個位元組就夠了,因為只需存放偏移量。
即指標在上兩種型別之間轉化:
l 當基於儲存器的指標作為一個實參傳遞給需要一般指標的函式時,指標自動轉化。
l 如果不說明外部函式原形,基於儲存器的指標自動轉化為一般指標,導致錯誤,因而請用“#include”說明所有函式原形。
l 可以強行改變指標型別。
[dvnews_page=第八節 Keil C51函式]
C51函式宣告對ANSI C作了擴充套件,具體包括:
中斷宣告方法如下:
void serial_ISR () interrupt 4 [using 1]
{
/* ISR */
}
為提高程式碼的容錯能力,在沒用到的中斷入口處生成iret語句,定義沒用到的中斷。
/* define not used interrupt, so generate "IRET" in their entrance */
void extern0_ISR() interrupt 0{} /* not used */
void timer0_ISR () interrupt 1{} /* not used */
void extern1_ISR() interrupt 2{} /* not used */
void timer1_ISR () interrupt 3{} /* not used */
void serial_ISR () interrupt 4{} /* not used */
由small compact 及large說明,例如:
void fun1(void) small { }
提示:small說明的函式內部變數全部使用內部RAM。關鍵的經常性的耗時的地方可以這樣宣告,以提高執行速度。
在函式前宣告,只對一個函式有效。該函式呼叫過程中將不可被中斷。
在主程式和中斷中都可呼叫的函式,容易產生問題。因為51和PC不同,PC使用堆疊傳遞引數,且靜態變數以外的內部變數都在堆疊中;而51一般使用暫存器傳遞引數,內部變數一般在RAM中,函式重入時會破壞上次呼叫的資料。可以用以下兩種方法解決函式重入:
a、在相應的函式前使用前述“#pragma disable”宣告,即只允許主程式或中斷之一呼叫該函式;
b、將該函式說明為可重入的。如下:
void func(param...) reentrant;
KeilC51編譯後將生成一個可重入變數堆疊,然後就可以模擬通過堆疊傳遞變數的方法。
由於一般可重入函式由主程式和中斷呼叫,所以通常中斷使用與主程式不同的R暫存器組。
另外,對可重入函式,在相應的函式前面加上開關“#pragma noaregs”,以禁止編譯器使用絕對暫存器定址,可生成不依賴於暫存器組的程式碼。
由alien指定。
[dvnews_page=第四章 Keil C51高階程式設計]
本章討論以下內容:
l 絕對地址訪問
l C與彙編的介面
l C51軟體包中的通用檔案
l 段名轉換與程式優化
C51提供了三種訪問絕對地址的方法:
在程式中,用“#include<absacc.h>”即可使用其中定義的巨集來訪問絕對地址,包括:
CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD
具體使用可看一看absacc.h便知
例如:
rval=CBYTE[0x0002];指向程式存貯器的0002h地址
rval=XWORD [0x0002];指向外RAM的0004h地址
直接在資料定義後加上_at_ const即可,但是注意:
(1)絕對變數不能被初使化;
(2)bit型函式及變數不能用_at_指定。
例如:
idata struct link list _at_ 0x40;指定list結構從40h開始。
xdata char text[25b] _at_0xE000;指定text陣列從0E000H開始
提示:如果外部絕對變數是I/O埠等可自行變化資料,需要使用volatile關鍵字進行描述,請參考absacc.h。
此法是利用連線控制指令code xdata pdata /data bdata對“段”地址進行,如要指定某具體變數地址,則很有侷限性,不作詳細討論。
方法是用#pragma語句具體結構是:
#pragma asm
彙編行
#pragma endasm
這種方法實質是通過asm與ndasm告訴C51編譯器中間行不用編譯為彙編行,因而在編譯控制指令中有SRC以控制將這些不用編譯的行存入其中。
C模組與彙編模組的介面較簡單,分別用C51與A51對原始檔進行編譯,然後用L51將obj檔案連線即可,關鍵問題在於C函式與彙編函式之間的引數傳遞問題,C51中有兩種引數傳遞方法。
(1) 通過暫存器傳遞函式引數
最多隻能有3個引數通過暫存器傳遞,規律如下表:
引數數目
char
int
long,float
一般指標
1
2
3
R7
R5
R3
R6 & R7
R4 & R5
R2 & R3
R4~R7
R4~R7
R1~R3
R1~R3
R1~R3
(2) 通過固定儲存區傳遞(fixed memory)
這種方法將bit型引數傳給一個儲存段中:
?function_name?BIT
將其它型別引數均傳給下面的段:?function_name?BYTE,且按照預選順序存放。
至於這個固定儲存區本身在何處,則由儲存模式預設。
(3) 函式的返回值
函式返回值一律放於暫存器中,有如下規律:
return type
Registev
說明
bit
標誌位
由具體標誌位返回
char/unsigned char 1_byte指標
R7
單位元組由R7返回
int/unsigned int 2_byte指標
R6 & R7
雙位元組由R6和R7返回,MSB在R6
long&unsigned long
R4~R7
MSB在R4, LSB在R7
float
R4~R7
32Bit IEEE格式
一般指標
R1~R3
儲存型別在R3 高位R2 低R1
(4) SRC控制
該控制指令將C檔案編譯生成彙編檔案(.SRC),該彙編檔案可改名後,生成彙編.ASM檔案,再用A51進行編譯。
在C51/LiB目錄下有幾個C原始檔,這幾個C原始檔有非常重要的作用,對它們稍事修改,就可以用在自己的專用系統中。
init_mem.C:此檔案是初始化動態記憶體區的程式原始碼。它可以指定動態記憶體的位置及大小,只有使用了init_mem( )才可以調回其它函式,諸如malloc calloc,realloc等。
calloc.c:此檔案是給陣列分配記憶體的原始碼,它可以指定單位資料型別及該單元數目。
malloc.c:此檔案是malloc的原始碼,分配一段固定大小的記憶體。
realloc.c:此檔案是realloc.c原始碼,其功能是調整當前分配動態記憶體的大小。
啟動檔案STARTUP.A51中包含目標板啟動程式碼,可在每個project中加入這個檔案,只要復位,則該檔案立即執行,其功能包括:
l 定義內部RAM大小、外部RAM大小、可重入堆疊位置
l 清除內部、外部或者以此頁為單元的外部儲存器
l 按儲存模式初使化重入堆疊及堆疊指標
l 初始化8051硬體堆疊指標
l 向main( )函式交權
開發人員可修改以下資料從而對系統初始化
常數名 意義
IDATALEN 待清內部RAM長度
XDATA START 指定待清外部RAM起始地址
XDATALEN 待清外部RAM長度
IBPSTACK 是否小模式重入堆疊指標需初始化標誌,1為需要。預設為0
IBPSTACKTOP 指定小模式重入堆疊頂部地址
XBPSTACK 是否大模式重入堆疊指標需初始化標誌,預設為0
XBPSTACKTOP 指定大模式重入堆疊頂部地址
PBPSTACK 是否Compact重入堆疊指標,需初始化標誌,預設為0
PBPSTACKTOP 指定Compact模式重入堆疊頂部地址
PPAGEENABLE P2初始化允許開關
PPAGE 指定P2值
PDATASTART 待清外部RAM頁首址
PDATALEN 待清外部RAM頁長度
提示:如果要初始化P2作為緊湊模式高階地址,必須:PPAGEENAGLE=1,PPAGE為P2值,例如指定某頁1000H-10FFH,則PPAGE=10H,而且連線時必須如下:
L51<input modules> PDATA(1080H),其中1080H是1000H-10FFH中的任一個值。
以下是STARTUP.A51程式碼片斷,紅色是經常可能需要修改的地方:
;------------------------------------------------------------------------------
; This file is part of the C51 Compiler package
; Copyright KEIL ELEKTRONIK GmbH 1990
;------------------------------------------------------------------------------
; STARTUP.A51: This code is executed after processor reset.
;
; To translate this file use A51 with the following invocation:
;
; A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the following
; L51 invocation:
;
; L51 <your object file list>, STARTUP.OBJ <controls>
;
;------------------------------------------------------------------------------
;
; User-defined Power-On Initialization of Memory
;
; With the following EQU statements the initialization of memory
; at processor reset can be defined:
;
; ; the absolute start-address of IDATA memory is always 0
IDATALEN EQU 80H ; the length of IDATA memory in bytes.
;
XDATASTART EQU 0H ; the absolute start-address of XDATA memory
XDATALEN EQU 0H ; the length of XDATA memory in bytes.
;
PDATASTART EQU 0H ; the absolute start-address of PDATA memory
PDATALEN EQU 0H ; the length of PDATA memory in bytes.
;
; Notes: The IDATA space overlaps physically the DATA and BIT areas of the
; 8051 CPU. At minimum the memory space occupied from the C51
; run-time routines must be set to zero.
;------------------------------------------------------------------------------
;
; Reentrant Stack Initilization
;
; The following EQU statements define the stack pointer for reentrant
; functions and initialized it:
;
; Stack Space for reentrant functions in the SMALL model.
IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.
;
; Stack Space for reentrant functions in the LARGE model.
XBPSTACK EQU 0 ; set to 1 if large reentrant is used.
XBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
;
; Stack Space for reentrant functions in the COMPACT model.
PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
PBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
;
;------------------------------------------------------------------------------
;
; Page Definition for Using the Compact Model with 64 KByte xdata RAM
;
; The following EQU statements define the xdata page used for pdata
; variables. The EQU PPAGE must conform with the PPAGE control used
; in the linker invocation.
;
PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
PPAGE EQU 0 ; define PPAGE number.
;
;------------------------------------------------------------------------------
putchar.c
putchar.c是一個低階字元輸出子程,開發人員可修改後應用到自己的硬體系統上,例如向CLD或LEN輸出字元。
預設:putchar.c是向串列埠輸出一個字元XON|XOFF是流控標誌,換行符“/*n”自動轉化為回車/換行“/r/n”。
getkey.c
getkey函式是一個低階字元輸入子程,該程式可用到自己硬體系統,如矩陣鍵盤輸入中,預設時通過串列埠輸入字元。
還包括對Watch-Dog有獨特功能的INIT.A51函式以及對8×C751適用的函式,可參考原始碼。
C51編譯器生成的目標檔案存放於許多段中,這些段是程式碼空間或資料空間的一些單元,一個段可以是可重定位的,也可以是絕對段,每一個可重定位的段都有一個型別和名字,C51段名有以下規定:
每個段名包括字首與模組名兩部分,字首表示儲存型別,模組名則是被編譯的模組的名字,例如:
?CO?main1 :表示main1模組中的程式碼段中的常數部分
?PR?function1?module 表module模組中函式function1的可執行段,具體規定參閱手冊。
C51編譯器是一個具有優化功能的編譯器,它共提供六級優化功能。確保生成目的碼的最高效率(程式碼最少,執行速度最快)。具體六級優化的內容可參考幫助。
在C51中提供以下編譯控制指令控制程式碼優化:
OPTIMIZE(SJXE):儘量採用子程式,使程式程式碼減少。
NOAREGS:不使用絕對暫存器訪問,程式程式碼與暫存器段獨立。
NOREGPARMS:引數傳遞總是在區域性資料段實現,程式程式碼與低版本C51相容。
OPTIMIZE(SIZE)AK OPTIMIZE(speed)提供6級優化功能,預設為: OPTIMIZE(6,SPEED)。
[dvnews_page=第五章 Keil C51庫函式參考]
C51強大功能及其高效率的重要體現之一在於其豐富的可直接呼叫的庫函式,多使用庫函式使程式程式碼簡單,結構清晰,易於除錯和維護,下面介紹C51的庫函式系統。
C51提供的本徵函式是指編譯時直接將固定的程式碼插入當前行,而不是用ACALL和LCALL語句來實現,這樣就大大提供了函式訪問的效率,而非本徵函式則必須由ACALL及LCALL呼叫。
C51的本徵庫函式只有9個,數目雖少,但都非常有用,列如下:
_crol_,_cror_:將char型變數迴圈向左(右)移動指定位數後返回
_iror_,_irol_:將int型變數迴圈向左(右)移動指定位數後返回
_lrol_,_lror_:將long型變數迴圈向左(右)移動指定位數後返回
_nop_: 相當於插入NOP
_testbit_: 相當於JBC bitvar測試該位變數並跳轉同時清除。
_chkfloat_: 測試並返回源點數狀態。
使用時,必須包含#inclucle <intrins.h>一行。
如不說明,下面談到的庫函式均指非本徵庫函式。
例如8031、8051均為REG51.h其中包括了所有8051的SFR及其位定義,一般系統都必須包括本檔案。
該檔案中實際只定義了幾個巨集,以確定各儲存空間的絕對地址。
其中包括拷貝比較移動等函式如:
memccpy memchr memcmp memcpy memmove memset
這樣很方便地對緩衝區進行處理。
流函式通8051的串列埠或使用者定義的I/O口讀寫資料,預設為8051串列埠,如要修改,比如改為LCD顯示,可修改lib目錄中的getkey.c及putchar.c原始檔,然後在庫中替換它們即可。
bit isalnum(char c);
bit isalpha(char c);
bit iscntrl(char c);
bit isdigit(char c);
bit isgraph(char c);
bit islower(char c);
bit isprint(char c);
bit ispunct(char c);
bit isspace(char c);
bit isupper(char c);
bit isxdigit(char c);
bit toascii(char c);
bit toint(char c);
char tolower(char c);
char __tolower(char c);
char toupper(char c);
char __toupper(char c);
unsigned char _crol_(unsigned char c,unsigned char b);
unsigned char _cror_(unsigned char c,unsigned char b);
unsigned char _chkfloat_(float ual);
unsigned int _irol_(unsigned int i,unsigned char b);
unsigned int _iror_(unsigned int i,unsigned char b);
unsigned long _irol_(unsigned long l,unsigned char b);
unsigned long _iror_(unsigned long L,unsigned char b);
void _nop_(void);
bit _testbit_(bit b);
char getchar(void);
char _getkey(void);
char *gets(char * string,int len);
int printf(const char * fmtstr[,argument]…);
char putchar(char c);
int puts (const char * string);
int scanf(const char * fmtstr.[,argument]…);
int sprintf(char * buffer,const char *fmtstr[;argument]);
int sscanf(char *buffer,const char * fmtstr[,argument]);
char ungetchar(char c);
void vprintf (const char *fmtstr,char * argptr);
void vsprintf(char *buffer,const char * fmtstr,char * argptr);
float atof(void * string);
int atoi(void * string);
long atol(void * string);
void * calloc(unsigned int num,unsigned int len);
void free(void xdata *p);
void init_mempool(void *data *p,unsigned int size);
void *malloc (unsigned int size);
int rand(void);
void *realloc (void xdata *p,unsigned int size);
void srand (int seed);
void *memccpy (void *dest,void *src,char c,int len);
void *memchr (void *buf,char c,int len);
char memcmp(void *buf1,void *buf2,int len);
void *memcopy (void *dest,void *SRC,int len);
void *memmove (void *dest,void *src,int len);
void *memset (void *buf,char c,int len);
char *strcat (char *dest,char *src);
char *strchr (const char *string,char c);
char strcmp (char *string1,char *string2);
char *strcpy (char *dest,char *src);
int strcspn(char *src,char * set);
int strlen (char *src);
char *strncat (char 8dest,char *src,int len);
char strncmp(char *string1,char *string2,int len);
char strncpy (char *dest,char *src,int len);
char *strpbrk (char *string,char *set);
int strpos (const char *string,char c);
char *strrchr (const char *string,char c);
char *strrpbrk (char *string,char *set);
int strrpos (const char *string,char c);
int strspn(char *string,char *set);
[dvnews_page=第六章 Keil C51例子:Hello.c]
Hello位於/C51/excmples/Hello/目錄,其功能是向串列埠輸出“Hello,world”整個程式如下:
#pragma DB OE CD
#indule <reg51.h>
#include<stdio.h>
void main(void)
{
SCOn=0x50;
TMOD=0x20
TH1=0xf3;
Tri=1;
TI=1;
printf(“Hello,world /n”);
while(1) { }
}
(1) file_new新建一個hello.c檔案,輸入如上內容或直接用目錄下原始檔。
(2) file_save或工具欄將檔案存檔。
(3) project_new project建立一個project名為hello,並在其中加入hello.c。
這時該project已是開啟狀態,或用open project開啟已存在的project。
(4) option_C51 compiler中選出至少包括兩項DB OE。
(5) option_dscope Debugger選中hello/DS51.INI
檢視DS51.INI看其是否為:
“load…/…/BIN/8051.DLL
map 0, 0xffff”
否則修改。
(6) 在option_make選make檔案順序。
(7) project選Build project,看是否有語法錯誤,若無則生成HEX檔案,若有則修改原始檔後重復以上部分步驟。
(8) run_dScope debugger進入dScope51後裝入hello則可用go直接執行看serial視窗有無輸出,正常每系統執行一次,serial視窗均出現一個“Hello,world”表明執行無誤。
(1) 進入Ishell 用Setup editer選擇編輯器。
然後單擊Edit或用Edit命令編輯hello.c原始檔,存檔,也可以在files視窗中直接選中hello.c。
(2) 用cd改換project目錄至hello目錄。
(3) 在setup_target一專案選8051。
(4) 在setup_C51中輸出DB OE。
(5) 在setup_project輸入project名hello。
(6) 在setup_save儲存Ishell.CFG檔案。
(7) 編輯一個Link檔案hello.lin中有“hell.obj”一行。
(8) 由游標落在files選單中的Hello.c上,單擊“translate”,如無語法錯,再擊“link”,則Hex檔案生成。
(9) 單擊Simulate如在8051.CDF中選Simulate為dScope則進入dScope除錯直接“Go”,看serial視窗輸出為“Hello.world”。
(10) 如程式有誤修改原始碼後不必再translate或link了,只要一步Amake即可。
若project中包括不止一個檔案,在DOS的Ishell中不能用Translate編譯,而應建立bat檔案,直接在命令窗編譯,然後link連線。
如還需用Translate則只能多個檔案分別編譯,然後連線。
[dvnews_page=第七章 Keil C51的程式碼效率]
C51程式編譯生成彙編程式碼的效率,是由許多因素共同決定的,對於Keil C51,主要受以下兩種因素影響:
儲存模式決定了預設變數的儲存空間,而訪問各空間變數的彙編程式碼的繁簡程度決定了程式碼率的高低。
例如:一個整形變數i,如放於記憶體18H、19H空間,則++i的操作編譯成四條語句:
INC 0x19
MOV A,0x19
JNZ 0x272D
INC 0x18
0x272D:
而如果放於外存空間0000H、0001H則++i的操作編譯成九條語句:
MOV DPTR,0001
MOVX A,@ DPTR
INC A
MOVX @ DPTR,A
JNz #5
MOV OPTR,#0000
MOVX A,@DPTR
INC A
MOVX @ DPTR,A
就彙編之後的語句而言,對外部儲存器的操作較內部儲存器操作程式碼率要低得多,生成的語句為記憶體的兩倍以上,而程式中有大量的這種操作,可見儲存模式對程式碼率的響了。
因此程式設計的原則是
1、儲存模式從small-Compact-large依次選擇,實在是變數太多,才選large模式。
2、即使選擇了large模式,對一些常用的區域性的或者可放於記憶體中的變數,最好放於記憶體中,以儘量提高程式的程式碼率。
程式的結構單元包括模組、函式等等。同樣的功能,如果結構越複雜,其所涉及的操作、變數、功能模組函式等就越多,較之結構性好,程式碼簡單的程式其程式碼率自然就低得多。
此外程式的執行控制語句,也是影響程式碼率的關鍵因素,例如:switch -case語句,許多編譯器都把它們譯得非常複雜,Keil C51也不例外,相對較為簡易的Switch-case語句,編譯成跳轉指令形式,程式碼率較高,但對較為複雜的Switch-Case,則要呼叫一個系統庫函式?C?ICASE進行處理,非常複雜。
再如if( ),while( ),等語句也是程式碼相對較低的語句,但編譯以後比switch-case要高得多。
因此建議設計者儘量少用switch-case之類語句來控制程式結構,以提高程式碼率。
除以上兩點外,其它因素也會對程式碼率產生影響,例如:
是否用暫存器傳遞引數 即NOAREGS選項是否有
是否包括除錯資訊:即DEBUG選項
是否包括擴充套件的除錯資訊:即BJECTEXTEND
[dvnews_page=第八章 dScope for Windows使用詳解]
可設定其它各種除錯視窗,設定斷點、觀察點,修改地址空間,載入檔案等等;
支援使用者程式的各種顯示方式,可連續執行,單步執行使用者程式,並可線上 彙編;
支援命令列的輸入;
可設定所要觀察的變數、表示式等;
顯示內部暫存器的內容,程式執行次數等;
顯示串列埠接收和傳送的資料;
顯示所要觀察的各程式段佔用CPU的空間;
顯示所選擇的記憶體中的資料;
顯示各種符號名稱,包括專有符號,使用者自定義符號(函式名、變數、標號)等;
動態顯示當前執行的程式段的函式呼叫關係;
提供當前模組內各程式段中被執行程式碼的比率;。
可顯示I/O口,定時器,中斷,串列埠等外圍裝置狀態;
在uVision的Option選單dScope Debugger中指定dScope的初始化檔案,用uVision的RUN啟動dScope將自動載入此初始化檔案,自動執行其中命令;
下面是一個例子,可以看出調入一個除錯程式碼的過程。Ds51.ini:
load 8051.dll
load test
slog>>test.log
xtal=11.0592
define button "go to main","g,main"
ws RevCounter
ws rm.r
g,main
PA RESET
PA serial
PA timer0
方法1:命令列
WS expression [, numberbase ] [ LINE ]
其中numberbase為顯示數制,10對應10進位制,16對應16進位制,預設為16進位制。LINE為單行顯示,預設為多行顯示。
方法2:setup->Watchpoints,在對話方塊中輸入變數
d i(x,d):起始地址,終止地址
d 變數名
View->Call-stack->Show invocation,可以跟蹤呼叫過程;
在裝入8051.dll後,在dScope的主選單中將增加Peripherial,其有4個字選單:
I/0 port:Pi埠狀態
Interrupt:中斷設定
Timer:定時器中斷狀態
Serial:串列埠中斷狀態
設定相應的中斷請求標誌位即可產生中斷。
PA用來分析一段程式碼執行佔用CPU的百分比。定義:
命令列 PA func_name
dScope除了用命令列的方式進行除錯以外,還可將各種除錯命令彙集於一個除錯檔案中,然後呼叫該檔案,就可達到自動測試使用者原始碼的目的。dScope的命令檔案支援C/PL/M的格式,因而編制除錯命令檔案與編制C語言程式有些類似。
(1) 地址空間分段
dScope提供的最大可用空間為16M,實際上我們只用以下三段:
① 內部資料空間段(0X00段或D段)
0X00:0X0000~0X00:0XFFFF(對MSC51而言為0X00:0X00FF)
② 外部資料空間段(0X01段式或X段)
0X01:0X0000~0X01~0XFFFF
③ 程式空間段(0XFF段或C段)
0XFF:0X0000~0XFF:0XFFFF
(2) 地址空間型別
C:程式碼空間
D:內部直接定址空間
I: 內部間接定址空間
X:外部資料空間
B:位定址空間
P:I/O口
EB:擴充套件的位定址空間(MCS251專有)
ED:擴充套件的資料空間(MCS251專有)
CO:常數空間(MCS251專有)
HC:正常數空間(MCS251專有)
dScope支援十六進位制、八進位制、十進位制、二進位制常數,其後綴分別為H、Q(O)、T(或無)、Y;
dScope不區分常量的大、小寫。
(1) 整型常量
分為整型(int),無符號整型(uint,00rd),長整型(long),無符號長整型(Wlong、Word)。
(2) 浮點型常量
與ANSI C相同。
(3) 字串常量
與ANSI C相同
(4) 字元常量
分為字元型(Char)和無符號字元型(Uchar)一種。
(5) 行號常數
指使用者程式中的行號,實際上是個地址
(6) 位常量(Bit):
0和1
(7) 地址常數
地址常數的種類很多,地址常數不同於行號常數,行號常數就是一個地址,而地址數被引用時,實際上是取該地址中的資料。
C:程式碼地址常數,如C:0X0012或0XFF:0X0012
D:內部直接定址地址常數,如D:0X0068或0X00:0X0068
I:內部間按定址地址常數,如I:0X0010或0X00:0X0010
X:外部資料空間地址常數,如X:0X0028或0X01:0X0028
B:位地址常數,如B:0X20或B:0X24.0
EB:擴充套件的位地址常數(MCS251專有),
ED:擴充套件的資料空間地址常數(MCS251專有)
CO:常數空間地址常數(MCS251專有)
HC:正常數空間地址常數(MCS251專有)
(8) 識別符號常量
即使用者源程式中的標號、函式名等,實際上代表某一地址。
(9) 使用者源程式中定義的常數
dScope所支援的變數名或識別符號最多可由31個字元組成,第一個字母為A~Z,a~z,下劃線或問號,後續字元可為字母、數字、下劃線和問號。除CPU變數和系統變數外,dScope不支援全域性變數,但可視“define”命令定義的變數為全域性變數。
Dscope所支援的變數分為以下幾種(變數名稱不區分大、小寫),支援型別轉換:
(1) 整型變數
分為整型變數(int)、無符號整型變數(uint/word),長整型(Long) 、無符號長整型(Ulong/dword)。
(2) 浮點型變數(float)
與ANSI C相同。
(3) 字元型變數L
分為字元型(char)變數和無符號字元型(Uchar)
(4) 位變數(Bit)
(5) 系統變數
dScope自己定義了一系列內部變數,使用者可對這些變數進行讀或讀/寫操作, 可被使用者自定義數所引用。
a. Cycles (Read Only)
32位變數(Ulong),指示當前程式執行已花費的指令週期(cycle)。
b. Ramsize(R/W)
16位變數(Uint),指示內部可直接定址的資料空間大小。
c. Radix(R/N)
8位變數(Uchar),決定輸出的數制
Radix=0X0A (10進位制),Radix=0X10 (16進位制)
d. -IIP-(R/W)
8位變數(Uchar),指示當前的中斷巢狀數目。
e. $ (R/W)
32位變數(Ulong),指出PC值,通過對其進行寫操作,可改變程式執行的流程。
f. Itrace (R/W)
8位變數(Uchar),決定是否對程式執行情況進行記錄
Itrace=1,使能記錄操作
Itrace=0,根本上記錄操作
g. __Break__(R/W)
8位變數(Uchar) __Break__=1,中止程式的執行
h. __Mode__和__Frame size__是MCS 251專有的變數。
(6) CPU變數
即R0~R7、A、C(位變數)、B、DPTR及特殊功能暫存器變數,對這些變數均可進行讀、寫操作。
(7) 使用者源程式中定義的變數、陣列、結構等
dScope支援ANSI C的運算子,包括算術運算子,邏輯運算子,關係運算符。
以運算子將dScope所支援的常量、變數、函式等連線在一起,就構成了dScope的表示式。
dScope不支援在命令檔案中定義陣列,但可引用使用者程式中的陣列,引用方式如同C。
dScope不支援在命令檔案中定義結構和聯合,但可引用使用者程式中的結構和聯合,引用方式如同C,但如要輸出整個結構或聯合的結果,就要用命令“OBJ”。
不可自定義指標,但支援使用者源程式中的指標變數。
dScope提供了一系列除錯命令。在命令檔案中,dScope只支援這些語句及前述定義的表示式,C語言的語句均不被支援,但在命令檔案所包含的使用者自定義函式(非使用者源程式中的函式)中支援C語句,但使用者自定義函式中同樣不支援陣列、結構、聯合和指標。
(1) ASM
線上彙編命令,格式如下:
ASM C:0Xnnnn (或標號);設定插入彙編指令的地址
ASM 彙編指令
ASM 彙編指令
插入完畢後,在debug視窗內選擇“Assemble->Assemble”完成編譯。
(2) Assign
序列口分配指令,格式如下:
Assign channel<unreg>outreg
對MCS51為:Assign Win<SOIN> Soot
但目前的dScope版本並未提供完整串列埠視窗功能。
(3) Define
使用者自定義變數指令,格式如下:
Define <型別> <變數名>
型別一為如前所述的變數型別,Define指令定義的變數可能為全域性變數,可為使用者自定義函式所引用。
(4) Display
記憶體顯示命令,格式如下二:
D 起始地址,結束地址
地址如前所述的地址常數,識別符號常量。
(5) Enter
記憶體修改指令,格式如下:
E 型別地址=表示式 [表示式2],[……]
型別如前所述,地址如前所述的地址常數。表示式如前所述,但如果是函式名稱(含標號、指標變數),則關鍵字E→EP
(6) Map/Reset map
Map為記憶體段修改指令,Reset map將記憶體段復位或預設值。
(7) Object
用以引用使用者源程式中的結構(聯合)、陣列、格式如下:
Obj表示式 [n,],[Line]
表示式為使用者源程式中的陣列,結構(聯合)名稱。當Line預設時,數目、結構(聯合)的內容按n行輸出;如有Line,則單行輸出。
(8) U
反彙編命令,格式如下:
U [地址]
地址包括地址常 數及識別符號常量,指明反彙編的起始地址。
(9) WK
觀察點刪除命令,格式如下:
WK n1[n2 ],[……] ;刪除指定的觀察點,n為字元型,整型
常數
WK * ;刪除所有的觀察點
(10) WS
觀察點設定命令,格式如下:
WS 表示式[,n][LINE]
關鍵字LINE存在時,觀察點表示式單行輸出
LINE預設時,觀察點表示式n行輸出。
(11) G
連續執行命令,格式如下:
G [起始地址],[終止地址]
地址為識別符號常量或地址常數,地址預設時,為連續執行。
(12) T/P
單步執行指令,格式如下:
T/P n ;n指至單行執行的步數,P指給使用者當呼叫某函式時,把它作為一步處理,並不進入該函式執行。
(13) PA
效能分析操作指令,其分以下幾種:
PA
顯示當前所設定的效能分析程度段
PA Kill *
刪除當前所設定的所有效能分析程式段
PA Kill n1 [,n2],[……]
刪除指定的效能分析程式段
PA 地址範圍
設定效能分析程式段,地址範圍可以起始地址和結束地址的方式給出,也可給出函式名,行號範圍。
PA Reset
復位效能分析視窗(PA Windows),清除所有的記錄。
(14) BD
斷點失效命令,格式如下:
BD n1 [,n2],[,……] ;disable指定的斷點
DB * ;disable所有的斷點
(15) BE
斷點使能命令,格式如下:
BE M [,n2],[,……] ;使能指定的斷點
BE * ;使能所有的斷點
(16) BK
斷點刪除指令,格式如下:
BK M[,n2],[,……] ;刪除指定的斷點
BK * ;刪除所有的斷點
(17) BL
斷點顯示指令,顯示所有被定義的斷點。
(18) BS
斷點定義指令,dScope支援多達40個斷點,具體格式如下:
a.BS 表示式[,count] [,“cmd”]
count:經過該斷點的次數 [選項]
“cmd”:斷點到達後附帶執行的dScope命令(連項)
表示式一個條件表示式,此時該斷點稱為條件斷點(運算子為&.&&,<<=>,>=,= =,!=)
BS READ 表示式 [,count] [,“cmd”]
BS WRITE 表示式 [,count] [“cmd”]
BS READWRITE 表示式 [,count] [,“cmd”]
以上三種斷點稱訪問式(Access斷點),當某一址或變數被訪問(R/W)或某些值被讀寫時,程式被中斷。
(19) Define button
圖示定義指令,用於當視窗(Toolbox)
(20) !
DOS視窗Open命令,以“EXIT”命令退出DOS視窗。
(21) Include
檔案包含命令,格式如下:
Include [路徑] 檔名
dScope支援以檔案包含的方式調入並執行除錯命令檔案,使用者自定義函式檔案,除錯命令檔案可以有後綴,也可無後綴。
(22) Load
載入命令,格式如下:
Load [路徑] 檔名
Load指令能夠載入的檔案必須具有以下格式之一。
Intel Hex/Hex 386格式
Intel Object (OMF_51) 格式
Intel Object (OMF-251) 格式
dScope的CPU驅動檔案(.DLL)
(23) LOG
Command Window存檔指令,用於將Command Windows中的內容輸出到指定的檔案中,格式如下:
LOG > [路徑]檔名 ;建立一個新檔案
LOG >> [路徑]檔名 ;將Command Windows的內容輸出到某個已
存在的檔案中。
LOG OFF 完成輸出操作並開閉該檔案
LOG指令只將LOG>或LOG>>與LOG OFF指令之間的操作命令存入該指定檔案。
(24) Reset
復位指令,具體格式如下:
Reset ;執行dScope的復位
Reset Map ;復位外部資料空間
Reset Var ;復位SET指令定義的變數
(25) Save
該指令將一段記憶體映象以19EX386/HEX的格式存檔,具體格式如下:
Save 路徑 檔名:地址1、地址2
地址1、地址2指所要儲存的空間範圍,既可是識別符號,也可是址常數。
(26) SET
該指令回來定義dScope目的碼預定義變數的含義,這些預定義變數包括以下二種:
SRC ;指出所在的路徑
F1~F12;對應於鍵盤上的12個功能鍵,定義這些功能鍵的
含義。
SET指令的格式為:
SET 變數=“字串”
SET 變數
dScope支援三種函式,即dScope預定義函式,使用者自定義函式和訊號函式,分別詳述如下:
(1) dScope預定義函式
dScope號提供8個預定義函式(可視為dScope的庫函式)
①Void Printf(“String”,輸出表列)
螢幕列印函式,與ANSI C的Printf ( ) 函式相同
②Void exec(“Command__String”)
Command__String為一有效的命令字串,此函式用於在執行使用者自定義函式的過程中執行dScope命令,這個函式提供了一個很重要的編制測試命令檔案的方法。
③int getint(“Prompt__String”);從鍵盤輸入一個整數
int getlong (“Prompt__String”);從鍵盤輸入一個長整數
float getfloat (“Prompt__String”);從鍵盤輸入一個浮點數
以上這三個函式被執行時,dScope會彈出一個dialog box等待使用者輸入資料,其標題欄上是“Prompt__String”,利用這個函式,不僅可以為變數賦值,也可使使用者得以看清前一階段的測試結果。
④int rand (int seed)
該函式會輸出一個隨機數(-32768~32768)
⑤Void memeset (ulorg start , ulong end ,uchar val)
該函式用於給地址範圍(Start__end)內的記憶體賦值(Val)
⑥Void twatch (Long cycles)
定時函式,時間由(Long cycles)決定,它是以指令週期計數的,它也 用於產生一個訊號波形,該函式必須用於訊號函式中。
(2) 使用者自定義函式
這類函式不同於使用者源程式中的數函,其定義格式為
Func 返回型別 函式名(引數序列)
{
語句
}
返回型別如前所述的變數型別
使用者自定義函式中的語句與ANSI C相似,只是不支援陣列結構、聯合、指標,可引用dScope系統變數,define語句定義的變數和使用者源程式變數,不支援dScope命令,如想在函式中執行dScope命令,要藉助於exec(“Command__String”)函式,可引用dScope預定義的函式(除了twatch ( )函式),不支援ANSI C的庫函式。
(3) 訊號函式
用於產生具有某一波形的訊號,定義格式為:
Signal返回型別函式名(引數長列){
語句
}
訊號函式主要是利用twatch ( )函式,目前dScope版本在提供這一功能上面還有一定問題。
(4) dScope函式與ANSI函式的區別
① 不支援條件彙編
② 不支援標頭檔案
③ 無變數的初始化
④ 不支援陣列、結構、指標
⑤ 呼叫方式不同,自定義函式和訊號函式首先要包含一個函式檔案之中,然而在測試命令檔案中以Inclule指令呼叫該函式檔案,最後才能以函式名呼叫之。
⑥ 函式呼叫只支援傳值方式。