第3章 基于Keil软件的设计入门
3.1 Keil软件的使用
随着单片机技术的不断发展,以单片机C语言为主流的高级语言不断被更多的单片机爱好者和工程师所喜爱。使用C51单片机时肯定要使用到编译器,以便把写好的C程序编译为机器代码,这样单片机才能执行编写好的程序。Keil μVision 4由德国Keil Software公司推出,是众多单片机应用开发软件中优秀的软件之一,它支持众多不同公司的MCS51架构的芯片,支持PLM、汇编和C语言的程序设计,它提供了包括编辑、编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器,其内置的仿真器可模拟目标MCU,包括指令集、片上外围设备及外部信号等。同时它又有逻辑分析器,可监控基于MCU I/O引脚和外设状况变化下的程序变量。它界面友好,易学易用,在调试程序、软件仿真方面也有很强大的功能。本书是基于Keil C51而编写的。
在这一章首先将以一流水灯的设计为例,了解如何输入源程序,建立工程、对工程进行详细的设置,以及如何将源程序变为目标代码。
【例3-1】流水灯设计,如图3-1所示。
图3-1 流水灯硬件电路图
3.1.1 Keil μVision4 工程文件的建立
首先打开Keil μVision4软件,双击Keil μVision4图标。
Keil μVision4启动后,程序窗口的左边有一个工程管理窗口,该窗口有3个标签,分别是Files、Regs、Books,如果是第一次启动Keil,那么这3个标签全是空的,这3个标签的含义如下。
Files:显示当前项目的文件结构;
Regs:显示CPU的寄存器及部分特功能寄存器的值(调试时才出现);
Books:显示CPU的附加说明文件。
1.源文件的建立
使用菜单命令File→New或者单击工具箱的新建文件按钮,即可在项目窗的右侧打开一个新的文本编辑窗口,在该窗口中输入以下源程序:
保存该文件,注意必须加上扩展名(汇编语言源程序一般用.ASM或.A51为扩展名,如果是C语言用.c),这里假定将文件保存为流水灯.c。需要说明的是,源文件就是一般的文本文件,可以使用任意文本编辑。
2.建立工程文件
在项目开发中,并不是仅有一个源程序就行了,为了管理和使用方法,引入了Keil使用工程(Project)这一概念,下面介绍如何新建工程。
1)选择Project下的New μVision4 Project菜单,如图3-2所示,出现“Save As”对话框。选择放置工程的路径,然后给工程取名为例1,不需要扩展名,单击“保存”按钮,如图3-3所示。
图3-2 给文件起名和选择保存路径
图3-3 新建工程
2)选择正在使用的芯片,先选择厂家,然后是型号使用AT89S52时选择Atmel→AT89S52,选好芯片后单击确定按钮,如图3-4所示。
3)窗口左测出现如图3-5所示工程目录。新建工程至此完成。此时的工程是一个空的工程,里面什么文件也没有,需要手动把刚才编写好的源程序导入,单击Source Group1选项后单击鼠标右键,出现一个下拉菜单,如图3-5所示,选中Add Files to Group ‘Source Group1’选项,出现一个对话框,要求寻找源文件。找到刚才保存的“流水灯.c”双击鼠标将文件导入项目。
图3-4 选择所使用的目标芯片
图3-5 给工程添加文件
单击Source Group1选项前的加号,会发现“流水灯.c”文件已在其中。双击文件名,即可打开该源程序,如图3-6所示。
图3-6 打开工程下的文件
3.1.2 Keil μVision4 工程的详细设置
在Target 1界面中右击选择Options for Target 'target 1'选项或者使用菜单命令Project→Option for target 'target 1'即出现对工程设置的对话框,如图3-7所示。这个对话框可谓非常复杂,共有11个选项卡,要全部学会可不容易,好在绝大部分设置项取默认值就行了。
图3-7 选择工程设置的对话框
1.Target选项卡
Xtal文本框用于设置晶振频率,默认值是所选目标CPU的最高可用频率值,对于所选的AT89S52一般而言是24M,该值与最终产生的目标代码无关,仅用于软件模拟调试时显示程序执行时间。正确设置该数值可使显示时间与实际所用时间一致,一般将其设置成与用户硬件所用晶振频率相同,如果没必要了解程序执行的时间,也可以不设,这里设置为12,如图3-8所示。
图3-8 Target选项卡
Memory Model下拉列表框用于设置RAM使用情况,Small是所有变量都在单片机的内部RAM中;Compact是可以使用一页外部扩展RAM;Larget则是可以使用全部外部的扩展RAM。Code Model用于设置ROM空间的使用,Small模式,只用低于2KB的程序空间;Compact模式,单个函数的代码量不能超过2KB,整个程序可以使用64KB程序空间;Larget模式,可用全部64KB空间。
Use on-chip ROM复选项用于确认是否仅使用片内ROM。(注意:选中该项并不会影响最终生成的目标代码量。)
Operating System下拉列表框用于操作系统选择,Keil提供了两种操作系统:Rtx tiny和Rtx full,关于操作系统是另外一个很大的话题了,通常选用该项的默认值:None(不使用任何操作系统);
Off Chip Codememory选项组用以确定系统扩展ROM的地址范围,Off Chip XData memory选项组用于确定系统扩展RAM的地址范围,这些选择项必须根据所用硬件来决定,由于该例是单片应用,未进行任何扩展,所以均不重新选择,按默认值设置。
2.Output选项卡
Creat HEX file复选项用于生成可执行代码文件(可以用编程器写入单片机芯片的HEX格式文件,文件的扩展名为.HEX),默认情况下该项未被选中,如果要写片做硬件实验,就必须选中该项,这一点是初学者易疏忽的。
HEX文件格式是Intel公司提出的用来保存单片机或其他处理器的目标程序代码的文件格式。一般的编程器都支持这种格式。选中Creat HEX file复选项,使程序编译后产生HEX代码,如图3-9所示,供下载器软件下载到单片机中。
图3-9 Output选项卡
需要特别提醒注意的是,单片机只能下载HEX文件或BIN文件,HEX文件是十六进制文件,英文全称为hexadecimal, BIN是二进制文件,英文全称为binary,这两种文件可以通过软件相互转换,其实际内容都是一样的。
选中Debug information复选项将会产生调试信息,这些信息用于调试,如果需要对程序进行调试,应当选中该项。
Browse information复选项可以产生浏览信息,该信息可以用菜单命令View→Browse来查看,这里取默认值。
Select Folder for objects按钮是用来选择最终的目标文件所在的文件夹,默认与工程文件在同一个文件夹中。
Name of Executable文本框用于指定最终生成的目标文件的名字,默认与工程的名字相同,这两项一般不需要更改。
工程设置对话框中的其他各页面与C51编译选项、A51的汇编选项、BL51连接器的连接选项等用法有关,这里均取默认值,不作任何更改。
3.Listing选项卡
Listing选项卡用于调整生成的列表文件选项。在汇编或编译完成后将产生(∗. lst)的列表文件,在连接完成后也将产生(∗. m51)的列表文件,该页用于对列表文件的内容和形式进行细致的调节,其中比较常用的选项是C Compile Listing选项组中的Assamble Code项,选中该项可以在列表文件中生成C语言源程序所对应的汇编代码,如图3-10所示。
4.C51选项卡
C51选项卡用于对Keil的C51编译器的编译过程进行控制。Code Optimization选项组中Level是优化等级,C51在对源程序进行编译时,可以对代码优化至9级,默认使用第8级,如图3-11所示。一般不必修改,如果在编译中出现一些问题,可以尝试降低优化级别。
图3-10 Listing选项卡
图3-11 C51 选项卡
Emphasis下拉列表框可以选择编译优先方式,其中有三个选项,第一项,代码量优化(最终生成的代码量小);第二项,速度优先(最终生成的代码速度快);第三项,默认值。默认的是速度优先,可根据需要更改。
设置完成后按确认按钮返回主界面,则工程文件建立、设置完毕。
3.1.3 工程编译、连接
在设置好工程后,即可进行工程的编译、连接。
Project/Build target:先对该文件进行编译,然后再连接以产生目标代码;
Rebuild All target files:对当前工程中的所有文件重新进行编译然后再连接,确保最终生成的目标代码是最新的。
Translate:仅对该文件进行编译,不进行连接。
以上操作也可以通过工具栏按钮直接进行。图3-12是有关编译、设置的工具栏按钮,从左到右分别是:编译、编译连接、全部重建、停止编译和对工程进行设置。
图3-12 有关编译、设置的工具栏按钮
图中前三个都是编译按钮,不同是第1个按钮对应Translate,用于编译正在操作的文件。第2个按钮对应Build target,是编译修改过的文件,并生成应用程序供单片机直接下载。第3个按钮对应Rebuild All target files,是重新编译当前工程中的所有文件,并生成应用程序,供单片机直接下载。因为很多工程不止一个文件,当有多个文件时,可使用此按钮进行编译。在第3个右边的按钮是全部重建和停止编译按钮,只有单击了前三个中的任意一个,停止按钮才会生效。
选择图标或执行命令Debug→Start→Stop Debug Sessio或〈Ctrl+F5〉,开始进行软件调试。调试窗口如图3-13所示。常用调试工具条,如图3-14所示。
图3-13 调试窗口
图3-14 调试工具条
编译过程中的信息将出现在输出窗口中的Build Output窗口中,如果源程序中有语法错误,会有错误报告出现,双击该行,可以定位到出错的位置,对源程序反复修改之后,最终会提示获得了名为Text1.hex的文件,该文件即可被编程器读入并写到芯片中,同时还产生了一些其他相关的文件,可被用于Keil的仿真与调试,这时可以进入下一步调试的工作。
在图3-15中可以看到编译的错误信息和使用的系统资源情况等,以后要查错就靠它了。
图3-15 编译后的界面
其中Build Output中内容的含义是:
创建目标“Target 1”
编译文件流水灯.c…
链接…
程序大小:内部数据段=12.0 外部数据段=0 代码段=85
创建工程1的HEX文件…
工程1编译结果-0个错误,0个警告。
以上过程表示此工程成功通过编译。
注意在执行编译之前,要先保存文件,因为进行编译时,有时会导致计算机死机,使用户不得不重启计算机,若用户在编写一个很大的工程文件时,如没有及时保存,那么重启后,用户将找不到它的任何踪影,只得重写。虽然这种情况极少发生,但出于安全考虑,建议及时保存。
3.1.4 调试方法
一般来说,除了极少数简单的程序以外,绝大部分的程序都需要反复进行调试,几乎没有一次就能够编译正确的代码,使程序正确地执行的。真正可实现的代码都需要通过编译、烧写、调试的环节的,因此调试是单片机开发的重要环节,直接影响到产品的稳定性和开发周期。调试包括软件仿真、在线硬件仿真、串口打印三大手段。
软件仿真:很多编译器都包含调试环境,而调试环境都集成了单片机内核,像Keil开发环境集成了8051系列单片机内核、AVRStudio集成了AVR单片机内核。就以Keil软件仿真为例,当其在线软件仿真8051系列单片机时,不但能够将8051系列单片机的所有寄存器的信息都能够实时显示出来,而且能够观察到变量的变化、程序的跳转、内存信息甚至更多。
在线硬件仿真:在国内51硬件仿真器比较著名的是伟福仿真器,但是价格昂贵。其他很多仿真器很难做到完全硬件仿真,往往会造成仿真时正常,而实际运行时出现错误的情况,更坏的情况就是仿真也不能通过,还有的仿真器属于简单的在线仿真型,例如速度不高、实时性或稳定性不好、对断点有限制等造成仿真起来不太方便。
串口打印:在单片机编程中,串口占了很重要的地位,传统的单片机调试都是通过串口打印信息的,连Linux的内核调试都是通过串口打印信息来实现的。串口打印是最基本的调试技巧,在软件编程中,在适当的位置调用打印信息函数UARTPrintfString来显示监视信息,当程序被执行时,用户就可以通过串口辅助软件来监视串口打印信息了。
一般的情况下,恰当地通过软件仿真和串口打印就可以得到正确稳定的代码,没有必要购买昂贵的硬件仿真器。
在Keil调试环境中已经内置了一个51内核用来模拟程序的执行,该仿真功能很强大,可以在没有硬件和硬件仿真器的情况下可以进行代码调试。有一点要注意,软件仿真和真实的硬件有所出入的是执行的时序,具体表现的是程序的执行速度,计算机性能越好,软件仿真运行程序速度就越快。要进行软件仿真调试程序,首先保证当前的程序能够正确地编译通过。当被正确地编译通过以后,选择菜单Debug→Start→StopDebugSession命令进入软件调试环境,显示界面会有明显的变化,并且多出寄存器监视窗口、内存监视窗口、变量监视窗口等,并弹出调试工具条,再次将它列出来,如图3-16所示。
图3-16 调试工具条
各主要快捷按钮的功能见表3-1。
表3-1 快捷按钮的功能
学会程序调试,必须要理清单步执行和全速执行的概念。单步执行顾名思义就是程序执行一步后,等待用户操作执行下一步。全速执行就是程序执行一步后不需要用户操作继续执行下一步,直到检测到断点为止。一般来说,单步执行易于观察变量值的变化、寄存器值的变化和内存的变化等,而全速执行就可以知道程序是否正确,并且很快知道程序错在哪一个位置。
下面介绍程序调试的具体操作步骤。
1.寄存器窗口
单击View菜单,打开寄存器监视窗口Registers window,用于监视寄存器R0~R7的变化,并提供监视SP堆栈指针、PC程序计数器指针、PSW程序状态字的变化。从之前介绍软件延时的章节可以通过监视“sec”来获得精准的定时,如图3-17所示。
2.观察窗口
单击快捷按钮,弹出观察窗口,它主要用于监视变量值的变化,如图3-18所示。
图3-17 寄存器监视窗口
图3-18 观察窗口
3.反汇编窗口
单击快捷按钮,弹出反汇编窗口,它主要显示的是C语言代码被编译过后的汇编代码,如图3-19所示。
图3-19 反汇编窗口
4.外围设备窗口
单击Periherals菜单,选择相应的选项将会弹出以下的窗口,如图3-20~图3-23所示。
图3-20 中断系统状态窗口
图3-21 I/O口状态窗口
图3-22 串行口状态窗口
图3-23 定时器状态窗口
由于Keil的软件仿真环境内建了51内核,能够显示单片机所有资源的状态,所以用户软件仿真时,一定要打开相关的外围设备窗口,这样就可以完全模拟真实的单片机各个周边设备是如何变化的。
5.串行口打印窗口
单击快捷按钮,弹出串行口打印窗口,这里只要串口函数能正常执行,打印信息时就可以通过该串行口打印窗口来显示,如图3-24所示。
图3-24 串行口打印窗口
6.性能分析器
单击快捷按钮,弹出性能分析窗口,如图3-25所示。
图3-25 性能分析窗口
从图3-25可以看出,Delay1和Delay2的柱形条显而易见,柱形条越长就表示该函数占用CPU的时间越长。
7.中断有效性检测
示例检测代码为定时器流水灯实验代码。
第一步:在Timer0IRQ函数体内加上断点。
第二步:编译程序并通过。
单击快捷按钮进入调试模式,并单击快捷按钮让程序全速执行,若中断有效,则程序会执行到Timer0IRQ中断服务函数体内部,如图3-26所示。
图3-26 程序执行到中断服务函数体内部
8.硬件调试方法
1)硬件电路如果有发光二极管的话,可以在代码中加入内容以点亮发光二极管,用于验证代码是否执行到此处。比如,调用某个函数时,是否调用成功,可以在进入函数的开头,加入内容以点亮发光二极管。
2)电路如果有数码管的话,可以在代码中加入内容使数码管显示0~9,用于验证某一变量的输出值是否和预期的一样。
3)添加断点:如果用汇编语言的话,可以在程序中加入SJMP$,程序运行至此处就停止了,用于验证某一段代码是否和预期的一样。