尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Keil MDK 5.37+ 手动安装 ARM Compiler 5 解决 STM32 老工程编译报错

发布时间:2026/9/24 12:00:35

资讯中心
01
ARTICLE

Keil MDK 5.37+ 手动安装 ARM Compiler 5 解决 STM32 老工程编译报错

Keil MDK 5.37+ 手动安装 ARM Compiler 5 解决 STM32 老工程编译报错
1. 为什么新版 Keil MDK 打开老工程就报错如果你最近把 Keil MDK 升级到了 5.37 或更高版本然后打开一个用 STM32 CubeMX 生成的工程编译时大概率会看到类似这样的报错*** Error: Cannot find ARM Compiler ARMCC version 5或者更直接一点The selected ARM Compiler version is not installed.再或者CubeMX 生成的 Makefile 或工程文件里写死了ARMCC路径但新版 MDK 默认只装了 ARM Compiler 6也就是armclang于是编译器找不到整个工程直接卡死。这个问题的根源其实不复杂ARM Compiler 5简称 AC5从 MDK 5.37 开始就不再随安装包默认提供了。ARM 官方从 5.37 版本起把 AC5 从默认安装组件中移除只保留 AC6。但大量存量 STM32 工程——尤其是 CubeMX 生成的、基于 HAL 库的老工程——默认用的还是 AC5 的编译器和链接脚本甚至有些工程里直接引用了armcc的绝对路径。一旦你升级了 MDK这些工程就全部罢工。所以这篇文章要解决的问题很明确在 Keil MDK 5.37 及以上版本中手动把 ARM Compiler 5.06u7 装回去让老 STM32 工程能正常编译。适合所有还在维护 STM32 老项目、又不想降级 MDK 的嵌入式开发者。下面我会从原理、下载、安装、配置到踩坑排查一步步讲清楚。2. 先搞清楚 AC5 和 AC6 到底差在哪2.1 编译器架构的本质区别ARM Compiler 5 的核心是armcc它基于传统的 ARM 编译器架构对 C 标准的支持停留在 C99 为主部分 C11 特性支持不完整。而 ARM Compiler 6 的核心是armclang基于 LLVM/Clang 架构支持 C11、C14 甚至部分 C17 特性优化能力更强代码密度和性能在多数场景下都优于 AC5。但问题在于AC6 对老代码的兼容性并不完美。很多 STM32 老工程里用了 AC5 特有的语法扩展、内联汇编格式、__attribute__写法甚至链接脚本的语法都有差异。你直接把编译器从 AC5 切到 AC6轻则一堆 warning重则链接失败、启动文件报错、中断向量表对不上。2.2 为什么 CubeMX 生成的工程默认用 AC5STM32 CubeMX 在生成 Keil 工程时默认的编译器选项长期是 AC5。原因很简单ST 的 HAL 库和大量中间件比如 FreeRTOS、FatFS、USB 库在早期都是基于 AC5 验证的ST 官方例程也大多用 AC5 编译。虽然后来 CubeMX 新版本开始支持 AC6但很多老版本的 CubeMX 生成的工程文件里编译器版本是写死的。具体来说CubeMX 生成的.uvprojx文件里会有类似这样的配置ArmAdsMisc useUlib0/useUlib Optim2/Optim oTime0/oTime SplitLS0/SplitLS OneElfS1/OneElfS Strict0/Strict EnumInt0/EnumInt PlainCh0/PlainCh Ropi0/Ropi Rwpi0/Rwpi wLevel2/wLevel uThumb0/uThumb uSurpInc0/uSurpInc uC991/uC99 uGnu0/uGnu useXO0/useXO v6Lang1/v6Lang v6LangP1/v6LangP vShortEn1/vShortEn vShortWch1/vShortWch v6Lto0/v6Lto v6WtE0/v6WtE v6Rtti0/v6Rtti VariousControls MiscControls/MiscControls Define/Define Undefine/Undefine IncludePath/IncludePath /VariousControls /ArmAdsMisc其中v6Lang相关的配置就是 AC6 的选项。如果工程是用老版 CubeMX 生成的这里可能根本没有 v6 相关字段MDK 就会默认去找 AC5。2.3 手动装 AC5 和降级 MDK 哪个更划算你可能会想那我直接把 MDK 降回 5.36 不就行了理论上可以但实际操作中有几个问题。第一降级 MDK 意味着你要卸载当前版本重新安装老版本过程繁琐而且可能影响你其他新工程的开发。第二MDK 5.36 的安装包现在也不太好找官方下载页面默认给的都是最新版。第三你团队里其他人可能已经用了新版 MDK你一个人降级会导致工程文件版本不一致。相比之下手动安装 AC5 到新版 MDK 里是更干净、更可控的方案。你既保留了新版 MDK 的 IDE 功能和调试能力又能让老工程继续用 AC5 编译。而且 AC5 和 AC6 可以在同一个 MDK 里共存你可以在工程设置里自由切换。3. 下载 ARM Compiler 5.06u7 的正确姿势3.1 版本号里的门道ARM Compiler 5 有很多个小版本比如 5.06u1、5.06u2……一直到 5.06u7。为什么偏偏选 5.06u7因为这是 AC5 系列的最后一个更新版本build 960修复了之前多个版本的 bug对 C99 的支持也最完善。很多 STM32 老工程在 5.06u7 下编译最稳定用更早的版本反而可能遇到一些奇怪的链接错误。所以记住这个完整版本号ARM Compiler 5.06 update 7 (build 960)。你在下载和安装的时候认准这个版本。3.2 从哪里获取安装包ARM Compiler 5.06u7 的安装包官方渠道是 ARM 的开发者网站。你需要注册一个 ARM 账号然后在下载页面找到 ARM Compiler 5 的归档版本。具体路径大概是ARM Developer 网站 → Downloads → Arm Compiler → 选择 Arm Compiler 5.06u7 → 下载 Windows 版本。下载下来的文件通常是一个压缩包解压后里面会有setup.exe或者直接是一个可移植的文件夹结构。有些版本是独立的安装程序有些是直接解压就能用的绿色包。这个要注意区分。注意网上有很多第三方网盘分享的 AC5 安装包版本参差不齐有些甚至被修改过。建议尽量从官方渠道获取如果实在找不到也要核对文件哈希值确保安装包完整未被篡改。3.3 安装包目录结构预览解压后你通常会看到这样的结构ARM_Compiler_5.06u7/ ├── bin/ │ ├── armcc.exe │ ├── armasm.exe │ ├── armlink.exe │ ├── arm ar.exe │ └── ... ├── include/ │ ├── stdio.h │ ├── stdlib.h │ └── ... ├── lib/ │ └── ... └── ...这个目录结构很关键因为后面在 MDK 里配置编译器路径时你要指向的就是这个根目录。bin文件夹里是编译器可执行文件include是标准头文件lib是库文件。MDK 需要知道这个根目录在哪才能调用armcc去编译你的代码。4. 把 AC5 装进 MDK 的完整操作流程4.1 确定 MDK 的安装目录和编译器存放位置在动手之前先搞清楚你的 MDK 装在哪。默认路径通常是C:\Keil_v5\或者C:\Program Files\Keil_v5\MDK 的编译器组件一般放在C:\Keil_v5\ARM\ARM_Compiler_5.06u7\或者对于 AC6C:\Keil_v5\ARM\ARMCLANG\你要做的就是把下载好的 AC5 安装包解压或安装到C:\Keil_v5\ARM\下面文件夹名字建议保持为ARM_Compiler_5.06u7这样后面配置路径时不容易搞混。4.2 手动复制还是运行安装程序如果你下载的是独立安装程序直接运行setup.exe安装路径选择C:\Keil_v5\ARM\ARM_Compiler_5.06u7。安装程序会自动把文件放到位。如果你下载的是绿色压缩包直接解压到C:\Keil_v5\ARM\下确保最终路径是C:\Keil_v5\ARM\ARM_Compiler_5.06u7\bin\armcc.exe存在。实操心得我建议用绿色包直接解压的方式因为独立安装程序有时候会往注册表里写东西卸载不干净。绿色包解压即用想删就删更干净。4.3 在 MDK 里注册编译器路径文件放好了还不够MDK 不会自动发现新编译器。你需要手动告诉它。打开 Keil MDK点击菜单栏的Project→Manage→Project Items或者直接点工具栏上的Options for Target按钮那个魔术棒图标。在弹出的窗口里选择Target标签页找到ARM Compiler下拉框。正常情况下这里只会显示已安装的编译器版本。如果你刚把 AC5 文件放进去下拉框里可能还没有出现ARM Compiler 5的选项。这时候你需要点击下拉框旁边的...按钮或者进入Project→Manage→Compiler Versions手动添加编译器路径。具体操作是在Compiler Versions对话框里点击Add然后浏览到C:\Keil_v5\ARM\ARM_Compiler_5.06u7\选中这个文件夹MDK 会自动识别里面的bin目录和版本信息。添加成功后下拉框里就会出现ARM Compiler 5.06u7的选项。4.4 切换工程编译器版本编译器注册好了接下来要把当前工程切换到 AC5。还是在Options for Target的Target标签页把ARM Compiler下拉框从ARM Compiler 6改成ARM Compiler 5.06u7。改完之后点击OK保存。然后重新编译工程看看报错是否消失。注意切换编译器后有些工程可能需要清理一下之前的编译产物。点击Project→Clean Targets把旧的.o、.axf文件删掉再重新Build。否则可能因为残留文件导致链接错误。5. 配置过程中容易踩的坑和排查方法5.1 路径里有空格或中文导致识别失败MDK 对编译器路径的识别比较敏感。如果你的 MDK 安装在C:\Program Files\Keil_v5\这种带空格的路径下有时候 MDK 调用armcc时会因为路径解析问题报错。更严重的是中文路径比如C:\软件\Keil_v5\几乎必然出问题。解决办法很简单把 MDK 和 AC5 都装在纯英文、无空格的路径下。比如C:\Keil_v5\就是最稳妥的选择。如果你已经装在带空格的路径下了可以考虑把 AC5 单独解压到一个纯英文路径比如C:\ARM_Compiler_5.06u7\然后在 MDK 里指向这个路径。5.2 许可证问题导致编译器无法启动AC5 是需要许可证的。虽然 MDK 的社区版许可证可以覆盖大部分 STM32 开发场景但有时候 AC5 的许可证状态和 AC6 是分开管理的。如果你切换编译器后提示许可证错误可以检查一下File→License Management里的许可证状态。实操心得MDK 的社区版许可证对 AC5 的支持是没问题的但前提是你的 MDK 版本和许可证类型匹配。如果你用的是评估版或者过期许可证AC5 可能会拒绝编译。这时候要么更新许可证要么确认你用的是社区版。5.3 编译报错 cannot open source input file切换到 AC5 后有时候会遇到头文件找不到的问题。这通常是因为 AC5 和 AC6 的标准头文件路径不一样。AC6 用的是 Clang 的头文件AC5 用的是 ARM 自己的头文件。如果你工程里有些头文件是 AC6 特有的切到 AC5 后就会找不到。解决办法是检查工程的Include Paths设置。在Options for Target→C/C标签页里看看Include Paths是否包含了 AC5 的标准头文件目录。通常 AC5 的头文件在C:\Keil_v5\ARM\ARM_Compiler_5.06u7\include\下确保这个路径被正确引用。5.4 链接阶段报 undefined symbol这是最让人头疼的问题之一。AC5 和 AC6 的库文件格式不一样如果你工程里链接了一些预编译的.lib文件而这些库是用 AC6 编译的切到 AC5 后就会报未定义符号。排查方法是检查工程里所有.lib文件的来源。如果是 ST 官方提供的库通常会有 AC5 和 AC6 两个版本你需要选择 AC5 对应的版本。如果是自己编译的库需要用 AC5 重新编译一遍。5.5 常见问题速查表问题现象可能原因解决方法找不到 ARMCCAC5 未安装或路径未注册手动添加编译器路径许可证错误许可证不覆盖 AC5检查 License Management头文件找不到Include Paths 未包含 AC5 头文件添加 AC5 include 目录链接未定义符号库文件与编译器不匹配换用 AC5 编译的库路径解析失败路径含空格或中文改用纯英文无空格路径编译产物冲突旧编译文件残留Clean Targets 后重新编译6. 让 AC5 和 AC6 在同一台机器上和平共处6.1 多版本编译器的管理策略你不需要为了老工程而放弃新工程。MDK 支持同时安装多个编译器版本你可以在每个工程的设置里独立选择用哪个编译器。新工程用 AC6 享受更好的优化老工程用 AC5 保证兼容性互不干扰。管理策略很简单在Compiler Versions对话框里把 AC5 和 AC6 都注册进去。然后在每个工程的Options for Target里单独选择。MDK 会记住每个工程的编译器选择不会串。6.2 工程文件里的编译器版本锁定有一点要注意CubeMX 重新生成工程时可能会覆盖你在 MDK 里做的编译器设置。因为 CubeMX 是根据它自己的模板生成.uvprojx文件的如果你在 CubeMX 里没有正确配置编译器版本重新生成后可能又变回默认值。解决办法是在 CubeMX 的Project Manager→Toolchain / IDE设置里确认编译器选项。不过 CubeMX 对编译器版本的控制有限更稳妥的做法是在 CubeMX 生成工程后手动在 MDK 里改一次编译器设置然后不要再让 CubeMX 重新生成工程文件。如果必须重新生成记得重新检查编译器设置。6.3 团队协作时的版本统一如果你是团队开发确保所有人的 MDK 版本和 AC5 安装路径一致。否则会出现“我这里能编译你那里报错”的情况。建议在团队内部统一 MDK 版本号、AC5 版本号、安装路径甚至可以把 AC5 的安装包放在团队共享目录里新人入职直接复制。实操心得我们团队的做法是在项目根目录放一个tools/文件夹里面放 AC5 的绿色包和一份配置说明。新人拉下代码后按照说明把 AC5 解压到指定路径然后在 MDK 里注册一下就能用。这样比每个人自己去网上找安装包靠谱得多。7. 验证安装是否成功的实操检查7.1 编译一个最小工程装好 AC5 后别急着编译大工程。先建一个最小的 STM32 工程只包含启动文件和 main 函数用 AC5 编译一下。如果能通过说明编译器和基本环境没问题。然后再逐步把大工程切过来这样出问题容易定位。最小工程可以这样写#include stm32f1xx.h int main(void) { while (1) { } }启动文件用 ST 官方提供的startup_stm32f103xb.s链接脚本用默认的。编译选项里选择 AC5看看能不能生成.axf文件。7.2 检查编译输出信息编译成功后在 MDK 的Build Output窗口里你应该能看到类似这样的信息Toolchain: ARM Compiler 5.06u7这就说明 AC5 已经被正确调用了。如果显示的还是ARM Compiler 6说明编译器切换没生效回去检查Options for Target里的设置。7.3 用命令行验证 armcc 是否可用除了在 MDK 里验证你也可以直接在命令行里测试armcc是否可用。打开 CMD进入 AC5 的bin目录运行armcc --version如果输出类似ARM Compiler 5.06 update 7 (build 960)说明编译器本身是完好的。如果提示找不到命令说明路径没配好或者文件缺失。8. 关于 AC5 许可证和后续维护的几点提醒8.1 许可证的有效期和续期MDK 的许可证通常是一年有效期到期后需要续期。社区版许可证是免费的但需要每年重新激活。如果你发现 AC5 突然不能用了先检查许可证是否过期。在File→License Management里可以看到当前许可证的状态和到期时间。注意许可证过期后MDK 会限制编译输出大小超过 32KB 的代码无法编译。对于 STM32 老工程来说32KB 很容易超所以许可证问题一定要及时处理。8.2 AC5 的长期维护风险ARM 官方已经停止对 AC5 的功能更新只提供有限的安全维护。这意味着 AC5 不会再有新特性也不会针对新的 ARM 内核做优化。对于新项目强烈建议直接用 AC6。AC5 只适合维护存量老工程不适合作为新开发的起点。如果你手头的老工程迟早要迁移到 AC6建议尽早规划。迁移过程中最大的工作量通常是处理编译器差异导致的语法和链接问题。可以先把工程用 AC6 编译一遍看看报多少错评估一下迁移成本。8.3 备份 AC5 安装包的重要性因为 ARM 官方随时可能下架 AC5 的下载链接建议你把手头的 AC5 安装包备份一份。可以放在本地硬盘、团队共享目录或者私有代码仓库里。这样即使将来官方下载不到了你依然可以重新安装。我自己就吃过这个亏有一次换电脑想重新装 AC5结果发现官方下载页面已经找不到 5.06u7 的链接了最后是从同事那里拷贝了一份才搞定。从那以后我就把安装包和配置说明一起放进了项目仓库的tools/目录里。9. 从 AC5 迁移到 AC6 的渐进式思路9.1 先让工程能在 AC6 下编译通过如果你决定开始迁移第一步不是直接改代码而是先用 AC6 编译一遍看看报什么错。常见的错误包括内联汇编语法不兼容、__align关键字不支持、#pragma指令差异、链接脚本语法变化等。把这些错误列一个清单然后逐个解决。有些错误只需要改编译选项有些需要改代码。比如 AC6 里__align(8)要改成__attribute__((aligned(8)))__asm要改成__asm volatile等。9.2 处理链接脚本和启动文件AC5 和 AC6 的链接脚本格式有差异。AC5 用的是 scatter file.sctAC6 虽然也支持 scatter file但语法有些不同。启动文件里的汇编代码也可能需要调整特别是堆栈初始化和中断向量表的定义部分。ST 官方为 AC6 提供了更新版的启动文件和链接脚本可以直接从 ST 的 GitHub 仓库或者 CubeMX 新版本里获取。用官方提供的文件替换掉老文件能省不少事。9.3 逐步切换而不是一刀切不要试图一次性把所有模块都迁到 AC6。可以先把一些独立的、不依赖硬件的模块用 AC6 编译验证没问题后再逐步扩大范围。这样风险可控出问题也容易回退。实操心得我在迁移一个老工程时先把main.c和几个应用层文件切到 AC6底层驱动和中断处理还是用 AC5 编译的库。等应用层稳定后再逐步把底层也切过来。整个过程花了大概两周但比一次性全切要稳妥得多。10. 一些零碎但有用的经验补充10.1 MDK 安装时的组件勾选如果你还在用 MDK 5.36 或更早版本安装时记得勾选 ARM Compiler 5 组件。从 5.37 开始安装程序里就没有这个选项了必须手动装。所以如果你还没升级可以先在 5.36 里把 AC5 装好然后再升级 MDK这样 AC5 会被保留下来。10.2 工程文件版本兼容性MDK 5.37 生成的.uvprojx文件用 5.36 打开可能会提示版本不兼容。反过来5.36 生成的工程用 5.37 打开通常没问题。所以如果你团队里有人用老版本 MDK建议统一用老版本生成工程文件或者约定好大家都升级到同一版本。10.3 编译速度的取舍AC5 的编译速度通常比 AC6 慢一些特别是开启高级优化后。如果你只是日常调试可以把优化等级调低编译快一点。发布版本再开高优化。在Options for Target→C/C里可以设置优化等级AC5 的-O0到-O3都支持。10.4 调试器配置不受编译器影响切换编译器不会影响调试器配置。你之前用 ST-Link 或 J-Link 的调试设置切到 AC5 后依然有效。调试器只关心生成的.axf文件不关心是哪个编译器生成的。所以不用担心调试环境要重新配。10.5 保留一份可用的工程备份在切换编译器之前把整个工程目录复制一份备份。万一切换后出现难以解决的问题可以快速回退到备份版本。这个习惯在嵌入式开发里特别重要因为工程配置一旦乱了恢复起来很麻烦。11. 关于 CubeMX 串口中断发送配置的顺带提醒既然热词里提到了 STM32 CubeMX 串口中断发送配置这里顺带说一句。CubeMX 里配置串口中断发送需要在Connectivity→USARTx→NVIC Settings里勾选USARTx global interrupt。然后在代码里调用HAL_UART_Transmit_IT()来启动中断发送。但要注意AC5 和 AC6 对中断处理函数的编译方式有差异。AC5 下中断函数不需要特殊的属性修饰AC6 下可能需要加__attribute__((interrupt))。如果你在迁移过程中发现中断不触发先检查一下中断函数的定义方式是否匹配当前编译器。另外CubeMX 生成的stm32fxxx_it.c文件里中断处理函数的写法是固定的。如果你切换了编译器这个文件通常不需要改但如果遇到中断向量表对齐问题可能需要检查启动文件里的向量表定义。12. 最后分享几个我踩过的坑第一个坑我曾经把 AC5 解压到了一个带空格的路径下结果 MDK 死活识别不了。后来换成C:\Keil_v5\ARM\ARM_Compiler_5.06u7\就正常了。所以路径问题真的不能忽视。第二个坑有一次切换编译器后编译通过了但生成的固件跑不起来。排查了半天发现是链接脚本里的内存布局和 AC5 的默认设置不匹配。后来手动指定了 scatter file 才解决。所以切换编译器后一定要实际烧录验证不能只看编译通过。第三个坑团队里有人用 AC5有人用 AC6结果同一个工程在不同人电脑上编译出来的固件大小不一样。虽然功能都正常但版本管理很混乱。后来我们统一了编译器版本这个问题才消失。所以团队协作时编译器版本一定要统一。第四个坑AC5 的许可证过期后MDK 不会立刻报错而是编译到一半突然提示代码大小超限。这个很坑因为报错信息不直观。后来我养成了习惯每隔几个月就检查一下许可证状态避免关键时刻掉链子。这些经验看起来琐碎但每一个都是实际项目中真金白银换来的。希望你在手动安装 AC5 的过程中能少走一些弯路。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。