keil μVision4教程 下载本文

设置好断点后可以全速运行程序,一旦执行到该程序行即停止,可在此观察有关变量值,以确定问题所在。在程序行设置/移除断点的方法是将光标定位于需要设置断点的程序行,使用菜单Debug->Insert/Remove BreakPoint 设置或移除断点(也可以用鼠标在该行双击实现同样的功能);Debug->Enable/Disable Breakpoint 是开启或暂停光标所在行的断点功能;Debug->Disable All Breakpoint 暂停所有断点;Debug->Kill All BreakPoint 清除所有的断点设置。这些功能也可以用工具条上的快捷按钮进行设置。

除了在某程序行设置断点这一基本方法以外,Keil 软件还提供了多种设置断点的方法,按Debug->Breakpoints? 即出现一个对话框,该对话框用于对断点进行详细的设置,如图3.3.1所示。

图3.3.1 断点设置对话框

图3.3.1中Expression 后的编缉框内用于输入表达式,该表达式用于确定程序停止运行的条件,这里表达式的定义功能非常强大,涉及到Keil 内置的一套调试语法,这里不作详细说明,仅举若干实例,希望读者可以举一反三。

1) 在 Experssion 中键入a==0xf7,再点击Define 即定义了一个断点, 注意,a 后有两

个等号,意即相等。该表达式的含义是:如果a 的值到达0xf7 则停止程序运行。除使用相等符号之外,还可以使用>,>=,<,<=,!=(不等于),&(两值按位与),&&(两 值相与)等运算符号。

2) 在 Experssion 后中键入Delay 再点击Define,其含义是如果执行标号为Delay 的行则

中断。

3) 在 Experssion 后中键入Delay,按Count后的微调按钮,将值调到3,其意义是当第三次

执行到Delay 时才停止程序运行。

28

4) 在 Experssion 后键入Delay , 在Command 后键入printf(“SubRoutine ‘Delay’ has

been Called\\n”)主程序每次调用Delay 程序时并不停止运行,但会在输出窗口Command 页输出一行字符,即SubRoutine ‘Delay’ has been Called。其中“\\n”的用途是回车换行,使窗口输出的字符整齐。

5) 设置断点前先在输出窗口的 Command页中键入DEFINE int I,然后在断点设置时同4),

但是Command 后键入printf(“SubRoutine ‘Delay’ has been

Called %dtimes\\n”,++I),则主程序每次调用Delay 时将会在Command 窗口输出该字符及被调用的次数,如SubRoutine ‘Delay’ has been Called 10 times。

对于使用 C 源程序语言的调试,表达式中可以直接使用变量名,但必须要注意,设置时只能使用全局变量名和调试箭头所指模块中的局部变量名。

第四节 实例调试

为进行程序的调试,我们首先给源程序制造一个错误,将延时子程序的第三行“DJNZR6,$”后的$改为D1,然后重新编译,由于程序中并无语法错误,所以编译时不会有任何出错提示,但由于转移目的地出错,所以子程序将陷入无限循环中。

进入调试状态后,按 F10 以过程单步的形式执行程序,当执行到LCALL DELAY 行时,程序不能继续往下执行,同时发现调试工具条上的Halt 按钮变成了红色,说明程序在此不断地执行着,而我们预期这一行程序执行完后将停止,这个结果与预期不同,可以看出所调用的子程序出了差错。为查明出错原因,按Halt 按钮使程序停止执行,然后按RST 按钮使程序复位,再次按下F10 单步执行,但在执行到LCALL DELAY 行时,改按F11 键跟踪到子程序内部(如果按下F11 键没有反应,请在源程序窗口中用鼠标点一下),单步执行程序,可以发现在执行到“DJNZ R6,D1”行时,程序不断地从这一行转移到上一行,同时观察左侧的寄存器的值,会发现R6 的值始终在FFH 和FEH 之间变化,不会减小,而我们的预期是R6 的值不断减小,减到0 后往下执行,因此这个结果与预期不符,通过这样的观察,不难发现问题是因为标号写错而产生的,发现问题即可以修改,为了验证即将进行的修改是否正确,可以先使用在线汇编功能测试一下。把光标定位于程序行“DJNZ R6,D1”,打开在线汇编的对话框,将程序改为“DJNZ R7,0EH”,即转回本条指令所在行继续执行,其中0EH 是本条指令在程序存储器中的位置,这个值可以通过在线汇编窗口看到,如图3 所示。然后关闭窗口,再进行调试,发现程序能够正确地执行了,这说明修改是正确的。注意,这时候的源程序并没有修改,此时应该退出调试程序,将源程序更改过来,并重新编译连接,以获得正确的目标代码。

29

第四章 Keil 程序调试窗口

上一章中我们学习了几种常用的程序调试方法,这一讲中将介绍 Keil 提供各种窗口如输出窗口、观察窗口、存储器窗口、反汇编窗口、串行窗口等的用途,以及这些窗口的使用方法,并通过实例介绍这些窗口在调试中的使用。

第一节 程序调试时的常用窗口

Keil 软件在调试程序时提供了多个窗口,主要包括输出窗口(Output Windows)、观察窗口(Watch&Call Statck Windows)、存储器窗口(Memory Window)、反汇编窗口(DissamblyWindow)串行窗口(Serial Window)等。进入调试模式后,可以通过菜单View 下的相应命令打开或关闭这些窗口。

图4.1.1是输出窗口、观察窗口和存储器窗口,各窗口的大小可以使用鼠标调整。进入调试程序后,输出窗口自动切换到Command 页。该页用于输入调试命令和输出调试信息。对于初学者,可以暂不学习调试命令的使用方法。

图4.1.1 调试窗口(命令窗口、存储器窗口、观察窗口)

一、存储器窗口

存储器窗口中可以显示系统中各种内存中的值,通过在Address 后的编缉框内输入“字母:数字”即可显示相应内存值,其中字母可以是C、D、I、X,分别代表代码存储空间、直接寻址的片内存储空间、间接寻址的片内存储空间、扩展的外部RAM 空间,数字代表想要查看的地址。例如输入D:0 即可观察到地址0 开始的片内RAM 单元值、键入C:0 即可显示从0 开始的ROM 单元中的值,即查看程序的二进制代码。该窗口的显示值可以以各种形式显示,如十进制、十六进制、字符型等,改变显示方式的方法是点鼠标右键,在弹出的快捷菜单中选择,该菜单用分隔条分成三部份,其中第一部份与第二部份的三个选项为同一级别,选中第一部份的任一选项,内容将以整数形式显示,而选中第二部份的Ascii 项则将以字符型式显示,选中Float 项将相邻四字节组成的浮点数形式显示、选中Double 项则将相邻8 字节组成双精度形式显示,如图图4.1.2所示。

30

图4.1.2 存储器数值各种方式显示选择

第一部份又有多个选择项,其中Decimal 项是一个开关,如果选中该项,则窗口中的值将以十进制的形式显示,否则按默认的十六进制方式显示。Unsigned 和Signed 后分别有三个选项:Char、Int、Long,分别代表以单字节方式显示、将相邻双字节组成整型数方式显示、将相邻四字节组成长整型方式显示,而Unsigned 和Signed 则分别代表无符号形式和有符号形式,究竟从哪一个单元开始的相邻单元则与你的设置有关,以整型为例,如果你输入的是I:0,那么00H 和01H 单元的内容将会组成一个整型数,而如果你输入的是I:1,01H和02H 单元的内容全组成一个整型数,以此类推。有关数据格式与C 语言规定相同,请参考C 语言书籍,默认以无符号单字节方式显示。第三部份的Modify Memory at X:xx 用于更改鼠标处的内存单元值,选中该项即出现如图4.1.3所示的对话框,可以在对话框内输入要修改的内容。

图4.1.3 存储器的值的修改

二、工程窗口寄存器页

图4.1.4是工程窗口寄存器页的内容,寄存器页包括了当前的工作寄存器组和系统寄存器,系统寄存器组有一些是实际存在的寄存器如A、B、DPTR、SP、PSW 等,有一些是实际中并不存在或虽然存在却不能对其操作的如PC、Status 等。每当程序中执行到对某寄存器的操作时,该寄存器会以反色(蓝底白字)显示,用鼠标单击然后按下F2 键,即可修改该值。

31