新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > KeilC51使用詳解 (二)

        KeilC51使用詳解 (二)

        作者: 時間:2016-11-18 來源:網絡 收藏
        第三章 Keil C51 vs 標準C

        深入理解并應用C51對標準ANSIC的擴展是學習C51的關鍵之一。因為大多數擴展功能都是直接針對8051系列CPU硬件的。大致有以下8類:l 8051存儲類型及存儲區域l 存儲模式l 存儲器類型聲明l 變量類型聲明l 位變量與位尋址l 特殊功能寄存器(SFR)l C51指針l 函數屬性具體說明如下(8031為缺省CPU)。

        本文引用地址:http://www.104case.com/article/201611/315904.htm

        第一節 Keil C51擴展關鍵字

        C51 V4.0版本有以下擴展關鍵字(共19個):_at_ idata sfr16 alien interrupt smallbdata large _task_ Code bit pdatausing reentrant xdata compact sbit data sfr

        第二節 內存區域(Memory Areas):

        1. Pragram Area:

        由Code說明可有多達64kBytes的程序存儲器

        2. Internal Data Memory:

        內部數據存儲器可用以下關鍵字說明:data:直接尋址區,為內部RAM的低128字節 00H~7FHidata:間接尋址區,包括整個內部RAM區 00H~FFHbdata:可位尋址區, 20H~2FH

        3. External Data Memory

        外部RAM視使用情況可由以下關鍵字標識:xdata:可指定多達64KB的外部直接尋址區,地址范圍0000H~0FFFFHpdata:能訪問1頁(25bBytes)的外部RAM,主要用于緊湊模式(Compact Model)。

        4. Speciac Function Register Memory

        8051提供128Bytes的SFR尋址區,這區域可位尋址、字節尋址或字尋址,用以控制定時器、計數器、串口、I/O及其它部件,可由以下幾種關鍵字說明:sfr:字節尋址 比如 sfr P0=0x80;為PO口地址為80H,“=”后H~FFH之間的常數。sfr16:字尋址,如sfr16 T2=0xcc;指定Timer2口地址T2L=0xcc T2H=0xCDsbit:位尋址,如sbit EA=0xAF;指定第0xAF位為EA,即中斷允許還可以有如下定義方法:sbit 0V=PSW^2;(定義0V為PSW的第2位)sbit 0V=0XDO^2;(同上)或bit 0V-=0xD2(同上)。

        第三節 存儲模式

        存儲模式決定了沒有明確指定存儲類型的變量,函數參數等的缺省存儲區域,共三種:

        1. Small模式

        所有缺省變量參數均裝入內部RAM,優點是訪問速度快,缺點是空間有限,只適用于小程序。

        2. Compact模式

        所有缺省變量均位于外部RAM區的一頁(256Bytes),具體哪一頁可由P2口指定,在STARTUP.A51文件中說明,也可用pdata指定,優點是空間較Small為寬裕速度較Small慢,較large要快,是一種中間狀態。

        3. large模式

        所有缺省變量可放在多達64KB的外部RAM區,優點是空間大,可存變量多,缺點是速度較慢。提示:存儲模式在C51編譯器選項中選擇。

        第四節 存儲類型聲明

        變量或參數的存儲類型可由存儲模式指定缺省類型,也可由關鍵字直接聲明指定。各類型分別用:code,data,idata,xdata,pdata說明,例:data uar1char code array[ ]=“hello!”;unsigned char xdata arr[10][4][4];

        第五節 變量或數據類型

        C51提供以下幾種擴展數據類型:bit 位變量值為0或1sbit 從字節中定義的位變量 0或1sfr sfr字節地址 0~255sfr16 sfr字地址 0~65535其余數據類型如:char,enum,short,int,long,float等與ANSI C相同。

        第六節 位變量與聲明

        1. bit型變量

        bit型變量可用變量類型,函數聲明、函數返回值等,存貯于內部RAM20H~2FH。注意:(1) 用#pragma disable說明函數和用“usign”指定的函數,不能返回bit值。(2) 一個bit變量不能聲明為指針,如bit *ptr;是錯誤的(3) 不能有bit數組如:bit arr[5];錯誤。

        2. 可位尋址區說明20H-2FH

        可作如下定義:int bdata i;char bdata arr[3],然后:sbit bito=in0;sbit bit15=I^15;sbit arr07=arr[0]^7;sbit arr15=arr[i]^7;

        第七節 Keil C51指針

        C51支持一般指針(Generic Pointer)和存儲器指針(Memory_Specific Pointer).

        1. 一般指針

        一般指針的聲明和使用均與標準C相同,不過同時還可以說明指針的存儲類型,例如:long * state;為一個指向long型整數的指針,而state本身則依存儲模式存放。char * xdata ptr;ptr為一個指向char數據的指針,而ptr本身放于外部RAM區,以上的long,char等指針指向的數據可存放于任何存儲器中。一般指針本身用3個字節存放,分別為存儲器類型,高位偏移,低位偏移量。

        2. 存儲器指針

        基于存儲器的指針說明時即指定了存貯類型,例如:char data * str;str指向data區中char型數據int xdata * pow; pow指向外部RAM的int型整數。這種指針存放時,只需一個字節或2個字節就夠了,因為只需存放偏移量。

        3. 指針轉換

        即指針在上兩種類型之間轉化:l 當基于存儲器的指針作為一個實參傳遞給需要一般指針的函數時,指針自動轉化。l 如果不說明外部函數原形,基于存儲器的指針自動轉化為一般指針,導致錯誤,因而請用“#include”說明所有函數原形。l 可以強行改變指針類型。

        第八節 Keil C51函數

        C51函數聲明對ANSI C作了擴展,具體包括:

        1. 中斷函數聲明:

        中斷聲明方法如下: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 */

        2. 通用存儲工作區

        3. 選通用存儲工作區由using x聲明,見上例。

        4. 指定存儲模式

        由small compact 及large說明,例如:void fun1(void) small { }提示:small說明的函數內部變量全部使用內部RAM。關鍵的經常性的耗時的地方可以這樣聲明,以提高運行速度。

        5. #pragma disable

        在函數前聲明,只對一個函數有效。該函數調用過程中將不可被中斷。

        6. 遞歸或可重入函數指定

        在主程序和中斷中都可調用的函數,容易產生問題。因為51和PC不同,PC使用堆棧傳遞參數,且靜態變量以外的內部變量都在堆棧中;而51一般使用寄存器傳遞參數,內部變量一般在RAM中,函數重入時會破壞上次調用的數據。可以用以下兩種方法解決函數重入:a、在相應的函數前使用前述“#pragma disable”聲明,即只允許主程序或中斷之一調用該函數;b、將該函數說明為可重入的。如下:void func(param...) reentrant;KeilC51編譯后將生成一個可重入變量堆棧,然后就可以模擬通過堆棧傳遞變量的方法。由于一般可重入函數由主程序和中斷調用,所以通常中斷使用與主程序不同的R寄存器組。另外,對可重入函數,在相應的函數前面加上開關“#pragma noaregs”,以禁止編譯器使用絕對寄存器尋址,可生成不依賴于寄存器組的代碼。

        7. 指定PL/M-51函數

        由alien指定。

        第四章 Keil C51高級編程

        本章討論以下內容:l 絕對地址訪問l C與匯編的接口l C51軟件包中的通用文件l 段名轉換與程序優化

        第一節 絕對地址訪問

        C51提供了三種訪問絕對地址的方法:

        1. 絕對宏:

        在程序中,用“#include”即可使用其中定義的宏來訪問絕對地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD具體使用可看一看absacc.h便知例如:rval=CBYTE[0x0002];指向程序存貯器的0002h地址rval=XWORD [0x0002];指向外RAM的0004h地址

        2. _at_關鍵字

        直接在數據定義后加上_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。

        3. 連接定位控制

        此法是利用連接控制指令code xdata pdata /data bdata對“段”地址進行,如要指定某具體變量地址,則很有局限性,不作詳細討論。

        第二節 Keil C51與匯編的接口

        1. 模塊內接口

        方法是用#pragma語句具體結構是:#pragma asm匯編行#pragma endasm這種方法實質是通過asm與ndasm告訴C51編譯器中間行不用編譯為匯編行,因而在編譯控制指令中有SRC以控制將這些不用編譯的行存入其中。

        2. 模塊間接口

        C模塊與匯編模塊的接口較簡單,分別用C51與A51對源文件進行編譯,然后用L51將obj文件連接即可,關鍵問題在于C函數與匯編函數之間的參數傳遞問題,C51中有兩種參數傳遞方法。(1) 通過寄存器傳遞函數參數最多只能有3個參數通過寄存器傳遞,規律如下表:

        參數數目charintlong,float一般指針
        123R7R5R3R6 & R7R4 & R5R2 & R3R4~R7R4~R7R1~R3R1~R3R1~R3
        (2) 通過固定存儲區傳遞(fixed memory)這種方法將bit型參數傳給一個存儲段中: ?function_name?BIT將其它類型參數均傳給下面的段:?function_name?BYTE,且按照預選順序存放。至于這個固定存儲區本身在何處,則由存儲模式默認。(3) 函數的返回值函數返回值一律放于寄存器中,有如下規律:
        return typeRegistev說明
        bit標志位由具體標志位返回
        char/unsigned char 1_byte指針R7單字節由R7返回
        int/unsigned int 2_byte指針R6 & R7雙字節由R6和R7返回,MSB在R6
        long&unsigned longR4~R7MSB在R4, LSB在R7
        floatR4~R732Bit IEEE格式
        一般指針R1~R3存儲類型在R3 高位R2 低R1
        (4) SRC控制該控制指令將C文件編譯生成匯編文件(.SRC),該匯編文件可改名后,生成匯編.ASM文件,再用A51進行編譯。

        第三節 Keil C51軟件包中的通用文件

        在C51/LiB目錄下有幾個C源文件,這幾個C源文件有非常重要的作用,對它們稍事修改,就可以用在自己的專用系統中。

        1. 動態內存分配

        init_mem.C:此文件是初始化動態內存區的程序源代碼。它可以指定動態內存的位置及大小,只有使用了init_mem( )才可以調回其它函數,諸如malloc calloc,realloc等。calloc.c:此文件是給數組分配內存的源代碼,它可以指定單位數據類型及該單元數目。malloc.c:此文件是malloc的源代碼,分配一段固定大小的內存。realloc.c:此文件是realloc.c源代碼,其功能是調整當前分配動態內存的大小。

        2. C51啟動文件STARTUP.A51

        啟動文件STARTUP.A51中包含目標板啟動代碼,可在每個project中加入這個文件,只要復位,則該文件立即執行,其功能包括:l 定義內部RAM大小、外部RAM大小、可重入堆棧位置l 清除內部、外部或者以此頁為單元的外部存儲器l 按存儲模式初使化重入堆棧及堆棧指針l 初始化8051硬件堆棧指針l 向main( )函數交權開發人員可修改以下數據從而對系統初始化 常數名 意義IDATALEN 待清內部RAM長度XDATA START 指定待清外部RAM起始地址XDATALEN 待清外部RAM長度IBPSTACK 是否小模式重入堆棧指針需初始化標志,1為需要。缺省為0IBPSTACKTOP 指定小模式重入堆棧頂部地址XBPSTACK 是否大模式重入堆棧指針需初始化標志,缺省為0XBPSTACKTOP 指定大模式重入堆棧頂部地址PBPSTACK 是否Compact重入堆棧指針,需初始化標志,缺省為0PBPSTACKTOP 指定Compact模式重入堆棧頂部地址PPAGEENABLE P2初始化允許開關PPAGE 指定P2值PDATASTART 待清外部RAM頁首址PDATALEN 待清外部RAM頁長度提示:如果要初始化P2作為緊湊模式高端地址,必須:PPAGEENAGLE=1,PPAGE為P2值,例如指定某頁1000H-10FFH,則PPAGE=10H,而且連接時必須如下:L51 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 , STARTUP.OBJ ;;------------------------------------------------------------------------------;; 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 0IDATALEN EQU 80H ; the length of IDATA memory in bytes.;XDATASTART EQU 0H ; the absolute start-address of XDATA memoryXDATALEN EQU 0H ; the length of XDATA memory in bytes.;PDATASTART EQU 0H ; the absolute start-address of PDATA memoryPDATALEN 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.;;------------------------------------------------------------------------------

        3. 標準輸入輸出文件

        putchar.cputchar.c是一個低級字符輸出子程,開發人員可修改后應用到自己的硬件系統上,例如向CLD或LEN輸出字符。缺省:putchar.c是向串口輸出一個字符XON|XOFF是流控標志,換行符“/*n”自動轉化為回車/換行“/r/n”。getkey.cgetkey函數是一個低級字符輸入子程,該程序可用到自己硬件系統,如矩陣鍵盤輸入中,缺省時通過串口輸入字符。

        4. 其它文件

        還包括對Watch-Dog有獨特功能的INIT.A51函數以及對8×C751適用的函數,可參考源代碼。

        第四節 段名協定與程序優化

        1. 段名協定(Segment Naming Conventions)

        C51編譯器生成的目標文件存放于許多段中,這些段是代碼空間或數據空間的一些單元,一個段可以是可重定位的,也可以是絕對段,每一個可重定位的段都有一個類型和名字,C51段名有以下規定:每個段名包括前綴與模塊名兩部分,前綴表示存儲類型,模塊名則是被編譯的模塊的名字,例如:?CO?main1 :表示main1模塊中的代碼段中的常數部分?PR?function1?module 表module模塊中函數function1的可執行段,具體規定參閱手冊。

        2. 程序優化

        C51編譯器是一個具有優化功能的編譯器,它共提供六級優化功能。確保生成目標代碼的最高效率(代碼最少,運行速度最快)。具體六級優化的內容可參考幫助。在C51中提供以下編譯控制指令控制代碼優化:OPTIMIZE(SJXE):盡量采用子程序,使程序代碼減少。NOAREGS:不使用絕對寄存器訪問,程序代碼與寄存器段獨立。NOREGPARMS:參數傳遞總是在局部數據段實現,程序代碼與低版本C51兼容。OPTIMIZE(SIZE)AK OPTIMIZE(speed)提供6級優化功能,缺省為: OPTIMIZE(6,SPEED)。



        關鍵詞: KeilC51使用詳

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 安泽县| 白水县| 获嘉县| 长白| 琼结县| 新竹市| 荥阳市| 东安县| 梨树县| 文成县| 永春县| 闽侯县| 西乡县| 榆中县| 天门市| 松阳县| 长治县| 双江| 织金县| 平湖市| 嘉义县| 开平市| 柳河县| 潮州市| 福鼎市| 正安县| 鞍山市| 信宜市| 凉山| 蒙山县| 河间市| 清新县| 习水县| 乌拉特前旗| 敖汉旗| 东宁县| 湖州市| 额尔古纳市| 松潘县| 荔浦县| 海口市|