三、调试命令
事实上,除了极简单的程序以外,绝大部分的程序都要通过反复调试才能得到正确的结果,因此,调试是软件开发中重要的一个环节。
1.常用调试命令
在对工程成功地进行汇编、连接以后,按“Ctrl+F5”或者使用菜单“Debug->Start/Stop Debug Session”即可进入调试状态,工具栏会多出一个用于运行和调试的工具条,如图8-8所示。Debug菜单上的大部分命令可以在此找到对应的快捷按钮,从左到右依次是复位、运行、停止、单步、过程单步、执行完当前子程序、运行到当前行、下一状态、打开跟踪、观察跟踪、反汇编窗口、观察窗口、代码作用范围分析、1#串行窗口、内存窗口、性能分析窗口、工具按钮等命令。
图8-8 调试工具栏
学习程序调试,必须明确两个重要的概念,即单步执行与全速运行。
全速执行是指一行程序执行完以后紧接着执行下一行程序,中间不停止,这样程序执行的速度很快,并可以看到该段程序执行的总体效果,即最终结果正确还是错误,但如果程序有错,则难以确认错误出现在哪些程序行。
单步执行是每次执行一行程序,执行完该行程序以后即停止。通过单步执行程序,可以找出程序中存在的问题,但是有时效率偏低,为此必须辅之以其他的方法。通过菜单“Debug->Run to Cursor line”(执行到光标所在行)命令,用鼠标在某一子程序的最后一行点一下即可全速执行完黄色箭头与光标之间的程序行。在进入该子程序后,使用菜单“Debug->Step Out of Current Function”(单步执行到该函数外),使用该命令后,即全速执行完调试光标所在的子程序或子函数并指向主程序中的下一行程序。调试窗口如图8-9所示。
主调试窗口用于用户显示源程序,窗口左边的小箭头指向当前程序语句,每执行一条语句小箭头会自动向后移动,便于观察程序当前执行点。命令窗口用户键入各种调试命令。观察窗口用于显示局部变量和观察点的状态。
图8-9 调试窗口
此外,在主调试窗口还可显示寄存器窗口、存储器窗口、反汇编窗口、串行窗口及性能分析窗口等。通过单击View菜单中的相应选项(或单击工具条中的相应按钮),可以很方便地实现窗口的切换。有关调试窗口的详细描述请见本章第四节。
2.在线汇编
在进入μVision2的调试环境以后,如果发现程序有错,可以直接对源程序进行修改,但是要使修改后的代码起作用,必须先退出调试环境,重新进行编译、连接后再次进入调试,如果只是需要对某些程序行进行测试,或仅需对源程序进行临时的修改,这样的过程未免有些麻烦,为此μVision2软件提供了在线汇编的能力。
图8-10 在线汇编窗口
将光标定位于需要修改的程序行上,用菜单“Debug->Inline Assambly…”即可出现如图8-10所示的对话框,其中,“Current Instruction”栏显示的是指定行当前的汇编指令,“Current Assembly”栏显示当前指定行地址,在“Enter New”后面的编辑框内直接输入新的汇编指令(如LJMP LCD1602),输入完后键入回车,新键入的指令将取代指定行上原有的指令,实现“在线汇编”功能。如果不再需要修改,可以点击右上角的关闭按钮关闭窗口。
3.断点设置
程序调试时,一些程序行必须满足一定的条件才能被执行(如程序中某变量达到一定的值、按键被按下、串口接收到数据、有中断产生等),这些条件往往是异步发生或难以预先设定的,这类问题使用单步执行的方法很难调试,一般通过设置断点解决该问题。断点设置的方法有多种,常用的是在某一程序行设置断点,设置好断点后可以全速运行程序,一旦执行到该程序行即停止,可在此观察有关变量值,以确定问题所在。
在程序行设置/移除断点的方法是将光标定位于需要设置断点的程序行,使用菜单“Debug->Insert/Remove Breakpoint”设置或移除断点,也可以用鼠标双击该行实现同样的功能;“Debug->Enable/Disable Breakpoint”是开启或暂停光标所在行的断点功能;“Debug->Disable All Breakpoint”暂停所有断点;“Debug->Kill All Breakpoint”清除所有的断点设置。这些功能也可以用工具条上的快捷按钮进行设置。除了在某程序行设置断点这一基本方法以外,μVision2软件还提供了多种设置断点的方法,按“Debug->Breakpoints…”即出现一个对话框,该对话框用于对断点进行详细的设置,如图8-11所示。
图8-11 断点设置对话框
图8-11中Expression后的编辑框内用于输入表达式,该表达式用于确定程序停止运行的条件,例如:
(1)在Expression中键入a==0x50,再点击Define即定义了一个断点,该表达式的含义是:如果a的值等于0x50则停止程序运行。
(2)在Expression后中键入Delay再点击Define,其含义是如果执行标号为Delay的行则中断。
(3)在Expression后中键入Delay,按Count后的微调按钮,例如将值调到3,其意义是当第3次执行到Delay时才停止程序运行。
(4)在Expression后键入Delay,在Command后键入printf(“Sub Routin‘Delay’has been Called\n”)主程序每次调用Delay程序时并不停止运行,但会在输出窗口Command页输出一行字符,即“Sub Routine‘Delay’has been Called”。其中“\n”是回车换行,使窗口输出的字符整齐。
(5)设置断点前先在输出窗口的Command窗口断点设置对话框页中键入DEFINE intI,然后在断点设置时同4),但是Command后键入printf(“SubRoutine‘Delay’has been Called%dtimes\n”,++I),则主程序每次调用Delay时将会在Command窗口输出该字符及被调用的次数,如“SubRoutine‘Delay’has been Called 10 times”则表示子程序“Delay”已是第十次调用。
对于调试使用C语言的源程序,表达式中可以直接使用变量名,但必须要注意,设置时只能使用全局变量名和调试箭头所指模块中的局部变量名。