8.6 C51的用户配置文件
C51的用户配置文件是用来在程序执行前,配置单片机系统的一些相关设置。在C51中,用户可以根据需要适当修改配置文件以满足不同的硬件环境需要。这些用户配置文件存放在Keil\C51\LIB文件夹中。C51编译器在对用户创建的项目进行编译连接时,会自动将用户配置文件中的代码添加到用户程序中去。
如果用户要对配置文件进行修改,可以通过KeilµVision3的项目窗口,先将需要修改的配置文件添加到自己的项目文件组中,然后在编辑窗口进行修改,最后再进行总体编译连接,这样就可以将修改后的用户配置文件代码连接到自己的源程序代码中。
C51的用户配置文件包括启动代码文件、变量初始化文件、基本I/O函数文件、分组配置文件几类,下面分别介绍这几类用户配置文件。
8.6.1 C51的启动代码详解
C51启动代码文件用于在源程序进入主函数前,完成对单片机片内外RAM清零、开设常规堆栈和再入函数堆栈、设置堆栈指针等任务。在KeilµVision3编译环境中,针对不同类型的8051单片机提供了多种启动代码配置文件,其中最常用的启动代码文件是STARTUP.A51,其他的启动代码都和STARTUP.A51作用相似。这里以启动代码文件STARTUP.A51为例进行介绍,其可以实现以下几方面功能。
❑定义内部RAM大小、外部RAM大小和可重入堆栈位置。
❑初始化8051硬件堆栈指针。
❑按存储模式初始化重入堆栈及堆栈指针。
❑清除内部、外部或者以此页为单元的外部存储器。
❑向主函数main()交权。
在KeilµVision3编译环境中,建立C51项目的时候,由连接定位器BL51自动将启动代码文件加入C51源程序代码前面,如图8.2所示。在该对话框中,单击“是”按钮便可以将启动代码文件添加到项目中。
图 8.2 添加启动代码文件
启动文件STARTUP.A51的目标代码已经保存在C51编译器的运行库中,只要单片机执行复位操作,则该文件将被立即执行。在启动文件STARTUP.A51中包含一些EQU语句,如表8.2所示。用户可以根据需要修改这些语句的值,从而实现对单片机系统启动初始化设置。
启动代码在程序中具有十分重要的作用,这里给出Keil C51的STARTUP.A51文件的源代码,如下所示。STARTUP.A51文件是用汇编语言编写的,用户可以根据程序的需要进行改写。这里为了阅读和理解的方便,将原文的英文注释改为中文注释。
$NOMOD51
;——————————————————————————————————————
;STARTUP.A51:8051单片机上电进行初始化的程序
;
;
A51 STARTUP.A51
;——————————————————————————————————————
;
;定义8051单片机上电初始化的内存空间
;
;使用EQU命令定义
;
IDATALEN EQU 80H;初始化IDATA存储器的字节数
;
XDATASTART EQU 0H;初始化XDATA存储器的绝对起始地址
XDATALEN EQU 0H;初始化XDATA存储器的字节数
;
PDATASTART EQU 0H;初始化PDATA存储器的绝对起始地址
PDATALEN EQU 0H;初始化PDATA存储器的字节数
;
;注意:在硬件上,IDATA存储器空间包括了8051系列单片机中的DATA存储器空间和BIT存储器空间
;
;——————————————————————————————————————
;
;模拟初始化再入堆栈
;
;用EQU指令初始化再入函数堆栈指针
;
;8051单片机存储器模式选用SMALL模式时,再入函数的堆栈空间
IBPSTACK EQU 0;使用SMALL存储器模式的再入函数时,需要将其设置为1
IBPSTACKTOP EQU 0FFH+1;将堆栈顶设置为最高地址+1
;
;单片机存储器模式选用LARGE模式时,再入函数的堆栈空间
XBPSTACK EQU 0;使用LARGE存储器模式的再入函数时,需要将其设置为1
XBPSTACKTOP EQU 0FFFFH+1;将堆栈顶设置为最高地址+1
;
;单片机存储器模式选用COMPACT模式时,再入函数的堆栈空间
PBPSTACK EQU 0;使用COMPACT存储器模式再入函数时,需要将其设置为1
PBPSTACKTOP EQU 0FFFFH+1;将堆栈顶设置为最高地址+1
;
;——————————————————————————————————————
;
;8051单片机使用COMPACT存储器模式时,64KB XDATA存储器空间的分页定义
;
;用EQU指令定义PDATA类型变量在XDATA存储器空间中的页地址
;使用EQU指令定义PPAGE时必须与L51连接定位器PDATA指令的控制参数一致
;
PPAGEENABLE EQU 0;使用PDATA类型变量时,需要将其设置为1
;
PPAGE EQU 0;定义页号
;
PPAGE_SFR DATA 0A0H;为SFR提供最高地址比特
;(8051变量使用P2作为i最高地址)
;
;———————————————————————————————————————
;标准SFR符号
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
DPL DATA 82H
DPH DATA 83H
NAME?C_STARTUP;模块名为?C_STARTUP
?C_C51STARTUP SEGMENT CODE;代码段
?STACK SEGMENT IDATA;堆栈段
RSEG?STACK;堆栈
DS 1
EXTRN CODE(?C_START);单片机主程序的起始地址
PUBLIC?C_STARTUP
CSEG AT 0;定义用户程序的起始地址,一般在MON51仿真器中使用
?C_STARTUP:LJMP STARTUP1
RSEG?C_C51STARTUP
STARTUP1:
;8051单片机在上电时清零IDATA内存。如果不需要上电清零IDATA,可以注销IF到IFEND
;之间的语句,或者修改IDATALEN的长度。为了让CPU具有掉电保护功能,需要确定IDATALEN的长度
;
IF IDATALEN<>0
MOV R0,#IDATALEN-1
CLR A
IDATALOOP:
MOV@R0,A
DJNZ R0,IDATALOOP
ENDIF
;8051单片机在上电时XDATA内存清零。如果不需要上电清零XDATA,可以修改XDATALEN的长度,
;或者注销IF到IFEND之间的语句
IF XDATALEN<>0
MOV DPTR,#XDATASTART
MOV R7,#LOW(XDATALEN)
IF(LOW(XDATALEN))<>0
MOV R6,#(HIGH(XDATALEN))+1
ELSE
MOV R6,#HIGH(XDATALEN)
ENDIF
CLR A
XDATALOOP:
MOVX@DPTR,A
INC DPTR
DJNZ R7,XDATALOOP
DJNZ R6,XDATALOOP
ENDIF
;送PDATA存储器页面高位地址
IF PPAGEENABLE<>0
MOV PPAGE_SFR,#PPAGE
ENDIF
;8051单片机在上电时PDATA内存清零。如果不需要上电清零PDATA,可以修改PDATALEN的长度,
;或者注销IF到IFEND之间的语句
IF PDATALEN<>0
MOV R0,#LOW(PDATASTART)
MOV R7,#LOW(PDATALEN)
CLR A
PDATALOOP:
MOVX@R0,A
INC R0
DJNZ R7,PDATALOOP
ENDIF
;设置指名使用SMALL存储器模式时再入函数的堆栈空间
IF IBPSTACK<>0
EXTRN DATA(?C_IBP)
MOV?C_IBP,#LOW IBPSTACKTOP
ENDIF
;设置指名使用LARGE存储器模式时再入函数的堆栈空间
IF XBPSTACK<>0
EXTRN DATA(?C_XBP)
MOV?C_XBP,#HIGH XBPSTACKTOP
MOV?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
;设置8051单片机使用COMPACT存储器模式时,再入函数的堆栈空间
IF PBPSTACK<>0
EXTRN DATA(?C_PBP)
MOV?C_PBP,#LOW PBPSTACKTOP
ENDIF
;设置8051单片机堆栈的起始地址
MOV SP,#?STACK-1
;如果程序超过64k,使用了程序分组技术,则启动下面的程序
;EXTRN CODE(?B_SWITCH0)
;
CALL?B_SWITCH0;初始化代码分组0
;程序从第一组开始执行
;使用LJMP指令跳转到用户主程序的main()主函数处
LJMP?C_START
END
前面介绍了C51的启动代码,下面详细介绍上面的启动代码文件中常用的一些EQU语句的功能。
1.常数IDATALEN
常数IDATALEN用于声明8051单片机开始运行时,需要清零的片内RAM字节数。在启动代码文件中,IDATALEN一般默认值为80H。而对于8052单片机,由于其具有256字节内部RAM,因此可设置为100H。
一般来说,只有当程序需要在开始时清零内部RAM,才有必要对IDATALEN进行赋值。如果希望单片机片内RAM具有掉电保护功能,则应将常数IDATALEN设置为0。
2.常数XDATASTART和XDATALEN
常数XDATASTART和XDATALEN分别用于声明需要清零的XDATA存储器的首地址和长度。其中XDATASTART指出对应的XDATA储存器的首地址,XDATALEN指出需要进行清零的总字节数。
3.常数PDATASTART和PDATALEN
常数PDATASTART和PDATALEN分别用于声明需要清零的PDATA存储器的首地址和长度。其中PDATASTART指出对应的PDATA储存器的首地址,PDATALEN指出需要清零的总字节数。
4.常数IBPSTACK和IBPSTACKTOP
常数IBPSTACK和IBPSTACKTOP用于定义在SMALL编译模式下创建的再入函数的模拟堆栈区。其中,IBPSTACK=1时表示创建模拟堆栈,并对堆栈指针(变量C_IBP)进行初始化;IBPSTACK=0(默认值)时表示不创建模拟堆栈。IBPSTACKTOP用于指出SMALL编译模式下再入函数的模拟堆栈区栈顶首地址,默认值为IDATA区的0xFF地址。
KeilµVision3编译器对于该堆栈不检查是否能满足要求,用户需要自己进行判断。
5.常数XBPSTACK和XBPSTACKTOP
常数XBPSTACK和XBPSTACKTOP用于定义在LARGE编译模式下创建的再入函数的模拟堆栈区。其中XBPSTACK=1时表示创建模拟堆栈,并对堆栈指针(变量C_XBP)进行初始化;XBPSTACK=0(默认值)时表示不创建模拟堆栈。XBPSTACKTOP则指出LARGE编译模式下再入函数的模拟堆栈区栈顶首地址,默认值为XDATA区的0xFFF地址。
KeilµVision3编译器对于该堆栈不检查是否能满足要求,用户需要自己进行判断。
6.常数PBPSTACK和PBPSTACKTOP
常数PBPSTACK和PBPSTACKTOP用于定义在COMPACT编译模式下创建的再入函数的模拟堆栈区。其中,PBPSTACK=1时表示创建模拟堆栈,并对堆栈指针(变量C_PBP)进行初始化;XBPSTACKTOP指出栈顶首地址,默认值为PDATA区的0XFFFF地址。
KeilµVision3编译器对于该堆栈不检查是否能满足要求,用户需要自己进行判断。
7.常数PPAGEENABLE和PPAGE
常数PPAGEENABLE和PPAGE用于在COMPACT编译模式下,使用“页寻址”方式操作PDATA存储区域。对于LARGE编译模式,使用这些指令可以提高程序的运行速度或减少程序代码的长度。
为了实现对存储器空间的“页寻址”操作,常数PPAGEENABLE允许对8051单片机P2进行初始化。例如,需要初始化P2作为COMPACT模式高端地址,则必须置PPAGEENAGLE=1,PPAGE为P2值,如果指定某页1000H~10FFH,则PPAGE=10H,而且连接时必须是如下形式。
L51<input modules>PDATA(1080H),其中1080H是1000H-10FFH中的任意一个值
常数PPAGEENABLE和PPAGE必须与KeilµVision3的连接定位器BL51的控制指令“PDATA”一起使用。其中,PDATA指令是用来指定XDATA存储器中PDATA区的首地址。
KeilµVision3编译器和BL51连接定位器都不对PPAGE和PDATA指令的正确与否进行检查,用户必须自行保证PPAGE和PDATA为正确的值。
除了STARTUP.A51启动代码文件外,还有一些适用于特殊增强型单片机的启动代码文件,如START751.A51、STARTLPC.A51、START390.A51和START_AD.A51等。这些启动代码文件的使用方法和STARTUP.A51类似,只是增加了一些特殊功能,如设置片内数据存储器SRAM的地址范围、扩展堆栈寻址方式、调整CPU时钟、并行端口复位状态、设置看门狗定时器、片内EPROM的保密状态、扩展堆栈模式以及堆栈空间大小等。