第1章 8051单片机与Keil Cx51基础
1.1 8051单片机的存储器组织结构
8051单片机最早由Intel公司推出,它在一块超大规模集成电路芯片上同时集成了CPU、ROM、RAM以及TIMER/COUNTER,使用者只需外接少量的接口电路就可组成自己的专用微处理器系统。目前,市场上8051单片机的硬件支持芯片及软件应用程序的种类十分丰富,除了Intel公司之外,还有Philips、Siemens、ADM、Fujutsu、OKI、ATMEL等公司都推出了以8051为核心的单片机。新一代的8051单片机集成度更高,在片内集成了更多的功能部件,如A/D、PWM、PCA、WDT以及高速I/O口等,在工业测量控制领域内得到极为广泛的应用,因此,有人指出8051单片机已成为事实上的工业标准。目前已有多个厂家生产不同型号的8051单片机,它们各有特点,但其基本内核相同,指令系统也完全兼容。
图1.1所示为8051基本内核的结构框图,包括:
● 中央处理器CPU,用于执行各种指令和运算处理;
● 内部数据存储器RAM,用于存放可以读写的数据;
● 内部程序存储器ROM,用于存放程序指令或某些常数表格;
● 4个8位的并行I/O接口P0、P1、P2和P3(每个接口都可以用做输入或者输出);
● 2个定时器/计数器,用做外部事件计数器或内部定时;
● 中断系统具有5个中断源(2个外部中断、2个定时器中断、1个串行口中断,采用2个优先级的嵌套中断结构,可实现二级中断服务程序嵌套,每一个中断源都可用软件程序规定为高优先级中断或低优先级中断);
● 1个串行接口电路(用做异步接收发送器);
● 内部时钟电路(晶体和微调电容需要外接,振荡频率可以高达40MHz)。
以上各部分通过内部总线相连接。在很多情况下,单片机还要和外部设备或外部存储器相连接,连接方式采用三总线(地址、数据、控制)方式,但在8051单片机中,没有单独的地址总线和数据总线,而是与并行I/O口中的P0口及P2口公用的,进行外部扩展时,P0口分别作为低8位地址线和8位数据线,P2口则作为高8位地址线用,所以也是16条地址线和8条数据线。但是读者一定要建立一个明确的概念,单片机进行外部扩展的地址线和数据线都不是独立的总线,而是与并行I/O口公用的,这是8051单片机结构上的一个特点。
对于采用高级语言Keil Cx51的用户来说,了解和熟悉8051单片机的存储器组织结构是十分必要的,这样在具体编程时可以合理安排各种变量,最大限度实现代码优化。从使用者的角度看,8051单片机有如下3个存储器空间。
图1.1 8051基本内核的结构框图
程序存储器ROM 对于普通8051单片机,程序存储器ROM空间大小为64KB,用于存放程序代码和一些表格常数,称为CODE空间。普通8051可采用“代码分组”(CODE BANK)设计技术,将ROM空间扩展到32×64KB,新型Philips 80C51Mx单片机的ROM空间最大可扩展到16 MB,称为ECODE和HCONST空间。8051单片机专门提供一个引脚“EA”来区分片内ROM和片外ROM,EA引脚接高电平时,单片机从片内ROM中读取指令,当指令地址超过片内ROM空间范围后,就自动地转向片外ROM读取指令;EA引脚接低电平时,所有的取指操作均对片外ROM进行。程序存储器的某些地址单元是保留给系统使用的:0000H~0002H单元是所有执行程序的入口地址,复位后CPU总是从0000H地址开始执行程序;0003H~002BH单元均匀地分为5段,用于5个中断服务程序的入口,产生某个中断时,将自动进入其对应入口地址开始执行中断服务程序,一些新型8051单片机增加了更多的中断源,它们的中断入口地址也相应增加。
片内数据存储器RAM 对于普通8051单片机,片内数据存储器RAM空间最大为256 B,用于存放程序执行过程的各种变量及临时数据。片内RAM的低128个字节可用直接寻址方式进行访问,也可用间接寻址方式访问,称为DATA区。其中,00H~1FH地址范围平均分为4组,每组都有8个工作寄存器R0~R7,称为工作寄存器区(Register Banks)。20H~2FH地址范围中,每个存储器单元的每一位都可以用位处理指令直接操作,该段地址范围称为位寻址区(BDATA区),其中每一位称为一个bit。对于51子系列单片机仅有上述低128个字节,对于52子系列单片机,增加了高128个字节的片内RAM,地址范围为80H~FFH,该范围只能采用间接寻址方式访问,整个片内RAM地址范围00H~FFH称为IDATA区。与IDATA空间高128个字节(地址范围80H~FFH)重叠部分称为特殊功能寄存器区(SFR SPACE),有些特殊功能寄存器是可以位寻址的,其可寻址位称为sbit。Philips公司推出的新型单片机80C51Mx,其片内RAM最大可扩充到64 KB,称为EDATA区。
片外数据存储器RAM 对于普通8051单片机,片外数据存储器RAM空间大小为64 KB,称为XDATA区。在XDATA空间内进行分页寻址操作时,称为PDATA区。有些新型80C51单片机的扩充片内RAM,需要用专门的特殊功能寄存器“映像”(MAP)到XDATA地址空间;还有一些新型80C51单片机可以将片外RAM最大扩展到16 MB,称为HDATA区。
图1.2所示为普通8051单片机的存储器组织结构,其中,各部分空间说明及地址范围见表1-1。
表1-1 普通8051单片机存储器空间分配表
图1.2 普通8051单片机的存储器组织结构
图1.3所示为新型80C51单片机的扩展存储器组织结构,其中各部分空间说明及地址范围见表1-2。
表1-2 新型80C51单片机扩展存储器空间分配表
图1.4所示为Philips 80C51Mx单片机的存储器组织结构,其中各部分空间说明及地址范围见表1-3。
表1-3 Philips 80C51Mx单片机存储器空间分配表
图1.3 新型8051单片机的扩展存储器组织结构
图1.4 Philips 80C51Mx单片机的存储器组织结构
1.2 Keil Cx51开发工具
C语言是一种通用的计算机程序设计语言,在国际上十分流行,它既可用来编写计算机的系统程序,也可用来编写一般的应用程序。以前计算机的系统软件主要是用汇编语言编写的,对于单片机应用系统来说更是如此。由于汇编语言程序的可读性和可移植性都较差,采用汇编语言编写单片机应用程序的周期长,而且调试和排错也比较困难。为了提高编制单片机应用程序的效率,改善程序的可读性和可移植性,采用高级语言无疑是一种最好的选择。
C语言既具有一般高级语言的特点,又能直接对计算机的硬件进行操作,表达和运算能力也较强,许多以前只能采用汇编语言来解决的问题现在都可以改用C语言来解决。德国Keil Software公司多年来致力于单片机C语言编译器的研究,该公司开发的Keil Cx51是一种专为8051单片机设计的高效率C语言编译器,符合ANSI标准,生成的程序代码运行速度极高,所需要的存储器空间极小,完全可以和汇编语言相媲美。
Keil公司目前已经推出了V7.0以上版本的Cx51编译器,为8051单片机软件开发提供了全新的C语言环境,同时保留了汇编代码高效、快速的特点。Cx51已被完全集成到一个功能强大的全新集成开发环境μVision2中,其中包括项目(Project)管理器、Cx51编译器、Ax51宏汇编器、BL51/Lx51连接定位器、RTX51实时操作系统、Simulator软件模拟器以及Monitor51硬件目标调试器,所有这些功能均可在μVision2提供的单一而灵活的开发环境中极为简便地进行操作。
μVision2提供了强大的项目管理功能,可以十分方便地进行结构化多模块程序设计。μVision2内部集成源级浏览器(Browser)利用符号数据库中详细的符号信息,使用户可以快速浏览源文件,并优化用户的变量数据存储器。
μVision2内部集成器件数据库(Device Database)储存了多种不同型号单片机的片上资源信息,通过它可以自动设置Cx51编译器、Ax51宏汇编器、BL51/Lx51连接定位器及调试器的默认选项,充分满足用户利用特定单片机片上集成外围功能的要求。
μVision2内部集成源程序编辑器允许用户在编辑源程序文件时(甚至在未经编译和汇编之前)设置程序调试断点,便于在程序调试过程中快速检查和修改程序。
μVision2提供文件查找功能,能对单一文件或全部项目文件进行指定搜索。此外还提供了用户工具菜单接口,允许在μVision2中直接启动用户功能。
μVision2支持软件模拟仿真(Simulator)和用户目标板调试(Monitor51)两种工作方式,在软件模拟仿真方式下不需要任何8051单片机硬件即可完成用户程序仿真调试,极大地提高了用户程序开发效率,在用户目标板调试方式下,利用硬件目标板中的监控程序可以直接调试目标硬件系统,使用户可以节省购买昂贵硬件仿真器的费用。
1.3 Cx51简单编程与调试
采用Keil Cx51开发8051单片机应用程序一般需要以下步骤。
① 在μVision2集成开发环境中创建一个新项目(Project),并为该项目选定合适的单片机CPU器件。
② 利用μVision2的文件编辑器编写C语言(或汇编语言)源程序文件,并将文件添加到项目中去。一个项目可以包含多个文件,除源程序文件外还可以有库文件或文本说明文件。
③ 通过μVision2的各种选项,配置Cx51编译器、Ax51宏汇编器、BL51/Lx51连接定位器以及Debug调试器的功能。
④ 利用μVision2的构造(Build)功能对项目中的源程序文件进行编译连接,生成绝对目标代码和可选的HEX文件,如果出现编译连接错误则返回到第②步,修改源程序中的错误后重新构造整个项目。
⑤ 将没有错误的绝对目标代码装入μVision2调试器进行仿真调试,调试成功后将HEX文件写入到单片机应用系统的EPROM中。
下面通过一个简单实例进行说明这几个步骤。启动μVision2后,单击“Project/New Project”菜单选项,在弹出的对话框窗口中输入项目文件名max,并选择合适的保存路径(通常为每个项目建一个单独的文件夹),单击“保存”按钮,这样就创建了一个文件名为max.uv2的新项目文件,如图1.5所示。
图1.5 在μVision2中新建一个项目
项目名保存完毕后将弹出如图1.6所示器件数据库对话框窗口,用于为新建项目选择一个CPU器件(窗口的Description栏对不同公司生产的8051CPU器件做了必要说明),根据需要选择CPU器件(例如Atmel公司的AT89C51),选定后μVision2将按所选器件自动设置默认的工具选项,从而简化了项目的配置过程。
图1.6 为项目选择CPU器件
创建一个新项目后,项目中会自动包含一个默认的目标(Target 1)和文件组(Source Group 1)。用户可以给项目添加其他文件组(Group)以及文件组中的的源文件,这对于模块化编程特别有用。项目中的目标名、组名以及文件名都显示在μVision2的项目窗口“Files”标签页中。接下来要给项目添加源程序文件,源文件可以是已有的,也可以是新建的。新建源文件时单击菜单“File /New”,在打开的编辑窗口中输入下例的C51源程序。
例:求两个输入数据中的较大者。
# include<stdio.h> /* 预处理命令 */ # include<reg51.h> char max (char x , char y) { /* 定义max函数,x、y为形式参数*/ if ( x > y ) return (x); /* 将计算得到的最大值返回到调用处*/ else return(y) ; } /* max函数结束 */ main() { /* 主函数 */ char a, A, c; /* 主函数的内部变量类型说明 */ SCON=0x52; /* 8051单片机串行口初始化 */ TMOD=0x20; TCON=0x69; TH1=0x0F3; scanf ("%c %c", &a, &A); /* 输入变量a和b的值 */ c= max (a,A); /* 调用max函数 */ printf ( " \n max =%c \n ", c); /* 输出变量c的值 */ } /* 主程序结束 */
程序输入完成后,单击菜单“Files /Save As…”,如图1.7所示,将其另存为扩展名为.C的源程序文件,其存放的路径一般设为与项目文件相同。
图1.7 保存新建项目中的源程序文件
μVision2具有十分完善的右键功能,将鼠标指向项目窗口的“Files”标签页中的“Source Group 1”文件组并单击右键,会弹出一个快捷菜单,如图1.8所示。
图1.8 项目窗口的右键菜单
单击快捷菜单中的“Add Files to Group ‘Source Group 1’”选项,弹出如图1.9所示添加源文件选择窗口,选中刚才保存的源程序文件“max.c”,并单击“Add”按钮,将其添加到新创建的项目中去。
图1.9 添加源文件选择窗口
接下来根据需要配置Cx51编译器、Ax51宏汇编器、BL51/Lx51连接定位器以及Debug调试器的各项功能。单击菜单“Project/Options for Target”,弹出如图1.10所示窗口,这是一个十分重要的窗口,包括“Device”、“Target”、“Output”、“Listing”、“C51”、“A51”、“BL51 Locate”、“BL51 Misc”和“Debug”等多个选项标签页,其中许多选项可以直接用其默认值,必要时可进行适当调整。
图1.10所示为其中的“Target”标签页,用于设定目标硬件系统的时钟频率Xtal为24.0 MHz;C51编译器的存储器模式为Small(C51程序中局部变量位于片内数据存储器DATA空间);程序存储器ROM空间设为Large(使用64KB程序存储器);不采用实时操作系统;不采用代码分组设计。
图1.10 配置“Target”标签页
图1.11所示为“Output”标签页,用于设定当前项目在编译连接之后生成的执行代码输出文件。输出文件名默认为与项目文件同名(也可以指定其他文件名),存放在当前项目文件所在的目录中,也可以单击“Select Folder For Objects”来指定存放输出文件的目录路径。
● 选中“Create Executable”表示项目编译连接后生成执行代码输出文件。
● 选中复选框“Debug Information”将在输出文件中包含进行源程序调试的符号信息。
● 选中复选框“Browse Information”将在输出文件中包含源程序浏览信息。
● 选中复选框“Create HEX File”表示当前项目编译连接完成之后生成一个用于EPROM编程的HEX文件。
● 在“After Make”栏中选中复选框“Beep When Complete”和复选框“Start Debugging”表示编译连接完成之后计算机将发出一声提示音,并立即进入调试状态。
图1.11 设定执行代码输出文件选项
图1.12所示为“C51”标签页,用于设定当前项目对Cx51编译器的控制命令选项。“Preprocessor Symbols”栏用于定义Cx51预处理器符号,定义符号后一般要在源程序中增加相应的“ifdef”、“ifndef”、“endif”等预处理器命令。
●“Code Optimization”栏用于设定Cx51编译器的优化级别,需要注意的是优化级别并非越高越好,应根据具体要求适当选择,关于Cx51编译器优化级别的详细描述请参阅本书第9章。
●“Warning”栏用于选择编译时给出警告信息的详细程度,编号越大越详细。
●“Include Paths”栏用于指定用户规定的包含文件路径,可以手工指定路径,也可以通过该栏右边的“…”按钮来浏览选择路径。
●“Misc Controls”用于增加除了Cx51编译器默认选项之外的其他命令选项。
● 所有选定的编译命令选项都会显示在“Compiler control string”栏内。
图1.13所示为“BL51 Locate”标签页,用于设定当前项目对BL51连接定位器的命令选项。选中复选框“Use Memory Layout from Target Dialog”时,BL51连接定位器将按前面“Target”标签页中的设定对执行代码进行存储器地址空间定位,这也是BL51的默认选项。不选中该复选框则应在其他栏内填入希望的存储器地址空间范围值。关于BL51连接定位器对存储器地址空间处理的详细讨论请参阅本书第11章。
图1.12 设定Cx51编译器命令选项
图1.13 设定BL51连接定位命令选项
图1.14所示为“Options”选项中的“Debug”标签页,用于设定μVision2调试器的一些选项。在μVision2中可以对经编译连接所生成的执行代码进行两种仿真调试:软件模拟仿真调试和目标硬件仿真调试,前者不需要8051单片机硬件,仅在PC机上就可以完成对8051单片机各种片内资源的仿真,仿真结果可以通过μVision2的串行窗口、观察窗口、存储器窗口及其他一些窗口直接输出,其优点是不言而喻的,缺点是不能观察到实际硬件的动作。
Keil公司还提供了一种目标监控程序Monitor51,通过它可以实现μVision2与用户目标硬件系统相连接,进行目标硬件的在线仿真调试,这种方法可以立即观察到目标硬件的实际动作,特别有利于分析和排除各种硬件故障。通常可以先对用户程序进行软件模拟仿真,排除一般性错误,然后再进行目标硬件仿真调试。
进行软件模拟仿真时应选中“Debug”标签页中的“Use Simulator”圆形单选框,进行目标硬件仿真调试时则要选中“Use Keil Monitor-51 Driver”圆形单选框,为了便于读者进一步学习Keil Cx51应用编程,开发自己的单片机系统,本书作者设计了一种能直接与μVision2接口的“Keil Cx51源程序仿真硬件目标板”,其中预装了Keil公司提供的Monitor-51监控程序,可以实现与μVision2无缝连接,使用非常方便,节省用户购买昂贵硬件仿真器的费用,关于它的具体使用方法请参阅本书8.4节。
图1.14 设定Debug仿真调试选项
在该窗口所有的标签页中都有一个“Defaults”按钮,用于设定各种默认命令选项,初次使用时可以直接采用这些默认值,待熟悉之后再进一步采用其他选项。有关其他标签页的详细描述请参阅本书第7章。
完成上述关于编译、连接定位、仿真调试工具配置的基本选项设定之后,就可以对当前新建项目进行整体创建(Build target)。将鼠标指向项目窗口中的文件“max.c”并单击右键,从弹出的快捷菜单中单击“Build target”选项,如图1.15所示,μVision2将按“Options for Target”窗口内各种选项设置,自动完成对当前项目中所有源程序模块文件的编译连接,同时μVision2的输出窗口将显示编译连接提示信息,如图1.16所示,如果有编译连接错误,将鼠标指向窗口内的提示信息后双击,光标将自动跳到编辑窗口源程序文件发生错误的地方,以便于修改。如果没有编译连接错误则生成绝对目标代码文件。
编译连接完成后将μVision2转入仿真调试状态,在此状态下的“项目窗口”自动转到“Regs”标签页,显示调试过程中单片机内部工作寄存器R0~R7、累加器A、堆栈指针SP、数据指针DPTR、程序计数器PC以及程序状态字PSW等的值,如图1.17所示。
在仿真调试状态下单击“Debug/Go”菜单项,启动用户程序全速运行,再单击“View/Serial Window #1”选项,打开调试状态下μVision2的串行窗口1,用户程序中采用scanf()和printf()所进行的输入和输出操作,都是通过串行窗口1实现的,将鼠标指向该窗口并键入数字2和9,立即得到输出结果“max=9”,如图1.18所示。
图1.15 利用右键快捷菜单对当前项目进行编译连接
图1.16 编译连接完成后输出窗口的提示信息
μVision2调试器的仿真功能十分完善,除了全速运行之外还可以进行单步、设置断点、运行到光标指定位置等多种操作,调试过程中可随时观察局部变量以及用户设置的观察点状态、存储器状态、片内集成外围功能状态,通过调用信号函数或用户函数可实现其他多种仿真功能。关于μVision2调试器的详细介绍请参阅本书第7章。
图1.17 μVision2的仿真调试状态窗口
图1.18 μVision2调试状态下串行窗口1及其数据输入和结果输出