
目录
1. 检查配置
1.1 硬件仿真配置
在开始使用仿真调试之前,先看下一下配置,按照如下步骤,找到魔术棒图标(①)点击,弹出界面后找到“debug”(②),而后找到自己所使用的下载器,这里我使用的是ST-Link,因此选择了“ST-Link Debugger”(③),然后找到“Settings”(④):

将①的位置配置为“SW”,作用是使用 SWD(Serial Wire Debug) 协议进行调试和烧录。②的位置代表芯片链接上了:

二者的对比,不过我们正产正常使用的ST-Link的是两线制的,所以选择SW即可:
| 对比项 | SWD | JTAG |
|---|---|---|
| 引脚数量 | 2 线(SWDIO + SWCLK) | 5 线(TMS, TCK, TDI, TDO, nTRST) |
| 速度 | 与 JTAG 相当(通常 1~4 MHz) | 与 SWD 相当 |
| 占用资源 | 更少引脚,适合小型封装芯片 | 需要更多引脚 |
| 兼容性 | 仅支持 ARM Cortex-M 内核 | 支持更广泛的芯片(如 ARM9) |
| 常用场景 | STM32 等 Cortex-M 芯片的主流选择 | 复杂调试(如多核芯片) |
找了一张相关引脚的图片:

图中框住部分代表Core Clock(内核时钟) 的配置,根据芯片规格、外设需求和实际应用场景来选择,这边就只是验证一下debug的使用,就默认了:

其他就是芯片的一些下载配置:

1.2 软件仿真配置
软硬件任选其一,首先点击魔术棒,找到Target,将频率改为8Mhz:

然后找到debug,主要关注黑框部分,绿线部分可勾选可不勾:

首先对于USB Simulator(USB 模拟器) 是一个用于 调试和仿真 USB 设备功能 的工具,它允许开发者在没有实际硬件的情况下测试 USB 协议栈、USB 设备类(如 HID、CDC、MSC 等)以及与主机(PC)的通信行为。相当于我们此时没有硬件设备,靠软件先模拟仿真一下,
Limit Speed to Real-Time(限制速度为实时)是一个与 调试器执行速度控制 相关的选项,主要用于在调试过程中保持代码执行与实际硬件运行的一致性。
Dialog DLL 是指 调试器(Debugger)配置中的动态链接库(DLL),用于支持特定的调试接口或硬件仿真器。而系统自带的 DCM.DLL,是 Keil 提供的一个 调试通信中间层,用于优化调试器(如 J-Link、ULINK、ST-Link 等)与目标设备(MCU)之间的数据传输,可以适配不同的调试接口(如 JTAG、SWD、cJTAG),并自动选择合适的通信方式,不过这个毕竟是通用的,我们这里使用纯原生的,我们使用ST-Link,这里使用 DARMSTM.DLL ,当时如果使用J-Link可以使用JLinkARM.dll 根据自己回头使用下载器进行选配。
Parameter(参数) 是 Dialog DLL 的附加选项,用于传递特定的调试或烧录参数给底层调试器(如 ST-Link、J-Link 等)。它的具体含义取决于所使用的 调试器类型 和 目标芯片。同样的,我们在下载完编译器,选配好芯片后,由于我们使用的是STM32F1系列单片机,是ARM3内核的,其给我们默认的是 -pCM3 ,它也是通用的,它仅声明内核,不提供芯片的 Flash 大小、外设信息等细节。因此我们想要具体使用哪款新品,就声明具体型号(-pSTM32Fxxx),这里使用的是STM32F103C8T6,因此声明-pSTM32F103C8。
2. 调试界面
首先找到“Start/Stop Debug Sestion”,也就是如下图标,起作用是开启和关闭仿真调试:

点击后,进入仿真调试界面:

2.1 界面介绍
对于①②③,由于里面的条数比较多,下面进行详细介绍:

④ 寄存器窗口:显示当前CPU寄存器的值,这些寄存器包含了执行状态、指针、地址和一些重要的硬件信息。
⑤ 汇编程序窗口:与⑥中源码相对应,代码左侧灰色部分代码已编译部分,可设置断点(此部分可以查看代码是否编译或者是否被编辑器优化)。
⑥ 代码窗口:源代码显示。
⑦ Command窗口:调试命令行,可通过设置命令执行所有调试操作,如断点设置、变量寄存器访问、数据转换、基本计算等功能。通常也显示编译器或调试器的输出信息,比如错误消息、警告和打印输出。
⑧ 调用站和局部变量窗口:从左到右分别表示函数的类型名、函数的首地址、函数的返回类型。

2.2 运行调试
我们来看看①所框住的都是什么功能:

复位:相当于硬件上的复位按钮或者电源重启。
执行到断点处:或者说是开始或继续执行程序按钮。如果程序已经停在一个断点上,点击这个按钮将继续执行程序直到遇到下一个断点或程序结束。也就是说如果没有断点,程序会一直运行。
举个例子,假如我们打了两个断点(断点的概念下面说),让你全速运行到第一个断点,他就会停下(两个小箭头,蓝色代表当前鼠标光标所在行,黄色当前运行行):

此时在点击运行,就会到第二个断点停下:

停止执行:中止当前正在运行的程序。
执行进去:执行下一行代码,如果是调用函数就进入到该函数内部。
这句话什么意思呢,假如我们现在执行到如图位置:

此时在点击一下会发现,我们来到了延时函数内部:

执行过去:执行下一行代码,但是不进入函数内部。如果当前行调用了函数,IDE将执行整个函数,然后停在下一行。也就是说,如果在主函数中使用这个功能,会一直停留在主函数页面运行每一行代码,不会调转到其他函数中去。
还是距上面这个例子:

此时我们点击直行过去,会发现函数来到下一行,没有在进入到延时函数内:

执行出去:当运行在函数内部时,这个按钮将执行完当前函数的剩余代码,并停在返回点之后的下一行。
假设我们此时运行到延时函数内部,我们想要将之后的代码运行完,只需要点击直行出去,就会将剩余代码执行完,跳出当前执行函数:


执行到光标处:程序执行将继续进行,直到到达当前代码编辑器中光标所在的行。
2.3 断点
先看看断点相关(也就是③),断点是调试过程中的一个关键部分,允许你停止程序的执行以检查变量的值或程序的行为:

其功能:

这直接按照字面意思理解即可,我们可以通过鼠标左键,在代码旁边灰色部分直接点击,生成断点:

2.4 窗口功能
比较常用的几个,不过下面也都全介绍了一遍:

命令行:打开Commod窗口,显示与调试会话相关的信息,包括用户输入的调试命令和由调试器返回的消息。它允许用户直接输入命令,例如管理断点、控制程序执行等。

反汇编窗口:用来开启如下图,示当前执行的汇编代码,与源代码视图同步,有助于理解C/C++代码是如何转换为处理器指令的,以及在调试时实际执行的指令。

符号窗口:列出了所有编译后的符号,包括函数、变量和类型定义。这个窗口让你可以确认是否有符号未定义或检查变量的地址和值。

内核寄存器:显示处理器内核的寄存器值。有助于理解程序的当前状态和执行流程,尤其是在硬件层面的调试中。

回调部变量:当调试时停留在断点时,这里会显示函数的调用关系,以及压进的变量值,可以在这里看到函数的调用关系和传递给函数的参数值。这个一般和断点配合,反推异常调用以及查看局部变量,无需使用变量查看串口。
变量显示:用于查看单片机中某个变量的值,一般多用于查看全局变量以及外设寄存器数值、表达式显示变量,也可直接操作变量值。

内存窗口:显示内存地址以及地址处内存的数据,一般可查看变量以及寄存器数据、函数地址等

虚拟串口窗口:如果程序使用了串口(例如USART),此窗口将显示由模拟器重定向的串口输出。

系统分析窗口:提供高级的代码性能分析功能,例如代码覆盖率、执行时间分析等。软件逻辑分析仪功能也包含在这里。

TRACE窗口:如果硬件支持,此功能允许实时跟踪指令执行,以及程序的行为和性能分析。
外设寄存器窗口:显示和控制单片机外设寄存器的状态,可以在这里查看和修改外设寄存器的值,如定时器、串口等的配置和状态。
3. 使用样例
3.1 串口打印窗口(逻辑分析仪)
前期准备完了,我们进入仿真界面,找到仿真界面,如果觉得界面太小,可以拖拽放大界面:

也可以直接拽出来,看自己喜好:

简单做个了解,对于放大和缩小格,也可以使用鼠标滑轮完成:

3.1.1 方法一:查看GPIO口
找到 Setup 按钮,点击出现如下界面:

找到方块,点击,输入PORT+当前引脚通道+GPIO位置,例如我们此时想要测,PA0引脚,就需要输入 PORTA.0,如下图:

输入完后点击黄色部分,其会自动保存如图格式,当然你自己打成如图样式也一样:

点击刚刚生成的部分,将全部部分改为Bit,完事点击Close:

点击全速运行,可以发现按照500ms拉高和拉低一下电平(横线代表每格数据0.5s):

3.1.2 方法二:查看参数
首先我们写一个简单的函数,记得编译运行一下,在进入仿真界面:
#include "stm32f10x.h" // Device header
#include "Delay.h"
char flag;
int main(void)
{
flag = 1;
while (1)
{
flag = 1;
Delay_ms(500);
flag = 0;
Delay_ms(500);
}
}
按照上面的方法,进行配置:

可以看到正常反应:

对于查看参数我们还有另一种方法,鼠标右键,找到图示位置,点击:

可以发现也能打开逻辑分析仪,然后右键图示位置,将数据调为bit:

点击也能正常运行:

3.2 观察窗口(数据读取)
还是先写一个简单的代码(记得运行一下再进入仿真):
#include "stm32f10x.h" // Device header
#include "Delay.h"
char sum[3] = {0,0,0};
int main(void)
{
while (1)
{
sum[0]++ ;
sum[1] += 2;
sum[2] += 3;
Delay_ms(1000);
}
}
找到图示位置:

点击<Enter expression>,输入我们想要查看的数据,例如sum:

点击前面的小加号,可以看到当前数组数据,由于之前运行工一下,因此此时显示1,2,3,此时数据是十六进制显示:

右键sum,将图示位置勾选去掉:

点击运行可以看到数据按照代码编写,进行累加:

如果当前变量没有实时更新,则需要点击下图位置,勾选上即可:

3.3 内存查看窗口(Memory)
查看当前数据所在内存空间的起始地址,我们将watch也打开对比一下看看:

在其中输入,想要查看的数据,会找到其所在地址:

我们也可以对所在地址的值进行修改,例如把sum[0]的数据改为0x33,双击要修改的地址的数据,直接修改即可:

当我们修改后,再次运行会发现,数据从我们修改的值开始累加了:

其他功能持续更新中······


905

被折叠的 条评论
为什么被折叠?



