一、软件调试使用1.1 基本调试操作 上文已经说过在线调试和模拟调试的配置过程,但无论是在线还是模拟调试,调试技巧工具的使用都是一样的。
点击红色d,进入调试
可以发现,多出了一个工具条,这就是 Debug 工具条,这个工具条在我们仿真的时候是非
常有用的,下面简单介绍一下 Debug 工具条相关按钮的功能。Debug 工具条部分按钮的功能如
图:
复位(Reset):其功能等同于硬件上按复位按钮。相当于实现了一次硬复位。按下该按钮之后,代码会重新从头开始执行。
执行到断点处(Run):该按钮用来快速执行到断点处,有时候你并不需要观看每步是怎么执行的,而是想快速的执行到程序的某个地方看结果,这个按钮就可以实现这样的功能,前提是你在查
看的地方设置了断点。
挂起(Stop):此按钮在程序一直执行的时候会变为有效,通过按该按钮,就可以使程序停止下来,进入到单步调试状态。
单步调试(Step):根据当前调试的窗口的语言,执行单条语句。如果遇到函数,则会进入函数内部。该按钮用来实现执行到某个函数里面去的功能,在没有函数的情况下,是等同于执行过去按钮的。
单步跳过调试(Step Over):如果是在C语言窗口中,则是按单条语句执行,与单步调试不同的是,遇到函数不会进入函数内部,而是直接全速运行函数,并跳到下一条语句。在碰到有函数的地方,通过该按钮就可以单步执行过这个函数,而不进入这个函数单步执行。
单步返回调试(Step Out):如果是在C语言窗口中,则是直接全速运行当前函数后面所有内容,直到函数返回上一级。该按钮是在进入了函数单步调试的时候,有时候你可能不必再执行该函数的剩余部分了,通过该按钮就直接一步执行完函数余下的部分,并跳出函数,回到函数被调用的置。
执行到光标处(Step Run to Cursor Line):该按钮可以迅速的使程序运行到光标处,其实是挺像执行到断点处按钮功能,但是两者是有区别的,断点可以有多个,但是光标所在处只有一个。
插入/移除断点:如果当前光标所在行未有断点,则插入断点(前提是当前行可以插入,如果无法插入会显示一个感叹号),在有断点的情况下则是移除断点。插入断点后,当前行前面会有个红圆表示断点位置。也可以通过直接点击红圆位置进行插入/移除断点的操作。另一种断点方式,是通过指令来控制,当然也可以使用Keil提供的界面化操作,设置某个变量读或写时触发断点。不过目前貌似有部分芯片不支持这种操作。注:断点最多只能打7个。
使能/禁止断点:开启或禁止当前光标所在行的断点。禁止后红圆变成白圆。
禁止所有断点:禁止当前所有的断点。
删除所有断点:删除所有断点。
1.2 调试窗口
汇编窗口:通过该按钮,就可以查看汇编代码,这对分析程序很有用。
观看变量/堆栈局部变量窗口:该按钮按下,会弹出一个显示变量的窗口,在里面可以查看各种你想要看的变量值,也是很常用的一个调试窗口。
观察窗口:watch窗口,可以看到你想看的变量。
内存查看窗口:该按钮按下,会弹出一个内存查看窗口,可以在里面输入你要查看的内存
地址,然后观察这一片内存的变化情况。是很常用的一个调试窗口。
串口打印窗口:该按钮按下,会弹出一个类似串口调试助手界面的窗口,用来显示从串口
打印出来的内容。
逻辑分析窗口:按下该按钮会弹出一个逻辑分析窗口,通过 SETUP 按钮新建一些 IO 口,
就可以观察这些 IO 口的电平变化情况,以多种形式显示出来,比较直观。
系统查看窗口:这个窗口用于查看当前单片机外设及内核寄存器的值,在调试外设底层时经常会使用到。
通过"View->Watch Windows->Watch1、Watch2"可以选择打开Watch窗口,也可以在工具栏
这里打开。再点击一次则可以关闭。
通过选中一个变量(一定要选中变量,而不是光变放在变量那里),右键添加入对应的Watch窗口,可以追踪查看当前变量的变化状态。注意,只有全局变量可以全程监视,临时变量只有在进入当前函数中才可监视到其数据,用static关键词修饰的变量无法监视。
如果当前变量没有实时更新,则需要点击"View->Periodic Window Update"将其勾选上。
在 "Watch" 窗口中,可以查看当前变量名称、值、数据类型,如果当前变量类型为结构体,则可以以对应的结构形式进行展开查看。
通过"View->Memory Windows->Memory1/2/3/4"打开Memory窗口,也可以通过工具栏这个图标打开。打开的状态下再按一次则可关闭。
在Memory窗口中输入想要查看内存的起始地址里的数据,另外右上角的锁可以把当前界面锁定下来。
另外如果查看的是Ram的地址,那其中的数据也可以直接通过此窗口进行修改。
- 系统视窗——System Viewer Windows(这个根据不同芯片会有不同的展示)
可以在"Peripherals"选项栏中选择"System Viewer"系统视窗中对应的外设,选择"Core Peripherals"则是内核调试窗口。另外系统视窗也可以通过工具栏中,这个位置打开。
这个窗口用于查看当前单片机外设及内核寄存器的值,在调试外设底层时经常会使用到。
在这个窗口中可以直接修改外设寄存器的值,当然部分只读寄存器是无法修改的,有些则是需要在特定条件下才可以设置生效,具体就得看对应的芯片手册里寄存器的说明了。
但我的Keil软件中无法显示这个视图,并且通过修改系统试图,调试时,点击打开系统视图发生了闪退的现象,目前能想到的原因是:重新安装Keil,安装最新版本。
若Keil软件的System Viewer中没有,可以在这里点击 Use Custom File,添加SRF后缀的文件,这个文件在芯片包里。添加后,确实有了系统视图,但会出现闪退的现象。
- 调度关系窗口——Call Stack Window
- 寄存器窗口——Register Window
- 反汇编调试窗口——Disassembly Window
- 命令窗口——Command Window
- 函数地址表——Symbols Window
- 跟踪窗口——Trace Windows
- 以上不常用的窗口介绍,详情:不常用调试窗口介绍
该窗口在"View->Serial Windows"中打开,也可以在工具栏这个位置打开。
该窗口在"View->Analysis Windows"中打开,也可以在工具栏这个位置打开。
二、注意事项1、有时候在watch窗口中,变量值不会刷新,这时候就需要查看一下"View->Periodic Window Update"是否已勾选,如果没勾选,变量只有在第一次添加或停止调试时才会刷新。另外当窗口里一次性加载了一个很大的数组,当展开数组时,变量刷新也会变得很慢,并且软件会变卡顿。
2、当选择了非0级优化时,调试可能会变得困难,具体表现在断点调试。比如现在下面的代码,代码优化的关系,有可能把case0、1、2里的return 1都合并成一行,导致运行调试时,无论当前程序进入了哪个分支,使用断点时都只会进其中一个。所以当开启代码优化等级后,需要注意断点调试将变得不可信。另外优化编译后,有部分代码也将无法打断点(被优化的代码)。
switch (xx){ case 0: { do_something0(); return 1; } case 1: { do_something1(); return 1; } case 2: { do_something2(); return 1; } default: { return 0; }}此时应该去看汇编的实现,其执行顺序与汇编一致。
3、目前发现有部分工程在一些电脑上调试时,打断点后在删除断点之前退出调试,会导致Keil崩溃,只能结束进程重启,可能是你的工程中有中文名字。
4、当开启内部看门狗并且未打开调试关看门狗功能时,停止运行一段时间后会复位。
5、在全速运行时,有时打断点会无效,取消断点也无效,貌似是Keil本身的问题。
|