单片机原理与嵌入式系统设计
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.3 Keil C51高级语言集成开发环境—µVision2 IDE

单片机系统的编程语言有汇编语言和高级语言两种。每一种类型的单片机都有与其指令系统对应的汇编语言,优点是可直接操作硬件,可执行文件比较小,而且执行速度很快,缺点是软件的维护性和可移植性差。

单片机的高级语言包括:BASIC语言、PL/M语言和C语言。BASIC语言主要应用在MCS-51系列单片机上,使用效果不是很理想,现在已经不再使用。PL/M语言对硬件的控制能力和代码效率都很好,但局限于Intel公司的微处理器系列,可移植性差。

Keil C51软件是目前开发80C51系列单片机最流行的软件工具,这从近年来各单片机仿真机厂商纷纷宣布全面支持Keil C51即可看出。Keil C51提供了包括C语言编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(µVision2 IDE)将这些部分组合在一起。掌握这一软件的使用对于使用80C51系列单片机的爱好者来说是十分必要的,即使不使用C语言而仅使用汇编语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会让开发者事半功倍。

3.3.1 µVision2 IDE主要特性

µVision2 IDE基于Windows的开发平台,包含一个高效的编辑器、一个项目管理器和一个MAKE工具。µVision2 IDE支持所有的Keil C51工具,包括C语言编译器、宏汇编器、连接/定位器、目标代码到 HEX的转换器。

µVision2 IDE内嵌有多种符合当前工业标准的开发工具,可以完成工程建立、管理、编译连接、目标代码的生成、软件仿真、硬件仿真等完整的开发流程。尤其C语言编译工具在产生代码的准确性和效率方面达到了较高的水平,而且可以附加灵活的控制选项,在开发大型项目时非常理想。它的主要特性如下。

(1)集成开发环境

µVision2 IDE包括一个工程管理器、一个功能丰富并有交互式错误提示的编辑器、选项设置、生成工具及在线帮助。可以使用µVision2 IDE创建源文件,并组成应用工程加以管理。µVision2 IDE可以自动完成编译、汇编和链接程序的操作,使用户可以只专注开发工作的效果。

(2)C51 编译器和A51汇编器

由µVision2 IDE创建的源文件,可以被C51编译器或A51汇编器处理,生成可重定位的object文件,Keil C51编译器遵照ANSI C语言标准,支持C语言的所有标准特性。另外还增加了几个可以直接支持80C51结构的特性。Keil A51宏汇编器支持80C51及其派生系列的所有指令集。

(3)LIB51库管理器

LIB51库管理器可以从由汇编器和编译器创建的目标文件建立目标库。这些库是按规定格式排列的目标模块,可在以后被链接器所使用。当链接器处理一个库时,仅仅使用了库中程序使用的目标模块而不是全部加以引用。

(4)BL51链接器/定位器

BL51链接器使用从库中提取出来的目标模块和由编译器、汇编器生成的目标模块,创建一个绝对地址目标模块。绝对地址目标文件或模块包括不可重定位的代码和数据。所有的代码和数据都被固定在具体的存储器单元中。绝对地址目标文件可以用于:

编程 EPROM 或其他存储器设备;

由µVision2 IDE调试器对目标进行调试和模拟;

使用在线仿真器进行程序测试。

(5)µVision2软件调试器

µVision2 IDE软件调试器能十分理想地进行快速、可靠的程序调试。调试器包括一个高速模拟器,可以使用它模拟整个80C51系统,包括片上外围器件和外部硬件。当从器件数据库选择器件时,这个器件的属性会被自动配置。

(6)µVision2 IDE硬件调试器

µVision2 IDE调试器提供了几种在实际目标硬件上测试程序的方法。

安装 MON51目标监控器到用户的目标系统,并通过Monitor-51接口下载程序。

使用高级GDI接口将µVision2 IDE调试器同第三方仿真器系统相连接,通过µVision2 IDE的人机交互环境完成仿真操作。

(7)RTX-51实时操作系统

RTX-51实时操作系统是针对80C51微控制器系列的一个多任务内核。RTX-51实时内核简化了需要对实时事件进行反应的复杂应用的系统设计、编程和调试。这个内核完全集成在C51编译器中,使用非常简单。任务描述表和操作系统的一致性由BL51链接器/定位器自动进行控制。

3.3.2 µVision2 IDE集成开发环境

安装完成后,用户可以双击桌面上的“µVision2”图标进入IDE环境,µVision2 IDE软件有菜单栏、可以快速选择命令按钮的工具栏、一些源代码文件窗口、对话框、信息显示窗口。µVision2 IDE界面如图3.5所示,µVision2 IDE允许同时打开、浏览多个源文件。

图3.5 µVision2 IDE界面图

µVision2 IDE提供下拉菜单和工具条按钮两种操作方式。下拉菜单提供多种选项,根据不同需要选用,工具条按钮实际上是下拉菜单中一些重要选项功能的快捷方式。表3.1~表3.7从µVision2 IDE的下拉菜单着手介绍它的具体功能。

表3.1 File(文件)菜单和命令

表3.2 Edit(编辑)菜单和编辑器命令

表3.3View(视图)菜单

表3.4 Project(项目)菜单和命令

表3.5 Debug(调试)菜单和命令

表3.6 Peripherals(外围器件)菜单*

* 外围器件菜单显示内容引与选择的MCU型号有关。

表3.7 Window(窗口)菜单

3.3.3 µVision2 IDE的使用

µVision2 IDE安装后自带了一些帮助文档,位于安装目录的Keil\C51\HLP文件夹,包括A51.pdf、C51.pdf、C51lib.chm、DBG51.CHM、errors.chm、GS51.pdf等,可以通过µVision2开发环境Project Window的Books标签页中的链接来打开这些文档。GS51.pdf是一个入门教程“Getting Started with µVision2”。这些资料详细介绍了集成开发环境使用、侦错、汇编语言编程(A51)、C语言编程(C51)等。在互联网上,有“µVision2入门教程”、“µVision2 调试命令”、“Keil Software-Cx51编译器用户手册中文完整版”和“Keil C51使用详解”等中文资料。

µVision2 IDE包括一个项目管理器,它可以使基于8x51的嵌入式系统的设计变得简单。要创建一个应用,需要按下列步骤进行操作:

① 启动µVision2 IDE,新建一个项目文件,并从器件库中选择一个CPU器件;

② 新建一个源文件并把它加入到项目中;

③ 增加并设置选择的器件的启动代码;

④ 针对目标硬件设置工具选项;

⑤ 编译项目并生成可以编程ROM的HEX文件。

下面通过一个创建项目实例介绍在µVision2中的软件开发流程。

下面将逐步描述,指引读者创建一个简单的µVision2项目。示例程序调用C51基本输入/输出库stdio.h中的printf函数从串口输出“Hello World!”,printf函数支持带格式的输出,整个程序只包含一个源文件HelloWorld.c,这个小型应用程序帮助读者确定Keil µVision2可以编译、链接和调试一个应用程序。

设项目名为HelloWorld,采用标准AT89C52芯片,程序使用的硬件资源是AT89C52片内的并行I/O口P2和串行口,不需要一个实际的单片机系统,因为µVision2 IDE可以模拟程序所需要的硬件并行I/O口和串行口。

(1)选择Project→New Project选项,如图3.6所示。

(2)在弹出的Create New Project对话框中选择要保存项目文件的路径,比如保存到HelloWorld目录里,在“文件名”文本框中输入项目名为HelloWorld,如图3.7所示,然后单击“保存”按钮。

图3.6 Project菜单

图3.7 Create New Project对话框

(3)这时会弹出一个对话框,要求选择单片机的型号。读者可以根据使用的单片机型号来选择,Keil C51几乎支持所有的80C51内核的单片机,这里以常用的 AT89C52为例来说明。先选择ATMEL公司,再选择AT89C52,如图3.8所示,右边Description栏中显示该单片机的基本说明,然后单击“确定”按钮,弹出将8051初始化代码复制到项目中的询问窗口,如图3.9所示。单击“是”按钮,出现图3.10所示的窗口。如果需要重命名Target1和Source Group1,在左侧Project Workspace区用鼠标左键选中Target1,再用鼠标左键单击Target1,即可重新命名Target1。用同样的方法可以修改Source Group1,这里对此不做修改,使用默认名称。

(4)这时需要新建一个源程序文件。建立一个汇编语言或C语言文件,如果已经有源程序文件,可以忽略这一步。选择File→New选项,如图3.11所示。

图3.8 选择单片机型号对话框图

图3.9 选择是否加入初始化代码询问信息

图3.10 新建项目后µVision2界面图

图3.11 新建源程序文件对话框图

(5)在弹出的程序文本框中输入一个简单的程序,如图3.12所示,具体内容见本节后面的内容。

(6)选择File→SaveAs选项或者单击工具栏按钮,保存文件。

在弹出的如图3.13所示的对话框中,选择要保存的路径,在“文件名”文本框中输入文件名。注意,一定要输入扩展名,如果是C语言程序文件,扩展名为.c;如果是汇编文件,扩展名为.asm或.a51;如果是ini文件,扩展名为.ini。这里需要存储C语言源程序文件,所以输入扩展名.c(也可以保存为其他名字,比如new.c等),单击“保存”按钮。此处保存文件名为HelloWorld.c。

图3.12 程序文本框

图3.13 Save As对话框

(7)将HelloWorld.c文件加入到项目中,鼠标右键单击左边项目窗口中的Source Group1,在弹出的菜单中选择Add Files to Group 'Source Group 1',选择刚才建立的文件 HelloWorld.c,如图3.14所示,文件类型选择 C Source file(*.c)。如果是汇编文件,则选择 Asm Source file;如果是目标文件,则选择 Object file;如果是库文件,则选择 Library file。最后单击Add按钮,如果要添加多个文件,可以不断添加或一并选中添加。添加完毕后单击Close按钮,关闭该窗口。

图3.14 Add Files to Group 'Source Group 1'菜单

(8)这时在Source Group 1里就有 HelloWorld.c文件和事先建立项目时已经加入的文件STARTUP.a51了,如图3.15所示。

图3.15 HelloWorld.c文件

(9)接下来要对目标进行一些设置。选择Project→Options for Target 'Target 1'选项,或用鼠标右键单击Target 1,在弹出的快捷菜单中选择 Options for Target 'Target 1'选项,如图3.16所示。

(10)在弹出的Options for Target 'Target 1'对话框中有10个选项卡,如图3.17所示。

图3.16 Options for Target 'Target 1' 选项

图3.17 Target选项卡

① Target选项卡

Xtal(MHz):设置单片机工作的频率,默认是24.0MHz,把此项改为80C51单片机经常使用的晶振频率11.0592MHz和22.1184MHz之一,即11.0592MHz。Target选项卡中仅修改此项,其他默认即可。

Use On-chip ROM(0x0-0x1FFF):表示使用片上的Flash ROM。AT89C52有8KB的可重编程的Flash ROM,该选项取决于单片机嵌入式系统,如果单片机的EA接高电平,则选中这个选项,表示使用内部ROM,如果单片机的EA接低电平,表示使用外部ROM,则不选中该选项。

Off-chip Code memory:表示片外ROM的开始地址和大小,如果没有外接程序存储器,那么不需要填任何数据。Start表示一个ROM芯片的开始地址,Size为片外ROM的大小,一般填十六进制的数,Size为片外ROM的大小,最多可以外接3块ROM。

Off-chip Xdata memory:可以填写外接Xdata外部数据存储器的起始地址和大小。

CodeBanking:使用CodeBanking技术。Keil可以支持程序代码超过64KB的情况,最大可以有2MB的程序代码。如果代码超过64KB,那么就要使用CodeBanking技术,以支持更多的程序空间。CodeBanking支持自动的Bank的切换,这在建立一个大型系统时是必需的。例如,要在单片机里实现汉字字库、实现汉字输入法,都要用到该技术。

Memory Model:单击Memory Model后面的下拉箭头,会有3个选项。

Small:变量存储在内部RAM里。

Compact:变量存储在外部RAM里,使用8位间接寻址。

Large:变量存储在外部RAM里,使用16位间接寻址。

一般使用Small来存储变量,此时单片机优先将变量存储在内部RAM里,如果内部RAM空间不够,才会存到外部RAM中。Compact的方式要通过程序来指定页的高位地址,编程比较复杂,如果外部RAM很少,只有256B,那么对该256B的读取就比较快。

如果超过256B,而且需要不断地进行切换,就比较麻烦,Compact模式适用于比较少的外部RAM的情况。Large模式是指变量会优先分配到外部RAM里。

需要注意的是,3种存储方式都支持内部256B和外部64KB的RAM。因为变量存储在内部RAM里,运算速度比存储在外部RAM要快得多,大部分的应用都选择Small模式。

使用Small模式时,并不说明变量就不可以存储在外部,只是需要特别指定,比如:

unsigned char xdata a:变量a存储在外部的RAM。

unsigned char a:变量存储在内部RAM。

但是使用Large的模式时:

unsigned char xdata a:变量a存储在外部的RAM。

unsigned char a:变量a同样存储在外部RAM。

这就是它们之间的区别,可以看出这几个选项只影响没有特别指定变量的存储空间的情况,默认存储在所选模式的存储空间,比如上面的变量定义unsigned char a。

Code Rom Size:单击Code Rom Size后面的下拉箭头,将有3个选项。

Small: program 2K or less:适用于AT89C2051这些芯片,2051只有2KB的代码空间,所以跳转地址只有2KB,编译的时候会使用ACALL AJMP这些短跳转指令,而不会使用LCALL、LJMP指令。如果代码地址跳转超过2KB,那么会出错。

Compact:2K functiongs,64K program:表示每个子函数的代码大小不超过2KB,整个项目可以有64KB的代码。就是说在mAin()里可以使用LCALL、LJMP指令,但在子程序里只会使用ACALL、AJMP指令,只有确定每个子程序不会超过2KB,才可以使用Compact方式。Large: 64K program:表示程序或子函数代码都可以大到64KB,使用CodeBanking还可以更大,通常都选用该方式。选择Large方式速度不会比Small慢很多,所以一般没有必要选择Compact和Small方式。

这里选择Large方式。

Operating:单击Operating后面的下拉箭头,会有3个选项。

None:表示不使用操作系统。

RTX-51 Tiny Real-Time OS:表示使用Tiny操作系统。

RTX-51 Full Real-Time OS:表示使用Full操作系统。

这里选择 None。

② Output选项卡

Output选项卡如图3.18所示。

图3.18 设置Output卡

Select Folder for Objects:单击该按钮可以选择编译后目标文件的存储目录,如果不设置,就存储在项目文件的目录里。

Name of Executable:设置生成的目标文件的名字,默认情况下和项目的名字一样。目标文件可以生成库或者obj、HEX的格式。

Create Executable:如果要生成OMF和HEX文件,一般选中Debug Information和Browse Information,选中这两项,才有调试所需的详细信息。比如,要调试C语言程序,如果不选中,调试时将无法看到高级语言写的程序。而HEX文件为最终目标文件,需要写入目标系统的程序存储器中。

Create HEX File:要生成 HEX文件,一定要选中该选项,如果编译之后没有生成HEX文件,就是因为这个选项没有被选中。默认是不选中的。ProteusVSM与µVision2联调时需要HEX文件(见3.4.3节),一般选中它。

Create Library:选中该项时将生成lib库文件。根据需要决定是否要生成库文件,一般的应用是不生成库文件的。

AftermAke栏中有以下几个设置。

  • Beep When Complete:编译完成之后发出咚的提示声音。
  • Start Debugging:马上启动调试(软件仿真或硬件仿真),根据需要来设置,一般不选。为了产生编译之后马上运行,也可选中它。
  • Run User Program #1、Run User Program #2:这两个选项可以设置编译完之后所要运行的其他应用程序(比如有些用户自己编写了烧写芯片的程序,编译完便执行该程序,将 HEX文件写入芯片),或者调用外部的仿真程序。根据自己的需要设置。

③ Listing选项卡

Listing选项卡如图3.19所示。

图3.19 设置Listing选项卡

Keil C51在编译之后除了生成目标文件之外,还生成*.lst、*.m51的文件。这两个文件可以告诉程序员程序中所用的idata、data、bit、xdata、code、RAM、ROM、stack等的相关信息,以及程序所需的代码空间。

选中Assembly Code会生成汇编的代码。这是很有好处的,如果不知道如何用汇编来写一个long型数的乘法,那么可以先用C语言来写,写完之后编译,就可以得到用汇编实现的代码。对于一个高级的单片机程序员来说,往往既要熟悉汇编,同时也要熟悉C语言,才能更好的编写程序。某些地方用C语言无法实现,用汇编语言却容易实现;有些地方用汇编语言很烦琐,用C语言就很方便。

单击Select Folder for Listings按钮,在出现的对话框中可以选择生成的列表文件的存放目录。不做选择时,使用项目文件所在的目录。

④ Debug选项卡

Debug选项卡如图3.20所示。

图3.20 设置Debug选项卡

Load Application at Start:选择这项之后,Keil才会自动装载程序代码。

Go tillmAin:调试C语言程序时可以选择这一项,PC会自动运行到main程序处。

这里有两类仿真形式可选:Use Simulator和Use: Keil Monitor-51 Driver,前一种是纯软件仿真,后一种是带有Monitor-51硬件目标仿真器的仿真。

因为我们目前没有硬件系统,图3.20中使用默认选择Use Simulator。

最后单击OK按钮关闭对话框。

(11)编译连接程序,按F7或选择Project→Rebuild all target files选项,如图3.21所示。

如果没有错误,则编译连接成功,开发环境下面会显示编译连接成功的信息,如图3.22所示。

(12)编译完毕之后,选择Debug→Start/Stop Debug Session选项,即可进入Debug调试环境,如图3.23所示。

(13)装载代码之后,开发环境Output Window(在左下角)显示如图3.24所示的装载成功信息。

图3.21 Rebuild all target files

图3.22 编译连接成功信息

图3.23 Debug调试

图3.24 Debug调试界面

(14)示例程序使用串口打印函数printf输出“Hello World!”,整个程序只包含一个源文件HelloWorld.c。使用串口打印函数printf需要初始化单片机串口相关寄存器,故HelloWorld.c除main函数外,还有串口初始化函数initUart。此处我们只关心µVision2 IDE开发工具的使用,单片机串口的具体使用方法会在后续章节介绍。

HelloWorld.c源程序如下:

#include <REG52.H>//片内寄存器定义
#include <stdio.h>//输入/输出函数库
void initUart(void);/*初始化串口波特率,使用定时器1*/
/***********mAin C **************/
voidmAin (void)
{
unsigned int ulTimer;//延时设定的循环次数
    initUart();//为了使用printf语句,要初始化串口
    while (1){
        printf ("Hello World!");/* Print "Hello World" */
        for (ulTimer=0; ulTimer<1000; ulTimer++){}//延时
    }
}
/********** 初始化串口波特率 ************/
//为了使用串行口带格式输出函数printf,串口必须初始化
void initUart(void)/*初始化串口波特率,使用定时器1*/
{
/* Setup the serial port for 9600Baud at 11.0592MHz */
   SCON=0x50;/* SCON: mode 1,8-bit UART,enable rcvr */
    TMOD |=0x20;/* TMOD: timer 1,mode 2,8-bit reload */
    TH1=0xfd;/* TH1: reloadValue for 9600Baud @ 11.0592MHz */
    TR1=1;/* TR1: timer 1 run */
    TI=1;/* TI: set TI to send first char of UART */
}

选择View→Serial Window #1选项,查看串口输出内容,如图3.25示。

选择Peripherals中选项,还可以查看单片机内嵌外设的变化,如选择Peripherals→I/O-Ports→Port 2选项,则可查看P2口信号变化,如图3.26示。

图3.25 打开Serial Window #1

图3.26 打开Parallel Port2

按F5键启动程序,在串口窗口Serial #1可看到printf的输出信息和P2端口数据的变化情况,如图3.27所示。串口窗口默认字符显示模式为Ascii Mode,在窗口中单击鼠标右键,在弹出的右键窗口中可修改显示模式为Hex Mode。

图3.27 程序连续运行时的窗口显示

3.3.4 Keil C51中printf库函数

printf函数是极为方便的信息输出函数,能将程序中的各种变量的值快速格式化并输出到控制台,在程序调试和测试中无处不在,C语言教材的例子程序中经常要用到它作为输出。

在前面介绍µVision2 IDE的使用中我们也用到printf函数,Keil C51的printf使用也极为方便,只要初始化串口后,关中断,TI=1,就能使用printf直接将信号输出到串口,在µVision2 IDE调试时,打开串口窗口,就能看到带格式的输出。串口的使用方法见第6章内容。