uVision2入门教程.docx
《uVision2入门教程.docx》由会员分享,可在线阅读,更多相关《uVision2入门教程.docx(47页珍藏版)》请在冰豆网上搜索。
uVision2入门教程
●
软件开发流程
当你使用KeilSoftware工具时,你的项目开发流程和其它软件开发项目的流程极其相似。
1、创建一个项目,从器件库中选择目标器件,配置工具设置。
2、用C语言或汇编语言创建源程序。
3、用项目管理器生成你的应用。
4、修改源程序中的错误。
5、测试,连接应用。
一个完整的8051工具集的框图可以最好地表述此开发流程。
每一个组件在下面详细描述。
●uVision2IDE
uVision2集成开发环境集成了一个项目管理器,一个功能丰富、有错误提示的编辑器,以及设置选项,生成工具,在线帮助。
利用uVision2创建你的源代码并把它们组织到一个能确定你的目标应用的项目中去。
uVision2自动编译,汇编,连接你的嵌入式应用,并为你的开发提供一个单一的焦点。
●C51编译器和A51汇编器
源代码由uVision2IDE创建,并被C51编译或A51汇编。
编译器和汇编器从源代码生成可重定位的目标文件。
KeilC51编译器完全遵照ANSIC语言标准,支持C语言的所有标准特性。
另外,直接支持8051结构的几个特性被添加到里面。
KeilA51宏汇编器支持8051及其派生系列的全部指令集。
●LIB51库管理器
LIB51库管理器允许你从由编译器或汇编器生成的目标文件创建目标库。
库是一种被特别地组织过并在以后可以被连接重用的对象模块。
当连接器处理一个库时,仅仅那些被使用的目标模块才被真正使用。
●BL51连接器/定位器
BL51连接器/定位器利用从库中提取的目标模块和由编译器或汇编器生成的目标模块创建一个绝对地址的目标模块。
一个绝对地址目标模块或文件包含不可重定位的代码和数据。
所有的代码和数据被安置在固定的存储器单元中。
此绝对地址目标文件可以用来:
⏹写入EPROM或其它存储器件。
⏹由uVision2调试器使用来模拟和调试。
⏹由仿真器用来测试程序。
●uVision2调试器
uVision2源代码级调试器是一个理想地快速,可靠的程序调试器。
此调试器包含一个高速模拟器,能够让你模拟整个8051系统,包括片上外围器件和外部硬件。
当你从器件库中选择器件时,这个器件的特性将自动配置。
uVision2调试器为你在实际目标板上测试你的程序提供了几种方法:
⏹安装MON51目标监控器到你的目标系统并且通过Monitor-51接口下载你的程序。
⏹利用高级的GDI(AGDI)接口,把uVision2调试器绑定到你的目标系统。
●Monitor-51
uVision2调试器支持用Monitor-51进行目标板调试。
此监控程序驻留在你的目标板的存储器里,它利用串口和uVision2调试器进行通信。
利用Monitor-51,uVision2调试器可以对你的目标硬件实行源代码级的调试。
●RTX51实时操作系统
RTX51实时操作系统是一个针对8051系列的多任务核。
RTX51实时内核从本质上简化了对实时事件反应速度要求高的复杂应用系统的设计,编程和调试。
RTX51实时内核是完全集成到C51编译器中的,从而方便使用。
任务描
述表和操作系统的连接由BL51连接器/定位器自动控制。
●产品一览
KeilSoftware提供第一流的8051系列开发工具,我们把我们的开发工具捆绑到不同的开发包或工具套件。
17页的对照表说明了整个KeilSoftware8051开发工具。
每一个套件及其内容描述如下:
●PK51专业开发套件
PK51专业开发套件包括了所有专业开发人员创建和调试复杂8051嵌入式应用系统所要用到的一切工具。
PK51专业开发套件可以针对所有的8051及其派生系列进行配置使用。
●DK51开发套件
DK51开发套件是PK51专业开发套件的精简版本。
它不包括小型RTX51实时操作系统。
此套件可以针对所有的8051及其派生系列进行配置使用。
●CA51编译套件
CA51编译套件是那些需要C编译器而不需要调试系统的开发人员的最好选择。
CA51开发包仅仅包含uVision2IDE。
uVision2调试器不包括在内。
此套件可以针对所有的8051及其派生系列进行配置使用。
●A51汇编套件
A51汇编套件包括一个汇编器和你创建嵌入式应用所需要的所有功能。
此套件可以针对所有的8051及其派生系列进行配置使用。
●RTX51实时操作系统(FR51)
RTX51实时操作系统是一个8051系列MCU的实时内核。
RTX51FULL提供RTX51TINY的所有功能和一些扩展功能,并且包括CAN通信协议接口。
●开发套件和工具的对照表:
利用此表选择你所需要的开发套件.
●文件夹组织结构
安装程序复制开发工具到基本目录的各个子目录中。
默认的基本目录是C:
\KEIL。
下表列出的文件夹结构是包括所有8051开发工具的全部安装信息。
你的安装信息由你购买的开发套件决定。
文件夹描述
C:
\KEIL\C51\ASM汇编SFR定义文件和模板源程序文件。
C:
\KEIL\C51\BIN8051工具的执行文件。
C:
\KEIL\C51\EXAMPLES示例应用。
C:
\KEIL\C51\RTX51完全实时操作系统文件。
C:
\KEIL\C51\RTX_TINY小型实时操作系统文件。
C:
\KEIL\C51\INCC编译器包含文件。
C:
\KEIL\C51\LIBC编译器库文件,启动代码和常规I/O资源。
C:
\KEIL\C51\MONITOR目标监控文件和用户硬件的监控配置。
C:
\KEIL\UV2普通uVision2文件。
在本使用指南中,我们假定用户采用默认的文件夹结构。
如果你安装你的软件到一个不同的文件夹,你必须调整路径名以适应你的安装。
●C51优化的C语言交叉编译器
KeilC51交叉编译器是一个基于ANSIC标准的针对8051系列MCU的C编译器,生成的可执行代码快速、紧凑,在运行效率和速度上可以和汇编程序得到的代码相媲美。
⏹和汇编语言相比,用C语言这样的高级语言有很多优势,比如:
⏹对处理器的指令集不必了解,8051CPU的基本结构可以了解,但不是必须的。
⏹寄存器的分配以及各种变量和数据的寻址都由编译器完成。
⏹程序拥有了正式的结构(由C语言带来的),并且能被分成多个单独的子函数。
这使整个应用系统的结构变得清晰,同时让源代码变得可重复使用。
⏹选择特定的操作符来操作变量的能力提高了源代码的可读性。
⏹可以运用和人的思维很接近的词汇和算法表达式。
⏹编写程序和调试程序的时间得到很大程度的缩短。
⏹C运行连接库包含一些标准的子程序,如:
格式化输出,数字转换,浮点运算。
⏹由于程序的模块结构技术,使得现有的程序段可以很容易的包含到新的程序中去。
⏹ANSI标准的C语言是一种丰常方便的,获得广泛应用的,在绝大部分系统中都能够很容易得到的语言。
因此,如果需要,现有的程序可以很快地移植到其他的处理器上,节省投资。
●C51语言的扩展
虽然C51是一个兼容ANSI的编译器,但为了支持8051系列MCU还是加入了一些扩展的内容。
C51编译器的扩展内容包括:
⏹数据类型
⏹存储器类型
⏹指针
⏹重入函数
⏹中断服务程序
⏹实时操作系统
⏹和PL/M及A51源程序的接口
以下各节简单地描述了上述的扩展特性。
●数据类型
本C51编译器支持下表列出的各种规格的数据类型。
.除了这些数据类型以外,变量可以组合成结构,联合及数组。
除非特别说明,这些变量都可以用指针存取。
注:
*bit,sbit,sfr,和sfr16为8051硬件和C51及C251编译器所特有,它们不是ANSIC的一部分,也不能用指针对它们进行存取。
这些sbit,sfr和sfr16类型的数据使你能够操作8051MCU所提供的特殊功能寄存器。
例如,下面的表达式:
sfrP0=0x80;/*Define8051P0SFR*/
声明了一个变量P0,并且把它和位于0x80(8051的端口0)处的特殊功能寄存器联系在一起。
当结果的数据类型和源数据类型不同时,C51编译器在数据类型间自动进行转换。
例如,一个bit变量赋值给一个interger变量时将会被转换为integer。
当然,你可以用类型表示进行强制转换。
数据转换时要注意,有符号变量的转换,其符号是自动扩展的。
●存储器类型
本C51编译器支持8051及其派生类型的结构,能够访问8051的所有存储器空间。
具有下表列出的存储器类型的变量都可以被分配到某个特定的存储器空间。
存储器类型描述
code程序空间(64Kbytes);通过MOVC@A+DPTR访问。
data直接访问的内部数据存储器;访问速度最快(128bytes)。
idata间接访问的内部数据存储器;可以访问所有的内部存储器空间(256bytes)。
bdata可位寻址的内部数据存储器;可以字节方式也可以位方式访问(16bytes)。
xdata外部数据存储器(64Kbytes);通过MOVX@DPTR访问。
pdata分页的外部数据存储器(256bytes);通过MOVX@Rn访问。
访问内部数据存储器将比访问外部数据存储器快的多。
由于这个原因,你应该把频繁使用的变量放置在内部数据存储器中,把很少使用的变量放在外部数据存储器中。
这通过使用SMALL模式将很容易就做到。
通过定义变量时包括存储器类型,你可以定义此变量存储在你想要的存储器中。
在变量的声明中,你可以包括存储器类型和signed或unsigned属性。
chardatavar1;
charcodetext[]="ENTERPARAMETER";
unsignedlongxdataarray[100];
floatidatax,y,z;
unsignedintpdatadimension;
unsignedcharxdatavector[10][4][4];
charbdataflags;
如果在变量的定义中,没有包括存储器类型,将自动选用默认或暗示的存储器类型。
暗示的存储器类型适用于所有的全局变量和静态变量,还有不能分配在寄存器中的函数参数和局部变量。
默认的存储器类型由编译器的参数SMALL,COMPACT及LARGE决定。
这些参数定义了编译时使用的存储模式。
●存储模式
存储模式决定了默认的存储器类型,此存储器类型将应用于函数参数,局部变量和定义时未包含存储器类型的变量。
你可以在命令行用SMALL,COMPACT和LARGE参数定义存储模式。
定义变量时,使用存储器类型显式定义将屏蔽默认存储器类型。
小(SMALL)模式
所有变量都默认在8051的内部数据存储器中。
这和用data显式定义变量起到相同的作用。
在此模式下,变量访问是非常快速的。
然而,所有数据对象,包括堆栈都必须放在内部RAM中。
堆栈空间面临溢出,因为堆栈所占用多少空间依赖于各个子程序的调用嵌套深度。
在典型应用中,如果具有代码分段功能的BL51连接/定位器被配置成覆盖内部数据存储器中的变量时,此SMALL模式是最好的选择。
紧凑(COMPACT)模式
此模式中,所有变量都默认在8051的外部数据存储器的一页中。
地址的高字节往往通过Port2输出。
其值必须由你在启动代码中设置,编译器不会为你设置。
这和用pdata显式定义变量起到相同的作用。
此模式最多只能提供256字节的变量。
这种限制来自于间接寻址所使用的R0,R1(MOVX@R0/R1)。
这种模式不如SMALL模式高效,所以变量的访问不够快。
不过它比LARGE模式要快。
大(LARGE)模式
在大模式下,所有的变量都默认在外部存储器中(xdata)。
这和用xdata显式定义变量起到相同的作用。
数据指针(DPTR)用来寻址。
通过DPTR进行存储器的访问的效率很低,特别是在对一个大于一个字节的变量进行操作时尤为明显。
此数据访问类型比SMALL和COMPACT模式需要更多的代码。
注意
你或许应该一直使用小模式,它产生最快,最紧凑,效率最高的代码。
你最好显式定义你的变量的存储器类型。
只有当你的应用不能在SMALL模式下操作时,你才需要往上增加你的存储模式。
●指针
C51编译器支持用星号(*)进行指针声明。
你可以用指针完成在标准C语言中有的所有操作。
另外,由于8051及其派生系列所具有的独特结构,C51编译器支持两种不同类型的指针:
存储器指针和通用指针。
通用指针
通用或未定型的指针的声明和标准C语言中一样。
如:
char*s;/*stringptr*/
int*numptr;/*intptr*/
long*state;/*longptr*/
通用指针总是需要三个字节来存储。
第一个字节是用来表示存储器类型,第二个字节是指针的高字节,第三字节是指针的低字节。
通用指针可以用来访问所有类型的变量,而不管变量存储在哪个存储空间中。
因而许多库函数都使用通用指针。
通过使用通用指针,一个函数可以访问数据,而不用考虑它存储在什么存储器中。
通用指针很方便,但是也很慢。
在所指向目标的存储空间不明确的情况下,它们用的最多。
存储器指针
存储器指针或类型确定的指针在定义时包括一个存储器类型说明,并且总是指向此说明的特定存储器空间。
例如:
chardata*str;/*ptrtostringindata*/
intxdata*numtab;/*ptrtoint(s)inxdata*/
longcode*powtab;/*ptrtolong(s)incode*/
正是由于存储器类型在编译时已经确定,通用指针中用来表示存储器类型的字节就不再需要了。
指向idata,data,bdata和pdata的存储器指针用一个字节保存,指向code和xdata的存储器指针用两个字节保存。
使用存储器指针比通用指针效率要高,速度要快。
当然,存储器指针的使用不是很方便。
在所指向目标的存储空间明确并不会变化的情况下,它们用的最多。
存储器指针和通用指针的比较
使用存储器指针可以显著的提高8051C程序的运行速度。
下面的示例程序说明了使用不同的指针在代码长度,占用数据空间和运行时间上的不同。
DescriptionIdataPointerXdataPointerGenericPointer
C源程序idata*ip;charxdata*xp;char*p;
charval;harval;charval;
val=*ip;val=*xp;val=*xp;
编译后的
代码MOVR0,ipMOVDPL,xp+1MOVR1,p+2
MOVval,@R0MOVDPH,xpMOVR2,p+1
MOVA,@DPTRMOVR3,p
MOVval,ACALLCLDPTR
指针大小1byte2byte3byte
代码长度4bytes9bytes11bytes+librarycall
执行时间4cycles7cycles13cycles
●重入函数
多个进程可以同时使用一个重入函数。
当一个重入函数被调用运行时,另外的一个进程可能中断此运行过程,然后再次调用此重入函数。
通常情况下,C51函数不能被递归调用,也不能应用导致递归调用的结构。
有此限制是由于函数参数和局部变量是存储在固定的地址单元中。
重入函数特性允许你声明一个重入函数。
即可以被递归调用的函数。
如:
intcalc(chari,intb)reentrant
{
intx;
x=table[i];
return(x*b);
}
重入函数可以被递归调用,也可以同时被两个或更多的进程调用。
重入函数在实时应用中及中断服务程序代码和非中断程序代码必须共用一个函数的场合中经常用到。
对每一个重入函数来说,根据存储模式,重入堆栈被安置在内部或外部单元中。
注意
在一个基本函数的基础上添加reentrant说明,从而使它具有重入特性。
需要注意的是,你可以选择哪些必须的函数为重入函数,而不需将全部程序声明为重入函数。
把全部程序声明为重入函数将增加目标代码的长度并减慢运行速度。
●中断服务程序
C51编译器允许你用C语言创建中断服务程序。
你仅仅需要关心中断号和寄存器组的选择。
编译器自动产生中断向量和程序的入栈及出栈代码。
在函数声明时包括interrupt,将把所声明的函数定义为一个中断服务程序。
另外,你可以用using定义此中断服务程序所使用的寄存器组。
unsignedintinterruptcnt;
unsignedcharsecond;
voidtimer0(void)interrupt1using2
{
if(++interruptcnt==4000)
{/*countto4000*/
second++;/*secondcounter*/
interruptcnt=0;/*clearintcounter*/
}
}
●参数传递
C51编译器能在CPU寄存器中传递最多三个参数,由于不用从存储器中读出和写入参数,从而显著提高了系统性能。
参数传递由REGPARMS和NOREGPARMS编译参数所控制。
下表列出了不同的参数和数据类型所占用的寄存器:
参数char,int,long,generic
数目1-bytepointer2-bytepointerfloatpointer
1R7R6&R7R4-R7R1—R3
2R5R4&R5
3R3R2&R3
如果没有CPU寄存器供参数传递所用,或太多的参数需要传递时,地址固定的存储器将用来存储这些额外的参数。
●函数返回值
函数返回值总是通过CPU寄存器进行。
下表列出了返回各种数据时所用的CPU寄存器:
返回数据类型寄存器描述
bitCarryFlag
char,unsignedchar,1-bytepointerR7
int,unsignedint,2-bytepointerR6&R7MSBinR6,LSBinR7
long,unsignedlongR4—R7MSBinR4,LSBinR7
floatR4—R732-BitIEEEformat
genericpointerR1—R3MemorytypeinR3,MSBR2,LSBR1
●寄存器优化
根据程序前后的联系,C51编译器分配最多7个寄存器来存储寄存器变量。
C51编译器能分析每个程序模块中对寄存器的修改。
连接程序产生一个全局的、项目级的寄存器文件,此文件包含被外部程序改变的所有寄存器的信息。
因而,C51编译器知道整个应用中每个函数所使用的寄存器,并能为每个C函数优化分配CPU寄存器。
●对实时操作系统的支持
C51编译器很好地集成了RTX-51Full和RTX-51Tiny多任务实时操作系统。
任务描述表在连接过程中控制和产生。
关于RTX实时操作系统的详细信息请参考169页开始的"RTX-51Real-TimeOperatingSystem"一章。
●和汇编语言的接口
你可以很容易在C程序中调用汇编程序,反之依然。
函数参数通过CPU寄存器传递,或使用NOREGPARMS参数指示编译器通过固定的存储器传递。
从函数返回的值总是通过CPU寄存器传递。
除了直接产生目标代码外,你还可以用SRC编译参数指示编译器产生汇编源代码文件(供A51汇编器使用)。
例如下面的C语言源代码:
unsignedintasmfunc1(unsignedintarg)
{
return(1+arg);
}
用SRC指示C51编译器编译时产生以下汇编文件:
?
PR?
_asmfunc1?
ASM1SEGMENTCODE
PUBLICasmfunc1
RSEG?
PR?
_asmfunc1?
ASM1
USING0
asmfunc1:
;----Variable'arg?
00'assignedtoRegister'R6/R7'----
MOVA,R7;loadLSBoftheint
ADDA,#01H;add1
MOVR7,A;putitbackintoR7
CLRA
ADDCA,R6;addcarry&R6
MOVR6,A
?
C0001:
RET;returnresultinR6/R7
你可以用#pragmaasm和#pragmaendasm预处理指示器来在你的C语言程序中插入汇编指令。
●和PL/M-51的接口
Intel的PL/M-51是一种流行的编程语言,在很多方面和C语言类似。
你很容易就可以将C程序和PL/M-51程序联接起来。
在你用alien声明PL/M-51函数后,你就可以从C语言中调用它们。
所有在PL/M-51模块中定义的全局变量都可以在C语言程序中使用。
例如:
externaliencharplm_func(int,char);
PL/M-51编译器和KeilSoftware工具都产生OMF51格式的目标文件。
连接程序使用OMF51文件来处理外部字符变量,而不管它们在什么地方声明和使用。
●代码优化
C51是一个杰出的优化编译器,它通过很多步骤以确保产生的代码是最有效率的(最小和/或最快)。
编译器通过分析初步的代码产生最终的最有效率的代码序列,以此来保证你的C语言程序占用最少空间的同时运行的快而有效。
C51编译器提供9个优化级别。
每个高一级的优化级别都包括比它低的所有优化级别的优化内容。
以下列出的是目前C51编译器提供的所有优化级别的内容:
⏹常量折叠:
在表达式及寻址过程中出现的常量被综合为一个单个的常量。
⏹跳转优化:
采用反转跳转或直接指向最终目的的跳转,从而提升了程序的效率。
⏹哑码消除:
永远不可能执行到的代码将自动从程序中剔除。
⏹寄存器变量:
只要可能,局部变量和函数参数被放在CPU寄存器中,不需要为这些变量再分配存储器空间。
⏹通过寄存器传递参数:
最多三个参数通过寄存器传递。
⏹消除全局公用的子表达式:
只要可能,程序中多次出