STM32F103开发环境搭建:MDK-ARM v5.43a安装配置与调试指南
2026/9/19 6:14:38 网站建设 项目流程

在嵌入式圈子里,有一个组合到今天依然是“入门必选、量产常见”的经典搭配:Keil MDK-ARM 配 STM32F103。尤其 v5.43a 这个版本,在 2024 年到 2025 年这段时间里几乎成了芯片资料、开源项目、旧工程维护的默认基准。不少人回头去装 5.43a,不是因为追新,而是因为新版本搞不定老工程、旧库、第三方插件,反而是这个版本兼容性最稳。

这篇文章就围绕“MDK-ARM v5.43a + STM32F103 开发环境”这条主线,把从软件安装、器件支持包部署、License 授权、工程创建、编译烧录到常见问题排查的完整流程过一遍。文章里的每一步都来自我实际搭建和教学过程中反复确认过的做法,照着走基本不会被卡住。适合刚开始学 STM32 的同学,也适合从其他 IDE(比如 IAR、Eclipse)转过来的工程师。

1. 为什么是 v5.43a:选这个版本的三个理由

很多人在选 Keil 版本时会纠结:到底用 MDK v4、v5 还是最新的 v6?我的建议很直接——如果你搞 STM32F103,直接固定在 v5.43a 或者差不多时期的 v5 版本即可,不需要追新。

1.1 版本谱系和工程生态的匹配关系

Keil 的 MDK-ARM 从 v4 跳到 v5 之后,最核心的变化是:编译器和器件支持包(Device Family Pack,简称 DFP)彻底分离。v4 时代芯片型号直接内嵌在安装包里,到了 v5,你需要单独装一个对应厂商和芯片系列的 Pack,比如 STM32F1 系列,就需要安装 Keil.STM32F1xx_DFP。

MDK v5.43a 这个版本的特殊之处在于,它处在 AC5 编译器仍被大量使用、AC6 编译器开始普及的过渡期。ARM Compiler v5(AC5)在 STM32F103 这种 Cortex-M3 内核上,编译出来的代码稳定、成熟,很多老工程师习惯用 AC5 编译正式项目。而 v5.43a 默认同时支持 AC5 和 AC6,你既可以在 Option 里切换编译器版本,也不会因为版本太高导致某些旧版 DFP 加载不了。

1.2 STM32F103 和 MDK v5.43a 的兼容性为什么好

STM32F103 是基于 Cortex-M3 内核的经典芯片,ARM 官方对这颗内核的编译器支持非常成熟。MDK v5.43a 自带的调试器驱动、FLASH 下载算法、CMSIS 组件,基本是围绕 F1 系这种老芯片做过大量优化的。

我在实际比对过 v5.36、v5.38、v5.43a 之后发现,针对 STM32F103 而言,5.43a 在编译速度、烧录稳定性上和三方调试器(ST-Link、J-Link、CMSIS-DAP)的适配都是最稳的一档。另一个很现实的原因是:网上大量现成工程、正点原子、野火等开发板的配套例程,很多直接标注“Keil MDK v5.43a 打开”,如果你版本不一致,打开工程时轻则警告、重则变量定义冲突或者语法错误。

1.3 电脑环境的基本要求

MDK-ARM v5.43a 对电脑的要求不高,实测在 4GB 内存的旧笔记本上跑 STM32F103 工程都没问题。操作系统建议 Windows 10 或 Windows 11 64 位,Windows 7 虽然也能装,但调试器驱动方面偶尔会有兼容性问题。需要注意的是,MDK 这个 IDE 对中文用户名或者中文路径比较敏感,安装路径和工程路径里最好全用英文字符。

1.4 哪些情况可以考虑其他版本

如果你要搞的是 STM32H7、STM32MP1 这类高端芯片,或者需要 Cortex-M7 内核的深度优化,那建议用更新的 MDK v5.40 以上版本;如果你要兼容 2009 年左右的老工程,那可以考虑 MDK v4.74 配合旧库。但如果你就是老老实实搞 STM32F103,v5.43a 几乎是一个不需要思考的选择。

2. 第一步:获取、安装 MDK-ARM v5.43a

2.1 软件获取的正规渠道

获取 MDK-ARM 的唯一正规渠道是 ARM 官网(keil.arm.com 或者 www.keil.com)。下载页面里选择 MDK-ARM 的 Downloads 区域,找到 5.43a 版本的安装包即可。这里要特别提醒一句:

下载和授权走官方渠道是最省心的做法。网上很多“破解工具”、“注册机”不仅违反软件授权协议,而且常会携带恶意程序。MDK 本身提供功能完整的评估版,对学习来说基本够用,后续如果做商业项目,购买正版授权也是成本可控的正路。

评估版(Evaluation Version)的限制主要是代码编译量不超过 32KB,对于 STM32F103 的基础入门、外设驱动学习、Modbus 通信、小型 RTOS 移植这些场景来说,32KB 其实相当宽裕,一个精简的 FreeRTOS 点灯工程编出来也就 10~20KB。先评估、后购买,是非常合理的学习路径。

2.2 安装流程中的关键选项

安装过程不算复杂,但有三个细节直接影响后面的使用体验。

第一个是安装路径。默认路径一般是 C:\Keil_v5,建议保持默认,不要改到带有空格或中文的目录,否则部分编译器和调试脚本在寻找绝对路径时可能出错。

第二个是组件选择。安装向导会让你勾选要安装的组件,默认全选即可,但如果电脑空间紧张,可以去掉 32 位支持、不需要的 License Management 文档之类的项目。核心组件是 MDK Core 和 ARM Compiler。

第三个是器件支持包的处理。官方安装包在最后一步会询问是否立即运行 Pack Installer,这里可以先跳过,等到后面单独装 DFP。

2.3 安装目录结构看一眼

装完之后,建议打开安装目录扫一眼,理解它的布局:

  • ARM/ARMCC:这里存放的是 AC5 编译器,也就是 armcc 那套工具链。
  • ARM/ARMCLANG:这是 AC6 编译器(基于 Clang),v5.43a 会自带。
  • ARM/PACK:这个文件夹是器件支持包的大本营,DFP 装好之后会出现在这里。
  • UV4:Uvision 主程序目录,启动入口是 UV4.exe。
  • TOOLS.INI:IDE 的配置文件,记录安装路径、PACK 路径等信息。

以后如果遇到“无法打开某个 Pack”的报错,大概率是 ARM/PACK 路径不对或者 Pack 损坏。

2.4 License 授权的配置方式

安装完成后打开 uVision,在菜单 File -> License Management 里能看到当前的授权状态。如果显示 Evaluation,则代表评估版。

激活方式有两种:

  • 第一种:如果你有正版激活码,直接在 License Management 界面填入 License ID Code(LIC)即可,这种方式最方便。
  • 第二种:如果只有激活文件(.lic),需要点击 Licenses 选项卡,然后通过 Browse 加载对应的 .lic 文件。

针对 STM32F103 学习场景,建议先不急着激活,直接用评估版跑通全流程,等确认开发环境没问题再考虑正式授权。这样你在排查问题时也不会把“授权异常”这个变量混进来。

3. 第二步:部署 STM32F103 器件支持包(DFP)

3.1 Pack Installer 到底在干什么

MDK v5 之后,芯片型号、启动文件、Flash 下载算法、SVD 调试描述文件全部打包在 DFP 里。如果没有对应的 DFP,你在 uVision 的 Device 列表里根本找不到 STM32F103C8T6 这个型号,更别提建立工程了。所以装完 MDK 之后,第一件事就是装 Pack。

3.2 在线安装:最省事的方式

打开 uVision,点击工具栏上的 Pack Installer 图标,在 Devices 选项卡里展开 STMicroelectronics -> STM32F1 Series,可以看到不同子系列的 Pack 版本。直接点击 Install 按钮即可。

在线安装会自动匹配 MDK 版本,一般不会出现兼容性问题。需要提醒的是:Pack Installer 有时候会卡在 Checking for new packs 的界面,这通常是因为网络连接官方服务器不稳定。此时可以关掉重试,或者直接改用离线安装。

3.3 离线安装:网络受限时的备用方案

在 ARM 官网的 PACK 下载页面,找到 Keil.STM32F1xx_DFP.2.4.1.pack 这样的文件(版本号可能更新),下载后直接双击,或者用 Pack Installer 的 File -> Import 菜单导入。

离线 Pack 的好处是:一次下载,之后可以反复安装,适合内网开发环境。安装完成后,可以在 Pack 区域看到 STM32F1 系列的组件列表,包括:

  • CMSIS
  • Device:Startup
  • Device:STM32F103 系列的外设定义
  • Flash 编程算法

这里要注意 DFP 版本并不是越新越好。有些过于新的 DFP 会默认启用一些新的 CMSIS 头文件规范,对老工程不友好。STM32F1 系列的话,2.3.0 到 2.4.x 这个区间都适合。

3.4 确认 Pack 安装成功

最简单的方法:在 uVision 中点击 Project -> New uVision Project,在弹出的芯片选择对话框中,直接输入 STM32F103C8,如果能看到对应型号并支持点选,说明 Pack 已经生效。如果没有,回到 Pack Installer 里再确认一遍安装状态。

4. 第三步:创建一个可编译、可烧录的 STM32F103 工程

4.1 工程结构选型:标准库、HAL 库还是 LL 库

STM32F103 的软件开发方式通常有三种:标准外设库(StdPeriph)、HAL 库、LL 库。在 MDK v5.43a 下,这三种都能用,但取舍差别不小。

如果你看的是 ST 官方或较老的教程,大概率用的标准外设库;如果是从 STM32CubeMX 起步,用的是 HAL 库。我的观点是:新学的人建议直接上 HAL 库,因为 CubeMX 生成的代码可以直接在 MDK 中打开,省去手写初始化配置的大量时间,比如 SPI 通过 DMA 读取传感器数据这种外设组合,CubeMX 图形化配置完再导入 MDK 编译,效率高很多。如果你在维护老项目、或者需要对寄存器级别的操作有绝对掌控力,标准库依然能打。

无论选哪种,MDK 工程的文件组织逻辑是一样的,都要包含:启动文件、系统时钟文件、外设驱动、用户主程序。

4.2 用 uVision 创建一个空白工程

在菜单 Project -> New uVision Project,输入工程名(比如 STM32F103_Demo),选择保存路径。这时会弹出 Device 选择窗口,按芯片具体型号选择,比如:

  • STM32F103C8T6:选择 STMicroelectronics -> STM32F1 Series -> STM32F103 -> STM32F103C8。
  • STM32F103ZET6:对应 STM32F103ZE。

选好型号后,会弹出 Manage Run-Time Environment 窗口。在这里可以勾选需要的软件组件,比如 CMSIS:CORE、Device:Startup,这两个是必须的。其他外设组件可以按需勾选,如果不想用 MDK 自带的组件,也可以后面手动添加库文件。

4.3 芯片选型与启动文件的关系

选完芯片后,uVision 会自动为工程添加对应的启动文件(比如 startup_stm32f103xb.s)和系统文件(system_stm32f1xx.c),这是初学者最容易忽略的部分。很多人编译报错,原因就是工程里少了这两个基础文件。

启动文件的作用是:定义中断向量表、初始化堆栈、调用 SystemInit、跳转到 main 函数。system_stm32f1xx.c 则负责把系统时钟配置到目标主频(比如 72MHz)。如果不小心删了启动文件,整个工程必然编译失败。

4.4 配置编译输出与调试器选项

建立工程后,在 Project -> Options for Target 里,有几个选项必须确认:

  • Output 选项卡:勾选 Create HEX File,这样编译后能生成用于烧录的 .hex 文件。
  • Debug 选项卡:右侧 Use 下拉框里选择调试器类型,常用的是 ST-Link Debugger 或 J-LINK。如果用的是开发板自带的 CMSIS-DAP,这里选 CMSIS-DAP Debugger。
  • Utilities 选项卡:勾选 Use Debug Driver 或选择 ST-Link,这一步负责烧录时调用下载算法。
  • C/C++ 选项卡:如果用了 HAL 库或者标准库,需要在这里添加 Include Paths,也就是头文件路径。

4.5 一个最小可运行的工程,源文件要准备多少

以标准库为例,一个最小点灯工程,源文件大概需要这些:

  • main.c:主循环,控制 GPIO。
  • stm32f10x_gpio.c / stm32f10x_rcc.c:外设驱动源文件(按需从标准库拷贝)。
  • stm32f10x_it.c:中断服务函数文件。
  • system_stm32f10x.c:时钟初始化。
  • startup_stm32f10x_hd.s:启动文件。

用 HAL 库的话,CubeMX 生成工程后会把这些都替你组织好,你只需要在 MDK 里打开 .uvprojx 工程文件。

4.6 从 CubeMX 生成的工程导入 MDK 的注意事项

用 CubeMX 生成工程时,Toolchain 选择 MDK-ARM V5,生成的 .uvprojx 直接双击就能用 MDK 打开。

这里有一个常见坑:如果 CubeMX 版本较新,生成的工程可能默认使用 AC6 编译器。虽然 v5.43a 能编译 AC6 代码,但如果你想把工程切回 AC5,需要在 Options -> Target -> ARM Compiler 里切换为 Version 5,并且把相应的启动文件、宏定义重新检查一遍。我个人的习惯是:新工程用 AC5,因为很多开源代码、老驱动都基于 AC5 的语法习惯,切换到 AC5 后省去一堆编译告警。

5. 第四步:编译、烧录、调试的完整闭环

5.1 第一个程序,建议从点灯开始

硬件上最简单的方式是一块 STM32F103 最小系统板,外接 ST-Link,然后板载一个 LED 接在 PC13(比如常见的 STM32F103C8T6 蓝色 pill 板)。程序逻辑很简单:开启 GPIOC 时钟,配置 PC13 为推挽输出,然后延时翻转电平。

用库函数写法,大致如下:

#include "stm32f10x.h" void Delay(void) { for (volatile int i = 0; i < 800000; i++); } int main(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); while (1) { GPIO_ResetBits(GPIOC, GPIO_Pin_13); Delay(); GPIO_SetBits(GPIOC, GPIO_Pin_13); Delay(); } }

这段代码在 MDK 里直接编译,正常情况下 0 Error 0 Warning,生成的 .hex 大小只有几 KB。

5.2 Flash 下载算法配置与烧录流程

在开始烧录之前,打开 Options for Target -> Utilities -> Settings,这里会列出当前调试器的信息。核心要确认的是 Flash Download 列表里是否自动识别了 STM32F10x Med-density Flash 这种编程算法。如果列表为空,需要手动 Add 对应的算法。

对于 STM32F103C8T6 这种中容量产品(64KB Flash),算法是 STM32F10x Med-density Flash;对于 ZET6(512KB Flash),算法是 STM32F10x High-density Flash。选错算法,轻则烧录失败,重则把整个 Flash 内容擦掉但写不进去。

实际烧录操作有两种方式:

  • 方式一:进入 Debug 模式,点击菜单 Flash -> Download,或者直接按 F8 快捷键,MDK 会通过调试器把程序写入 Flash,然后自动复位运行。
  • 方式二:把工程编出来的 .hex 文件,用 ST-Link Utility、STM32CubeProgrammer 或第三方 Flash 烧录工具单独烧录。

在调试阶段,直接按 F8 最方便,程序下载完成即可进入硬件调试。这里有一个实际体会:初次烧录时一定确认接线,ST-Link 的 SWDIO、SWCLK、GND、3V3 对应好,接反了大概率识别不到目标芯片,甚至可能烧坏调试器。

5.3 Debug 调试模式下的几个实用操作

进入在线调试后,经常用到的窗口有:

  • Register 窗口:观察 R0-R15、PSP、MSP 等寄存器值,做异常分析时非常有用。
  • Memory 窗口:直接查看指定地址的内存内容,比如检查 SPI DMA 接收缓冲区的原始数据。
  • Watch 窗口:右键变量名 Add to Watch,实时观察变量的变化。
  • Peripherals 窗口:可以直接查看 GPIO、USART、SPI 外设寄存器的当前值,很多外设问题在这里一眼就能看出来。

关于调试模式下的一个技巧性内容,热搜词里有人问“keil调试助手里面的 debug 模式如何显示结构体变量”,这里顺带讲一下:在 Watch 窗口添加结构体变量时,先展开结构体,然后在成员变量的后面输入要监视的表达式,比如输入数组名加 [0] 可以逐项查看数组元素;如果结构体含有指针成员,直接展开指针指向的内存即可查看具体数值。另外,在 Call Stack + Locals 窗口可以自动显示当前函数内的局部变量,包括结构体。

调试中还经常遇到的问题就是程序跑飞。当单步执行时,如果程序跳到了一个全是 0xFFFFFFFF 的地址,通常说明芯片进入了 HardFault_Handler。这时打开 Processor Fault Status 窗口查看 CFSR、HFSR 寄存器,大概能看出是总线错误还是栈溢出;如果栈溢出,优先检查启动文件中 Stack Size 是否太小,或者主程序里是否有超大的局部数组。

6. 常见问题与排查技巧实录

6.1 编译报错“cannot open source input file ... 或 No such file”

这种报错八成是 Include Paths 路径没有配置对。检查 C/C++ 选项卡里 Include Paths 是否包含所有头文件所在目录,尤其用 HAL 库时,至少需要包含:

  • 固件包根目录下的 Drivers/CMSIS/Include
  • Drivers/CMSIS/Device/ST/STM32F1xx/Include
  • Drivers/STM32F1xx_HAL_Driver/Inc

标准库同理,需要把每个外设驱动的头文件目录都加进去。出现这类问题,不要慌,把路径逐条捋一遍基本能解决。

6.2 下载失败:No Target Connected 或 RDDI-DAP Error

这个问题的高频原因是接线、驱动、供电三选一。先检查 ST-Link 与板子的接线是否牢靠,再用电脑的设备管理器查看驱动是否被正确识别。如果设备管理器里 ST-Link 显示黄色感叹号,重新安装驱动。

另一个常见原因是开发板供电不足。某些小系统板依靠 ST-Link 供电,但 ST-Link 输出的 3.3V 电流有限,如果板上有传感器、OLED、WiFi 模块同时取电,一进入烧录过程电压被拉低,调试器就掉线了。解决方法是给开发板单独接 USB 供电,同时共地。

6.3 编译通过、烧录成功,但程序不运行

先检查 Boot0 引脚的启动模式。STM32F103 的 BOOT0 接低电平时从主 Flash 启动,接高电平时进入系统引导或串口下载模式。如果你之前用串口下载过程序,把 BOOT0 跳线跳回 0 再看。

再一个常见原因是看门狗或者时钟配置问题。比如初始化时把独立看门狗(IWDG)使能了,但主程序里没有及时喂狗,导致芯片一直复位。排查方法是先注释掉所有看门狗相关代码,确认程序能跑起来再说。

6.4 中文乱码问题

MDK 默认编辑器对中文的支持并不好。如果你在代码注释里写中文,或者用 OLED 显示屏显示中文,经常遇到乱码。建议在 Edit -> Configuration -> Editor -> Encoding 里把默认编码改为 UTF-8。但这里有个坑:改编码后,之前用 GB2312 编码保存的旧文件可能直接变成乱码,注意切换编码时的备份。

如果只是串口打印乱码,排查方向是:代码里的字符串编码、串口波特率、目标板晶振是否与你程序设置的时钟一致。

6.5 关于 License、授权和版本的一些提醒

每次打开 MDK 时,如果日志里出现 FLEXlm Error 或 License 到期提示,说明授权异常。评估版不需要额外激活,但会有代码量限制和弹窗提醒,不影响学习使用。

再次强调,市面上流传的注册机类工具,无论从合规性还是安全性上都不值得碰,而是建议直接通过 ARM 官网购买 Node-Locked License。除非你只是用评估版做学习,32KB 限制对 STM32F103 常用外设实验完全够用。

6.6 其他高频问题速查表

现象常见原因处理建议
编译时 AC6 报错老代码依赖 AC5 语法切换编译器到 Version 5
下载算法不匹配DFP 缺失或选错 Flash 算法更新 DFP,在 Flash Download 里重新选
调试时无法设置断点编译优化等级太高将 Optimization 改为 -O0 或调试等级
编译变量未定义头文件包含不全使用 Go To Definition 追踪定位
程序复位后时钟不对外部晶振失效改用内部时钟确认问题是否在晶振电路
打开老工程报错缺少旧版 DFP安装对应的器件支持包

7. 一些值得一提的典型应用场景

7.1 串口控制与 Modbus 通信

STM32F103 配上 MDK 开发环境,最常见的工业应用就是串口控制和 Modbus 通信。很多传感器、电表、PLC 都支持 Modbus-RTU,而 ModbusPoll 这类上位机软件可以直接与 STM32 下位机联调。在 MDK 工程里,串口接收最好配合中断或 DMA,否则高速率通信丢包会非常严重。

拿 SPI 通过 DMA 方式读取芯片数据为例,用 CubeMX 配置 SPI 外设和 DMA 通道后,生成的代码里既有初始化流程也有 DMA 中断回调,之后用 MDK 编译烧录,读取 sensor 数据时效率比轮询方式高几个量级。类似的配置,比如 AD7190 这种高精度 ADC 通过 SPI 读取,也可以用同一个套路。

7.2 在 STM32F103 上移植 FreeRTOS

很多人在 MDK 环境下把 FreeRTOS 移植到 STM32F103C8T6。核心步骤是:在工程里加入 FreeRTOS 源码中的 kernel 相关文件(tasks.c、queue.c、list.c、portable 里的 GCC/ARM_CM3 移植文件),然后配置 FreeRTOSConfig.h 里的宏定义。v5.43a 的编译环境对 FreeRTOS 非常友好,只要把时钟节拍源选好,普通点灯演示基本一次成功。

注意一点:用 AC5 编译 FreeRTOS 时,栈对齐方式要符合 ARM AAPCS 标准,开发头文件里的 configTOTAL_HEAP_SIZE 不要开得太大,C8T6 只有 20KB RAM,给系统留足空间。

7.3 音频解码和第三方库移植

热搜词里还有像“stm32f103移植minimp3解码库”这种需求。在 MDK 中移植第三方库的思路几乎一致:将源码文件加入工程,把头文件路径和宏定义配置好,然后处理与硬件相关的数据输入输出接口。minimp3 的特点是单文件、依赖少,在 MDK 中移植时重点在于内存分配:解码 MP3 至少需要几十 KB 的 RAM 缓冲区,所以不建议在 C8T6 这种小内存芯片上解码高码率文件,ZET6 这类大内存型号会更合适。

7.4 跨厂商芯片的工程移植

有的项目要求把 STM32F103 的 HAL 库工程移植到其他厂商同内核芯片上,比如 APM32。在 MDK 环境中做这件事,大体思路是:保留用户应用层代码,替换 CMSIS 设备头和启动文件,编译链接层面则切换对应的 DFP。这需要你对工程的每一个外设初始化代码都做一次筛查,因为不同厂商的寄存器和外设布局不是全部兼容。

8. 关于环境搭建这件事的一些真心话

从零搭一套 MDK-ARM v5.43a + STM32F103 开发环境,对老手来说也就十分钟的事,但对新手来说,中间可能踩的坑确实不少。我在帮同事和学员排错时,见过太多人卡在安装路径中文、DFP 版本不匹配、调试器驱动这些并非不可逾越的问题上。

我的实际体会是:搭建开发环境这件事,最重要的是“固定”和“最小化”。固定指的是,选定一个版本组合之后,不要再频繁升级,尤其不要在生产项目做到一半时去换编译器或 DFP 版本。最小化指的是,出了问题不要一下子怀疑编译器、怀疑库、怀疑电脑,先用最小工程验证硬件通路,再逐步添加代码。

如果你刚开始接触 STM32F103,建议从一块最小系统板加一个 ST-Link 开始,不要去碰那些功能复杂的大板子,先把点灯跑通,再逐步加串口、SPI、DMA、FreeRTOS。环境稳定之后,你会发现 MDK v5.43a 这个“老版本”反而是让你最安心能出活的工具。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询