当今的嵌入式体系开发领域中,高效的调试东西关于工程师来说至关重要。它们能够极大地减少开发周期中的过错追踪时刻,并加速产品的上市时刻。MDK作为业界领先的嵌入式开发东西之一,其内置的调试功用被广大开发者所赞誉。这些功用不只供给了对代码履行的深化洞悉,还允许开发者在实时环境中监控和修正体系行为。经过本文,咱们将一起探索 MDK 的调试功用怎么成为嵌入式开发者的得力助手,以及它怎么助力咱们构建愈加安稳、高效的嵌入式应用。

1. 源码下载及前置阅览

  • STM32F103C8T6模板工程

链接:pan.baidu.com/s/1n7XHCaMY… 提取码:lw59

  • MDK5安装包

链接:pan.baidu.com/s/1j7USS7-r… 提取码:5q3s

  • 芯片固件包

链接:pan.baidu.com/s/1Td21MOEs… 提取码:86uh

假如你是个零根底的小白,连 STM32 都没见过,我也给你预备了一个保姆级教程,手把手教你搭建好 STM32 开发环境,并教你怎么下载程序,简直业界良心!

零根底快速上手STM32开发(手把手保姆级教程):www.lxlinux.net/e/stm32/stm…

假如你连代码都不知道怎么烧录到 STM32 的,能够参阅下文,供给了 5 种代码烧录方法:

STM32下载程序的五种方法:www.lxlinux.net/e/stm32/fiv…

新手小白假如连 MDK 的运用都不熟悉,那么能够经过下文先熟悉一下 MDK 的运用:

一文教你运用MDK开发东西:www.lxlinux.net/e/stm32/mdk…

2. MDK仿真调试装备

在 MDK 仿真前,咱们需求对其进行环境装备。

  • 翻开 Keil5 软件,翻开或许新建一个工程。

手把手教你运用MDK仿真调试

  • 点击 Options for Target,也就是咱们俗称的魔法棒。

手把手教你运用MDK仿真调试

  • 挑选 C/C++ 选项卡,在进行仿真时,咱们需求将 MDK 的优化调成 Level 0 等级。

手把手教你运用MDK仿真调试

  • 点击 Debug 选项卡,把「Load Application at Startup」和「Run to main」勾上,

手把手教你运用MDK仿真调试

手把手教你运用MDK仿真调试

Load Application at Startup 是在发动调试时是否加载应用程序,假如此选项去掉则不会主动将程序下载到单片机,直接调试。假如此选项打勾则每次进入调试前先下载应用程序,然后进入调试。

Run to main() 能够使程序履行到 main() 函数。进入调试形式后,程序主动运转到 main 函数处。

  • 翻开 Settings ,能够看到关于仿真器的设置,能够在这儿装备仿真器。默许情况下,大部分都是主动装备好的,无需额外修正。

手把手教你运用MDK仿真调试

  • 我这儿运用的是 ST-Link ,所以选的是 ST-Link 。假如你的 ST-Link 正常且插在电脑上了,右边 SW Device 会正常显现,表明仿真器与开发板衔接成功了。

    Debug Adapter 是你下载器的类型,这儿要挑选你运用的下载器类型。

    Serial 是指仿真器的序列号,当你挑选完仿真器之后,Serial 才会显现你下载器的序列号。

    在下面的 Version:FW 是下载器的版本号,本文运用的下载器是 ST-Link V2 所以显现的 HW 是 V2 。

    Port 是挑选仿真器的调试形式,ARM 芯片有两种调试形式,分别是 SW 和 JTAG 。

    相关于 JTAG 形式,SW 占用更少的信号线,而且功用相同支持代码下载与调试,所以强烈推荐运用 SW 调试形式。

手把手教你运用MDK仿真调试

假如 ST-Link 没有插上或设备异常,则会提示 No ST-Link detected。

手把手教你运用MDK仿真调试

  • 最终翻开 Utilities 选项卡将 Use Debug Driver 打勾,再点击 OK 确认一下,MDK 仿真的调试装备就完成了。

手把手教你运用MDK仿真调试

3. 各个调试按钮的效果

接着咱们编译一下代码。再点击这个像放大镜相同的按钮就能够开端仿真了(这个按钮一起也能够退出仿真)。

手把手教你运用MDK仿真调试

进入仿真之后的界面如下图示。

界面左面显现寄存器的地址和程序运转时刻,上方是汇编语言窗口,需求必定的汇编根底才干看得懂。界面左下方是指令窗口,这个窗口会显现一些打印信息,也能够在这个窗口输入一些指令。右下角的窗口是关于函数及变量在内存中的地址信息。

手把手教你运用MDK仿真调试

在左上方有一排关于调试的小按钮:

手把手教你运用MDK仿真调试

它们的功用从左到右分别是:复位、全速运转、中止、进入函数、履行过此函数、跳出函数、履行到光标处、显现下一个将运转的代码

  • 复位:从头履行程序;
  • 全速运转:开端履行程序;(快捷键为 F5 )
  • 中止:中止履行程序;
  • 进入函数:进入当时行代码中;(快捷键为 F11 )
  • 履行过此函数:履行当行代码;(快捷键为 F10 )
  • 跳出函数:跳出当时程序代码;(快捷键为 Ctrl+F11 )
  • 履行到光标处:主动履行代码至蓝色光标处;(快捷键为 Ctrl+F10 )
  • Show Next Statement:显现下一行即行将履行的程序。

这儿我以流水灯作为案例来具体的阐明一下各个按钮的运用方法,运用的单片机类型为 STM32F103C8T6 最小体系板。衔接 ST-Link 上电,接线图如下:

ST-Link V2 STM32
SWCLK SWCLK
SWDIO SWDIO
GND GND
3.3V 3V3

在 STM32F103C8T6 最小体系板上有个自带的小灯,这颗 LED 灯衔接在 PC13 管脚上。

首要咱们需求写一个小灯的初始化程序,这儿能够不用封装,直接写在 main.c 里边。

#define LED_CLK()       __HAL_RCC_GPIOC_CLK_ENABLE()
#define LED_GPIO        GPIOC
#define LED_PIN         GPIO_PIN_13
void led_init(void)
{
    GPIO_InitTypeDef gpio_initstruct;
    LED_CLK();                                              /* IO口时钟使能 */
    gpio_initstruct.Pin = LED_PIN;                          /* LED0引脚 */
    gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             /* 推挽输出 */
    gpio_initstruct.Pull = GPIO_PULLUP;                     /* 上拉 */
    gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           /* 高速 */
    HAL_GPIO_Init(LED_GPIO, &gpio_initstruct);              /* 初始化LED0引脚 */
}

主函数代码如下:

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    led_init();                         /* LED初始化 */
    while(1)
    { 
        HAL_GPIO_WritePin(LED_GPIO,LED_PIN,GPIO_PIN_SET);  /*使LED灭掉*/
        delay_ms(500);
        HAL_GPIO_WritePin(LED_GPIO,LED_PIN,GPIO_PIN_RESET);/*使LED亮起*/
        delay_ms(500); 
    }
}

点击放大镜进入仿真界面,然后再点击左上角的开端按钮(或许运用快捷键 F5 )开端履行代码。

手把手教你运用MDK仿真调试

能够看到 STM32F103C8T6 最小体系板上的 PC13 小灯在不断闪烁。这时分咱们在 19 行打上一个断点,再点击全速运转按钮:

手把手教你运用MDK仿真调试

能够看到当时程序运转到了第 19 行然后暂停了,STM32F103C8T6 最小体系板上的 PC13 小灯则会保持长亮。

(需求留意的是,调试停在中断处的时分,内核会中止,但是外设将会持续运转)

接着咱们在 21 行再打上一个断点,然后再点击全速运转按钮。

手把手教你运用MDK仿真调试

会发现代码履行到了 21 行就停下了,这时 STM32F103C8T6 最小体系板上的 PC13 小灯展灭掉。

咱们点击右上角复位的按钮,然后选中 led_init(); 这行代码,点击履行到光标处按钮(或许快捷键 Ctrl+F10 ),将代码履行至这一行。

(需求留意必需求退出调试形式再从头进入调试形式,否则代码会一直在死循环傍边履行,导致代码无法履行到你想要履行的那行)

手把手教你运用MDK仿真调试

这时分咱们点击进入函数按钮(或许快捷键 F11 ),则进入到 LED 的初始化函数傍边。

手把手教你运用MDK仿真调试

咱们能够看到当时程序履行到了 LED 的初始化函数中。这时,点击「履行过此函数按钮」(或许快捷键 F10 ),如下图示。

手把手教你运用MDK仿真调试

点击一下上图按钮,程序将履行一行代码。而且,假如当时行是函数,将不进入此函数内部代码,直接履行完函数代码并进入到下一行。

假如你不想检查 led_init() 函数里的代码了,你能够点击「跳出函数按钮」(或许快捷键 Ctrl+F11 ),能够按钮能够直接跳出当时代码程序,预备履行下一行。

(跳出函数的话会默许履行完当时程序代码,然后跳到下一行)

手把手教你运用MDK仿真调试

4. 检查程序段/函数履行的时刻

在代码中,咱们常常会运用延时函数。那么,咱们怎么确认延时函数真的延时了咱们所设置的时刻呢(比如 500ms)?

咱们能够经过代码调试功用来确认延时时刻的精确性。

首要翻开魔法棒,在 Debug 中翻开 Settings 选项。

手把手教你运用MDK仿真调试

再点击 Trace 选项卡,能够找到时钟频率。

手把手教你运用MDK仿真调试

默许情况下的时钟频率是 8MHz ,这儿咱们改成 72MHz 。

咱们选中 20 行,然后运用「履行到光标处按钮」(快捷键为 Ctrl+F10 )运转至 20 行。如下:

手把手教你运用MDK仿真调试

在左下方的 Sec 表明程序运转了多久,单位是秒( s ),咱们运用「履行过此函数」(快捷键为 F10 )履行一下延时函数,看看延时函数是否精确。结果如下:

手把手教你运用MDK仿真调试

运用此结果减去初始的时刻,能够看到大约延时了 0.5s 左右,也就是 500ms ,能够以为延时函数的时刻是十分精确的。

5. 东西栏常用窗口按钮介绍

在调试按钮的左面有一排窗口按钮,用于翻开各种调试窗口(也能够经过菜单栏的 View 翻开)。

  • 第一个 Command Window 按钮,能够翻开 Command 窗口,这个窗口能够显现一些打印的信息,还能输入指令。

手把手教你运用MDK仿真调试

  • 第二个按钮是 Disassembly Window ,这个窗口显现了汇编语言。你或许需求一些汇编语言的根底才干看得懂,这个窗口显现的光标表明下一条行将运转的汇编语言是什么。

手把手教你运用MDK仿真调试

  • 第三个按钮是 Symbols Window ,这是符号窗口,用于检查一些符号类型。本文暂时不对这个窗口进行深化学习。

手把手教你运用MDK仿真调试

  • 第四个按钮是 Registers Window ,这是一个寄存器窗口。这个窗口能够直观的检查一些内核的寄存器,还有程序运转时刻等等。

手把手教你运用MDK仿真调试

  • 第五个按钮是 Call Stack Window ,它是用于检查函数调用联系 & 局部变量。本文学习的是仿真东西一些根底的运用,所以不对这个窗口进行深化学习。

手把手教你运用MDK仿真调试

  • 第六个按钮是 Watch Windows ,用于检查函数首地址以及变量的值。

Watch 窗口还能够设置变量在被读或写后主动中止运转,关于代码调试十分有帮助。能够界说一个函数,将该函数的称号输入到窗口中,然后向函数传入一个数,在这个窗口你能够看到该函数的寄存器首地址,传完数之后你能够看到该数的类型是什么。

点击该按钮,弹出的界面如下:

手把手教你运用MDK仿真调试

举个栗子来演示一下这个过程。例如,在程序中界说一个全局变量 int temp; ,在 while 循环中履行 temp++ 。右击 temp ,挑选 Add “temp” to… 添加到 Wacth 1 。

手把手教你运用MDK仿真调试

在左下方的 Watch 1 窗口就能够看到 temp 的首地址和界说类型了。如下图:

手把手教你运用MDK仿真调试

这儿咱们运用「履行过此函数按钮」(快捷键为 F10 ),履行一遍程序,会发现 temp 的值发生了改动,履行了一次 temp++ 。如下图:

手把手教你运用MDK仿真调试

Wacth 窗口不止这些功用,Wacth 窗口还能够设置变量在被读或写后会主动中止运转。这个功用在调试行数比较多的项目十分有用,因为在许多场景下,有个变量有或许在几十上百处被修正,假如没有这个功用,排查变量被修正将变得十分困难。

那么怎么设置这个功用呢?

首要右击 temp ,会出现一个列表,点击 Set Access Breakpoint at “temp” 。如下图:

手把手教你运用MDK仿真调试

这时分会弹出一个窗口,在这个窗口你能够设置函数是否要在被读或许被写的主动中止运转。设置完之后点击 Define 就行了。

手把手教你运用MDK仿真调试

Wacth 窗口关于咱们代码调试还是有十分大的效果,咱们能够好好掌握。

  • 第七个按钮是 Memory Windows ,可用于检查内存的地址与值。界面如下图示:

手把手教你运用MDK仿真调试

同样的,咱们举一个比如。

首要咱们在程序中界说一个 uint8_t 类型的数值 temp[10] ,然后给数组的前五个数赋值 {1,2,3,4,15} ,其他元素默许值为 0 。在循环中咱们进行 temp[0]++ ,只对第一个元素自增。

编译一下,翻开仿真东西,再翻开Memory 窗口,在窗口中输入 temp ,这样咱们就能够看到 temp 数组在内存中的地址与值。前面咱们给数组赋值 {1,2,3,4,15} ,在 Memory 窗口能够看到 temp 数组被十六进制表明出来 “01 02 03 04 0F” 。如下图:

(留意,M3/M4/M7内核是小端形式,内存的值要倒着读)

手把手教你运用MDK仿真调试

Memory 窗口能够帮助咱们快速的检查变量在内存中的地址和值,便于咱们调试程序。

  • 第八个按钮是 Serial Windows ,这是用于检查串口的窗口。

手把手教你运用MDK仿真调试

  • 下面这个按钮是 Peripheral 窗口,于检查寄存器的值。Core Peripherals 是内核寄存器,其他的都是外设寄存器。如下图:

    手把手教你运用MDK仿真调试

    翻开之后是这个姿态的(我这儿翻开的是 GPIOC )。如下图:

    手把手教你运用MDK仿真调试

    在这儿你能够看到一些寄存器的值,假如你想看某个值,你能够点击左面的 + 号,在 + 号中有更具体的信息。

    经过这个窗口,能够检查到自己装备寄存器是否正确,确保外设能依照你的预期运转。

6. 小结

总的来说,想要将单片机学的更好,MDK 仿真东西就必不可少。MDK 仿真东西不只功用强大,而且操作起来的难度也不高,对新手也十分的友好,最重要的是它能够帮助咱们更好地理解和调试程序代码,学好运用 MDK 仿真东西,能够让你的技术更上一层楼。


别的,想进大厂的同学,必定要好好学算法,这是面试必备的。这儿预备了一份 BAT 大佬总结的 LeetCode 刷题宝典,许多人靠它们进了大厂。

手把手教你运用MDK仿真调试

刷题 | LeetCode算法刷题神器,看完 BAT 随你挑!

有收成?期望老铁们来个三连击,给更多的人看到这篇文章

推荐阅览:

欢迎关注我的博客:良许嵌入式教程网,满满都是干货!