1。标号
IDATALEN EQU 80H ; the length of IDATA memory in bytes.
这里IDATALEN只是一个标号而已,和idata不是一回事!你要是愿意,这段程序里的
IDATALEN你完全可以改成dog呀,pig呀,playboy呀这些标号(其实我的理想是过猪一 样的生活,不愁吃喝,无忧无虑,可惜做不到),上面的这一句是说程序里面凡是用 到IDATALEN的地方其实就是可以看成是80H这个数,你用80H去代替IDATALEN是完全对 的。 之所以取IDATALEN这么个名字,只是为了好记,表明和idata有一点点关系,不至于你 的程序长了,假使你本来是用了playboy作为标号的,写到后来你就会忘了playboy到 底是什么含义了。idata的范围是0~FFH。如果你想改成FFH,完全可以。
2。清零
IF IDATALEN <> 0
MOV R0,#IDATALEN - 1
CLR A
IDATALOOP: MOV @R0,A
DJNZ R0,IDATALOOP
关于这一段,很明显是在清零,如果上面idatalen=80H,那么是对0~7FH清零;如果 你的程序是改写成:
IDATALEN EQU 0100H ;
就是对0~FFH清零。 还要注意的是那条IF语句,下面再谈。 二、如何按你意愿加载这段程序 一般考虑到这个往往是你的设计中要区分上电复位和程序复位。有时候当程序复位时 你不希望一些内存单元被清零了,那么你不对startup.a51作点修改,就不行了。 默认是自动加载这段startup.a51的。 所以你要这样做: 把lib目录下的原始startup.a51文件拷到你的项目所在目录下,再把你项目目录下的 这个startup.a51加入到你的项目中(在keil的集成环境中,希望你对这个是知道如何 做的),然后对这个startup.a51加以修改。 比如改成:
IDATALEN EQU 00H ; the length of IDATA memory in bytes.
然后编译链接。这样你的程序中就不会包含对idata清零的内码了。 为什么?上面提到的IF语句的作用呀!当定义IDATALEN=0时,清零代码被跳过!
------------------------------------------------------------------------------------------------------------------------------------------
Startup.a51的中文说明
;------------------------------------------------------------------------------
;
STARTUP.A51: 用户上电初始化程序
;------------------------------------------------------------------------------
;
; 用户定义需上电初始化的内存空间
;
; 使用以下EQU命令可定义在CPU复位时需用0进行初始化的内存空间
;
;;
; IDATA 存储器的空间的绝对起始地址总是0.;
IDATALEN
EQU
80H ;
需用0进行初始化的IDATA存储器空间的字节数
;
XDATASTART
EQU
0H ;
XDATA存储器空间的绝对起始地址
XDATALEN
EQU
0H ;
需用0进行初始化的XDATA存储器的空间字节数.
;
PDATASTART
EQU
0H ;
PDATA存储器的空间的绝对起始地址
PDATALEN
EQU
0H ;
需用0进行初始化的PDATA存储器的空间字节数.
;
; 注意:
IDATA 存储器的空间在物理上包括了8051单片机的DATA和BIT存储器空间.
;
听 说 至少要保证与C51编译器运行库有关的存储器的空间进行0初始化 不知是否
;------------------------------------------------------------------------------
;
; 再入函数模拟初始化
;
; 以下用EQU指令定义了再入函数模拟堆栈指针的初始化
;
; 使用SMALL存储器模式时再入函数的堆栈空间 .
IBPSTACK
EQU
0 ;
使用SMALL存储器模式再入函数时将其设置成1.
IBPSTACKTOP
EQU
0FFH+1
; 将堆栈顶设置为最高地址+1.
;
; 使用LARGE存储器模式时再入函数的堆栈空间.; 使用LARGE存储器模式时再入函数的堆栈空间.
XBPSTACK
EQU
0 ;
使用LARGE存储器模式再入函数时将其设置成1.
XBPSTACKTOP
EQU
0FFFFH+1; 将堆栈顶设置为最高地址+1.
;
; 使用COMPACT存储器模式时再入函数的堆栈空间.;
使用COMPACT存储器模式时再入函数的堆栈空间.
PBPSTACK
EQU
0 ;
使用COMPACT存储器模式再入函数时将其设置成1.
PBPSTACKTOP
EQU
0FFFFH+1; 将堆栈顶设置为最高地址+1.
;
;------------------------------------------------------------------------------
;
; 使用COMPACT存储器模式时64K字节XDATA存储器空间的分页定义
;
; 以下用EQU指令定义PDATA类型变量在XDATA存储器空间的页地址
; 使用EQU指令定义PFAGE时必须与L51连接定位器PDATA指令的控制参数一致
;
PPAGEENABLE
EQU
0 ;
使用PDATA类型变量时将其设置成1.
PPAGE
EQU
0 ;
定义页号.
;
;------------------------------------------------------------------------------
NAME
?C_STARTUP; 模块名为 ?C_STAUTUP
?C_C51STARTUP
SEGMENT
CODE
; 代码
?STACK
SEGMENT
IDATA
; 堆栈
RSEG
?STACK
; 堆栈
DS 1
EXTRNEXTRN CODE
((?C_START))
; 程序开始地址
PUBLIC
?C_STARTUP
CSEG
AT
0x8000
; 定义用户程序的起始地址,用MON51仿真器时可能有用
?C_STARTUP:
LJMP
STARTUP1
RSEG
?C_C51STARTUP
STARTUP1::
;
; 初始化串口
MOV
SCON,#40H
MOV
TMOD,#20H
MOV
TH1,#0fdH
SETB
TR1
CLR
TI
; 单片机上电IDATA内存清零 如果不需要上电清零IDATA
可以注销IF到IFEDN之间的话句
; 或者修改IDTALEN的长度 为了具有掉电保护功能 不知IDTALEN多长为好
IF IDATALEN <> 0
MOV
R0,#IDATALEN - 1
CLR A
IDATALOOP:
MOV
@R0,A
DJNZ
R0,IDATALOOP
ENDIF
;
; 单片机上电XDATA内存清零 如果不需要上电清零XDATA
可以注销IF到IFEDN之间的话句
; 或者修改XDATALEN的长度
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 PAGEENABLE <> 0
MOV
P2,#PPAGE
ENDIF
;
; 单片机上电PDATA内存清零 如果不需要上电清零XDATA
可以注销IF到IFEDN之间的话句
; 或者修改PDATALEN的长度
IF PDATALEN <> 0
MOV
R0,#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
;
; 设置使用COMPACT存储器模式时再入函数的堆栈空间.
IF PBPSTACK <> 0
EXTRN DATA (C_PBP)
MOV
?C_PBP,#LOW PBPSTACKTOP
ENDIF
;
; 设置堆栈的起始地址
MOV
SP,#?STACK-1
; 例如 MOV SP,#4FH;
;
This code is required if you use L51_BANK.A51 with Banking Mode
4
; 如果你的程序使用了Mode 4
程序分组技术 请启动下面的程序,不会吧你的程序超过64K
利害
; EXTRN CODE (?B_SWITCH0)
;
CALL
?B_SWITCH0
; init bank mechanism to code bank 0
;;
程序从第一组bank 0
块开始执行
; 跳转到用户程序MAIN函数
LJMP
?C_START
END
;lINSHENGFENG
----------------------------------------------------------------------------------------------------------------------让我们先来看看STARTUP.A51文件(默认设置)吧!根据源文件中的说明文字,我们很容易分析出STARTUP.A51文件的工作方式和作用!让我们把它先汉化一下看看!
$NOMOD51
;Ax51宏汇编器控制命令:禁止预定义的8051 ;------------------------------------------------------------------------------
; This file is part of the C51 Compiler package
; Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software,
Inc.
;------------------------------------------------------------------------------
; STARTUP.A51: This code is executed after processor
reset. ; STARTUP.A51: STARTUP.A51文件所生成的代码将在单片机复位后被执行!
; To translate this file use A51 with the following
invocation: ; 将按照下面的命令行语句调用A51编译器进行编译产生目标文件
;
A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the
following
; BL51 invocation: ; 将按照下面的命令行语句调用BL51连接器把STARTUP.OBJ定位连接到您的程序代码中 ;
BL51 , STARTUP.OBJ
;
;------------------------------------------------------------------------------
;
; User-defined Power-On Initialization of
Memory ; 自定义上电后需要初始化的储存区域
; With the following EQU statements the initialization of
memory
; at processor reset can be defined: ; 使用下列EQU伪指令定义初始化的存储区域 在单片机复位后定义生效
;
; the absolute start-address
of IDATA memory is always 0
IDATALEN
EQU
80H
; the length of IDATA memory in bytes. ; IDATA(间接寻址区)其起始地址固定为0;IDATALEN用于指定需要初始化的IDATA区长度(以字节为单位)*
XDATASTART
EQU
0H
; the absolute start-address of XDATA memory
XDATALEN
EQU
0H
; the length of XDATA memory in bytes. ;XDATA (外部直接寻址区) XDATASTART用于指定需要初始化的XDATA区起始地址
;XDATALEN 用于指定需要初始化的XDATA区长度(以字节为单位)*
PDATASTART
EQU
0H
; the absolute start-address of PDATA memory
PDATALEN
EQU
0H
; the length of PDATA memory in bytes. ;PDATA(页寻址区) PDATASTART用于指定需要初始化的PDATA区起始地址
;PDATALEN用于指定需要初始化的;PDATA区长度(以字节为单位)*
; 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.
;注释:8051中 IDATA 区物理上已经包括了DATA区(直接寻址区)以及 BIT区 (位寻址
区)。C51(库)占用了 最小化内存空间,运行时程序需要把它设为0
;------------------------------------------------------------------------------
;
; Reentrant Stack Initilization ; 重入堆栈初始化
; The following EQU statements define the stack pointer for
reentrant
; functions and initialized it: ; 下面的EQU语句定义重入函数的堆栈指针并初始化它
; Stack Space for reentrant functions in the SMALL
model. ; SMALL模式下的重入函数的堆栈空间
IBPSTACK
EQU
0
; set to 1 if small reentrant is used. ;如果再SMALL模式下使用重入则设为1
IBPSTACKTOP
EQU
0FFH+1 ; set top of stack to highest
location+1. ;设置堆栈顶最高位置+1
;
; Stack Space for reentrant functions in the LARGE
model. ; LARGE模式下的重入函数的堆栈空间
XBPSTACK
EQU
0
; set to 1 if large reentrant is used. ;如果再LARGE模式下使用重入则设为1
XBPSTACKTOP
EQU
0FFFFH+1; set top of stack to highest
location+1. ;设置堆栈顶最高位置+1
;
; Stack Space for reentrant functions in the COMPACT
model.
; COMPACT模式下的重入函数的堆栈空间
PBPSTACK
EQU
0
; set to 1 if compact reentrant is used. ;如果再COMPACT模式下使用重入则设为1
PBPSTACKTOP
EQU
0FFFFH+1; set top of stack to highest
location+1. ;设置堆栈顶最高位置+1
;
;------------------------------------------------------------------------------
;
; Page Definition for Using the Compact Model with 64 KByte xdata
RAM ; 使用COMPACT模式时为64KB的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. ; 下面的EQU语句定义PDATA变量的使用了XDATA页
PPAGEENABLE
EQU
0
; set to 1 if pdata object are used. ;如果使用PDATA页则设为1
;
PPAGE
EQU
0
; define PPAGE number. ;定义页号
;
PPAGE_SFR
DATA
0A0H ; SFR
that supplies uppermost address byte ;SFR的最高地址字节
; (most 8051 variants use P2 as uppermost address
byte) ; (大多数8051变量要用P2的最高地址字节)
;------------------------------------------------------------------------------
; Standard SFR Symbols ; 标准SFR符号
ACC
DATA
0E0H
B
DATA
0F0H
SP
DATA
81H
DPL
DATA
82H
DPH
DATA
83H
NAME
?C_STARTUP
?C_C51STARTUP
SEGMENT CODE
?STACK
SEGMENT IDATA
RSEG
?STACK
DS
1
EXTRN CODE (?C_START) ;外部代码(这个标号将代表用户程序的启始地址)
PUBLIC ?C_STARTUP ;给外部使用的符号
CSEG
AT
0 ;在code段的0地址处放以下代码(使用AT指令进行绝对地址的定位)
?C_STARTUP:
LJMP
STARTUP1
RSEG
?C_C51STARTUP
STARTUP1:
IF IDATALEN <>
0 ;如果长度大于1则初始化IDATA
MOV
R0,#IDATALEN - 1
CLR
A
IDATALOOP:
MOV
@R0,A
DJNZ
R0,IDATALOOP
ENDIF
IF XDATALEN <>
0 ;如果长度大于1则初始化XDATA
MOV
DPTR,#XDATASTART
MOV
R7,#LOW (XDATALEN)
IF (LOW (XDATALEN)) <> 0 ;预置初始化时的外循环次数到R6
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
IF PPAGEENABLE <> 0
MOV
PPAGE_SFR,#PPAGE
ENDIF
IF PDATALEN <>
0 ;如果长度大于1则初始化PDATA
MOV
R0,#LOW (PDATASTART)
MOV
R7,#LOW (PDATALEN)
CLR
A
PDATALOOP:
MOVX
@R0,A
INC
R0
DJNZ
R7,PDATALOOP
ENDIF
IF IBPSTACK <>
0 ;SMALL模式下使用重入函数时要设置的堆栈
EXTRN DATA (?C_IBP)
MOV
?C_IBP,#LOW IBPSTACKTOP
ENDIF
IF XBPSTACK <>
0 ;COMPACT模式下使用重入函数时要设置的堆栈
EXTRN DATA (?C_XBP)
MOV
?C_XBP,#HIGH XBPSTACKTOP
MOV
?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
IF PBPSTACK <>
0 ;LARGE模式下使用重入函数时要设置的堆栈
EXTRN DATA (?C_PBP)
MOV
?C_PBP,#LOW PBPSTACKTOP
ENDIF
MOV
SP,#?STACK-1
; This code is required if you use L51_BANK.A51 with Banking Mode
4 ; 如果你的程序使用了Mode 4 程序分组技术(BANKING)请启用下面的程序代码
; EXTRN CODE (?B_SWITCH0)
;
CALL
?B_SWITCH0
; init bank mechanism to code bank 0
|