|  | 
 
| Keil C51开发系统基本知识(3) 
 2. 第二节 几类重要库函数
 1. 1. 专用寄存器include文件
 例如8031、8051均为REG51.h其中包括了所有8051的SFR及其位定义,一般系统都必须包括本文件。
 2. 2. 绝对地址include文件absacc.h
 该文件中实际只定义了几个宏,以确定各存储空间的绝对地址。
 3. 3. 动态内存分配函数,位于stdlib.h中
 
 4. 4. 缓冲区处理函数位于“string.h”中
 其中包括拷贝比较移动等函数如:
 memccpy memchr memcmp memcpy memmove memset
 这样很方便地对缓冲区进行处理。
 5. 5. 输入输出流函数,位于“stdio.h”中
 流函数通8051的串口或用户定义的I/O口读写数据,缺省为8051串口,如要修改,比如改为LCD显示,可修改lib目录中的getkey.c及putchar.c源文件,然后在库中替换它们即可。
 3. 第三节 Keil C51库函数原型列表
 1. 1. CTYPE.H
 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);
 2. 2. INTRINS.H
 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);
 3. 3. STDIO.H
 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);
 4. 4. STDLIB.H
 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);
 5. 5. STRING.H
 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);
 6. 第六章 Keil C51例子:Hello.c
 
 Hello位于C51excmplesHello目录,其功能是向串口输出“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
 ”);
 while(1) { }
 }
 1. 第一节 uVision for Windows的使用步骤
 (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选中helloDS51.INI
 查看DS51.INI看其是否为:
 “load……BIN8051.DLL
 map 0, 0xffff”
 否则修改。
 (6) 在option_make选make文件顺序。
 (7) project选Build project,看是否有语法错误,若无则生成HEX文件,若有则修改源文件后重复以上部分步骤。
 (8) run_dScope debugger进入dScope51后装入hello则可用go直接运行看serial窗口有无输出,正常每系统运行一次,serial窗口均出现一个“Hello,world”表明运行无误。
 2. 第二节 Ishell for Dos使用步骤
 (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则只能多个文件分别编译,然后连接。
 7. 第七章 Keil C51的代码效率
 C51程序编译生成汇编代码的效率,是由许多因素共同决定的,对于Keil C51,主要受以下两种因素影响:
 1. 第一节 存储模式的影响
 存储模式决定了缺省变量的存储空间,而访问各空间变量的汇编代码的繁简程度决定了代码率的高低。
 例如:一个整形变量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模式,对一些常用的局部的或者可放于内存中的变量,最好放于内存中,以尽量提高程序的代码率。
 2. 第二节 程序结构的影响
 程序的结构单元包括模块、函数等等。同样的功能,如果结构越复杂,其所涉及的操作、变量、功能模块函数等就越多,较之结构性好,代码简单的程序其代码率自然就低得多。
 此外程序的运行控制语句,也是影响代码率的关键因素,例如:switch -case语句,许多编译器都把它们译得非常复杂,Keil C51也不例外,相对较为简易的Switch-case语句,编译成跳转指令形式,代码率较高,但对较为复杂的Switch-Case,则要调用一个系统库函数?C?ICASE进行处理,非常复杂。
 再如if( ),while( ),等语句也是代码相对较低的语句,但编译以后比switch-case要高得多。
 因此建议设计者尽量少用switch-case之类语句来控制程序结构,以提高代码率。
 除以上两点外,其它因素也会对代码率产生影响,例如:
 是否用寄存器传递参数 即NOAREGS选项是否有
 是否包括调试信息:即DEBUG选项
 是否包括扩展的调试信息:即BJECTEXTEND
 8. 第八章 dScope for Windows使用详解
 1. 第一节 概述
 1. 1. 主窗口(Mainframe Window)
 可设置其它各种调试窗口,设置断点、观察点,修改地址空间,加载文件等等;
 2. 2. 调试窗口(DEBUG Window)
 支持用户程序的各种显示方式,可连续运行,单步运行用户程序,并可在线 汇编;
 3. 3. 命令窗口(Command Window)
 支持命令行的输入;
 4. 4. 观察窗口(Watch Window)
 可设置所要观察的变量、表达式等;
 5. 5. 寄存器窗口(Registe Window)
 显示内部寄存器的内容,程序运行次数等;
 6. 6. 串口窗口(Serical Windows)
 显示串口接收和发送的数据;
 7. 7. 性能分析窗口
 显示所要观察的各程序段占用CPU的空间;
 8. 8. 内存窗口(Memory Window)
 显示所选择的内存中的数据;
 9. 9. 符号浏览窗口(Symbol Browser Window)
 显示各种符号名称,包括专有符号,用户自定义符号(函数名、变量、标号)等;
 10. 10. 调用线窗口(Call-Stack Window)
 动态显示当前执行的程序段的函数调用关系;
 11. 11. 代码覆盖窗口
 提供当前模块内各程序段中被执行代码的比率;。
 12. 12. 外围设备窗口(peripherals)
 可显示I/O口,定时器,中断,串口等外围设备状态;
 2. 第二节 dScope for Windows基本操作
 1. 1. 指定初始化文件
 在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
 2. 2. 观察变量
 方法1:命令行
 WS expression [, numberbase ] [ LINE ]
 其中numberbase为显示数制,10对应10进制,16对应16进制,缺省为16进制。LINE为单行显示,缺省为多行显示。
 方法2:setup->Watchpoints,在对话框中输入变量
 3. 3. 显示RAM的值
 d i(x,d):起始地址,终止地址
 d 变量名
 4. 4. 观察堆栈
 View->Call-stack->Show invocation,可以跟踪调用过程;
 5. 5. 中断处理程序调试
 在装入8051.dll后,在dScope的主菜单中将增加Peripherial,其有4个字菜单:
 I/0 port:Pi端口状态
 Interrupt:中断设置
 Timer:定时器中断状态
 Serial:串口中断状态
 设置相应的中断请求标志位即可产生中断。
 6. 6. 性能分析(Performance Analyzer:PA)
 PA用来分析一段代码执行占用CPU的百分比。定义:
 命令行 PA func_name
 3. 第三节 dScope for Windows命令文件的编制
 dScope除了用命令行的方式进行调试以外,还可将各种调试命令汇集于一个调试文件中,然后调用该文件,就可达到自动测试用户源代码的目的。dScope的命令文件支持C/PL/M的格式,因而编制调试命令文件与编制C语言程序有些类似。
 1. 1. 地址空间及地址空间类型
 1. (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. (2) 地址空间类型
 C:代码空间
 D:内部直接寻址空间
 I: 内部间接寻址空间
 X:外部数据空间
 B:位寻址空间
 P:I/O口
 EB:扩展的位寻址空间(MCS251专有)
 ED:扩展的数据空间(MCS251专有)
 CO:常数空间(MCS251专有)
 HC:正常数空间(MCS251专有)
 2. 2. 常量
 dScope支持十六进制、八进制、十进制、二进制常数,其后缀分别为H、Q(O)、T(或无)、Y;
 dScope不区分常量的大、小写。
 1. (1) 整型常量
 分为整型(int),无符号整型(uint,00rd),长整型(long),无符号长整型(Wlong、Word)。
 2. (2) 浮点型常量
 与ANSI C相同。
 3. (3) 字符串常量
 与ANSI C相同
 4. (4) 字符常量
 分为字符型(Char)和无符号字符型(Uchar)一种。
 5. (5) 行号常数
 指用户程序中的行号,实际上是个地址
 6. (6) 位常量(Bit):
 0和1
 7. (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. (8) 标识符常量
 即用户源程序中的标号、函数名等,实际上代表某一地址。
 9. (9) 用户源程序中定义的常数
 3. 3. 变量
 dScope所支持的变量名或标识符最多可由31个字符组成,第一个字母为A~Z,a~z,下划线或问号,后续字符可为字母、数字、下划线和问号。除CPU变量和系统变量外,dScope不支持全局变量,但可视“define”命令定义的变量为全局变量。
 Dscope所支持的变量分为以下几种(变量名称不区分大、小写),支持类型转换:
 1. (1) 整型变量
 分为整型变量(int)、无符号整型变量(uint/word),长整型(Long) 、无符号长整型(Ulong/dword)。
 2. (2) 浮点型变量(float)
 与ANSI C相同。
 3. (3) 字符型变量L
 分为字符型(char)变量和无符号字符型(Uchar)
 4. (4) 位变量(Bit)
 5. (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. (6) CPU变量
 即R0~R7、A、C(位变量)、B、DPTR及特殊功能寄存器变量,对这些变量均可进行读、写操作。
 7. (7) 用户源程序中定义的变量、数组、结构等
 4. 4. 运算符
 dScope支持ANSI C的运算符,包括算术运算符,逻辑运算符,关系运算符。
 5. 5. 表达式
 以运算符将dScope所支持的常量、变量、函数等连接在一起,就构成了dScope的表达式。
 6. 6. 数组
 dScope不支持在命令文件中定义数组,但可引用用户程序中的数组,引用方式如同C。
 7. 7. 结构和联合
 dScope不支持在命令文件中定义结构和联合,但可引用用户程序中的结构和联合,引用方式如同C,但如要输出整个结构或联合的结果,就要用命令“OBJ”。
 8. 8. 指针:
 不可自定义指针,但支持用户源程序中的指针变量。
 9. 9. dScope命令语句
 dScope提供了一系列调试命令。在命令文件中,dScope只支持这些语句及前述定义的表达式,C语言的语句均不被支持,但在命令文件所包含的用户自定义函数(非用户源程序中的函数)中支持C语句,但用户自定义函数中同样不支持数组、结构、联合和指针。
 1. (1) ASM
 在线汇编命令,格式如下:
 ASM C:0Xnnnn (或标号);设定插入汇编指令的地址
 ASM 汇编指令
 ASM 汇编指令
 插入完毕后,在debug窗口内选择“Assemble->Assemble”完成编译。
 2. (2) Assign
 串行口分配指令,格式如下:
 Assign channel<unreg>outreg
 对MCS51为:Assign Win<SOIN> Soot
 但目前的dScope版本并未提供完整串口窗口功能。
 3. (3) Define
 用户自定义变量指令,格式如下:
 Define <类型> <变量名>
 类型一为如前所述的变量类型,Define指令定义的变量可能为全局变量,可为用户自定义函数所引用。
 4. (4) Display
 内存显示命令,格式如下二:
 D 起始地址,结束地址
 地址如前所述的地址常数,标识符常量。
 5. (5) Enter
 内存修改指令,格式如下:
 E 类型地址=表达式 [表达式2],[……]
 类型如前所述,地址如前所述的地址常数。表达式如前所述,但如果是函数名称(含标号、指针变量),则关键字E→EP
 6. (6) Map/Reset map
 Map为内存段修改指令,Reset map将内存段复位或缺省值。
 7. (7) Object
 用以引用用户源程序中的结构(联合)、数组、格式如下:
 Obj表达式 [n,],[Line]
 表达式为用户源程序中的数组,结构(联合)名称。当Line缺省时,数目、结构(联合)的内容按n行输出;如有Line,则单行输出。
 8. (8) U
 反汇编命令,格式如下:
 U [地址]
 地址包括地址常 数及标识符常量,指明反汇编的起始地址。
 9. (9) WK
 观察点删除命令,格式如下:
 WK n1[n2 ],[……] ;删除指定的观察点,n为字符型,整型
 常数
 WK * ;删除所有的观察点
 10. (10) WS
 观察点设置命令,格式如下:
 WS 表达式[,n][LINE]
 关键字LINE存在时,观察点表达式单行输出
 LINE缺省时,观察点表达式n行输出。
 11. (11) G
 连续运行命令,格式如下:
 G [起始地址],[终止地址]
 地址为标识符常量或地址常数,地址缺省时,为连续运行。
 12. (12) T/P
 单步运行指令,格式如下:
 T/P n ;n指至单行运行的步数,P指给用户当调用某函数时,把它作为一步处理,并不进入该函数运行。
 13. (13) PA
 性能分析操作指令,其分以下几种:
 PA
 显示当前所设置的性能分析程度段
 PA Kill
 | 
 |