1. 新建本地工程文件夹



2. 移植库函数文件
1)
固件库中的CMSIS和Driver文件夹复制到工程中的Libraries文件夹中,


并删除无用的文件


2)
将固件库中官方提供的示例程序中,复制中断相关的函数移植到本地工程的User文件夹中


并删除stm32f4xx_it.c中的一些代码


3. 开始新建工程
打开keil 5新建工程,选择新建的keil5工程的存储位置并命名,选择芯片型号




4. 添加组文件夹


5. 给组文件夹添加文件
5.1 StartUp组文件按夹


在此文件夹中添加汇编写的启动文件,当前使用的芯片是stm32f407
5.2 CMSIS组文件夹

添加内核相关的文件,单片机系统初始化、配置时钟的文件
5.3 FWLB组文件夹

添加全部的固件库的文件
5.4 USER组文件夹
添加中断相关的文件

创建main.c文件

选择创建的文件的存储位置

6.添加头文件路径
以上在给组文件夹移植文件时,都只添加了.c文件,并没有添加.h文件
keil5的魔术棒处可批量添加头文件位置


7.添加宏处理



8. 设置文件是否加入编译

下方调试时也会提到,把stm32f4xx_fmc.c也不加入编译。
9. 编译验证

10. 修改调试
编写main函数后,编译验证
在我编译后,会报错和警告
core_cmFunc.h(629): error: unknown register name 'vfpcc' in asm
这基本可以断定是 CMSIS 版本和你当前用的编译器(toolchain)不匹配 导致的。
vfpcc这个报错是怎么来的?
vfpcc是 ARMCC5(Keil 旧编译器) 那套内联汇编写法里用的 clobber 名称。但你现在的编译输出风格更像 GCC/Clang(ARM Compiler 6 / armclang) ,这些编译器不认识
"vfpcc"这个 clobber,于是直接报错。✅ 结论:你工程里的 CMSIS 头文件(
core_cmFunc.h)是偏 ARMCC5 的老版本/写法,但你项目用的却是 GCC 或 ARM Compiler 6(armclang)。
stm32f4xx_fmc.c: identifier "FMC_BCR1_BURSTEN" is undefined
FMC_BWTR1_ADDSET / ADDHLD / DATAST / BUSTURN / ACCMOD ... is undefined
FMC_Bank1E / FMC_Bank1 / FMC_Bank2 ... is undefined你工程把
stm32f4xx_fmc.c编进去了,但你当前这套头文件/芯片分支对 F407 没把 FMC 那套宏打开 ,所以stm32f4xx_fmc.c里用到的FMC_BCR1_* / FMC_Bank*全部 undefined。而你库里同时有
stm32f4xx_fsmc.c和stm32f4xx_fmc.c,说明 ST 这套库同时兼容两种命名/外设差异,但对某个具体芯片只能用其中一个,不能两个都无脑加进工程。
你该怎么选(对 STM32F407 来说)
STM32F407 的外部存储控制器通常是 FSMC (老命名/老寄存器宏体系),而 FMC 更常见于 F42x/F43x 等系列(以及后续统一命名的库)。
✅ 所以对你现在的情况,最稳的处理是:
✅ 方案 1(推荐):只保留 FSMC,移除 FMC
从工程里 Remove
stm32f4xx_fmc.c(只从工程移除,不用删文件)保留
stm32f4xx_fsmc.c(如果你要用外扩 SRAM/NOR/LCD 才需要;不需要就也可以不加)重新编译
为什么会这样(通俗解释)
stm32f4xx_fmc.c里面写的是 "FMC_* 宏/寄存器名",这些宏通常在对应的头文件分支里才会定义。但你现在编译到的
stm32f4xx.h/stm32f4xx_fmc.h并没有给 F407 提供那套FMC_*定义,于是.c文件里引用它们就全炸了。你现在只是 main 里 while(1),FSMC/FMC 都不需要 ,所以最简单是两个都别加;但你只要不编译
fmc.c,那堆 undefined 就会立刻消失。
警告:incompatible redefinition of macro "DBGMCU_APB2_FZ_DBG_TIMx_STOP" (declared at line xxxx)它不是"你写错了代码",而是 ST 的
stm32f4xx.h里有一组宏被重复定义了两次,而且定义值还不一样 (所以编译器报 incompatible redefinition)。比如这类宏本来用于"调试时冻结 TIM 定时器"的 DBGMCU 功能:
DBGMCU_APB2_FZ_DBG_TIM1_STOP
DBGMCU_APB2_FZ_DBG_TIM8_STOP
DBGMCU_APB2_FZ_DBG_TIM9_STOP
DBGMCU_APB2_FZ_DBG_TIM10_STOP
DBGMCU_APB2_FZ_DBG_TIM11_STOP在某些 ST 的头文件版本里,这几个宏有一段写法类似"把 APB2 的宏映射到 APB1 的宏",导致重复定义/值不一致,于是 ARMCC5 就一直警告。
✅ 结论:这是 固件库(header)本身的历史/兼容性问题,不是你工程配置"混库"的唯一证据(当然混库也可能导致更多重复定义,但你这张图看起来就是同一个文件内的重复定义)。
同一个文件里把同一批宏定义了两次,而且第二次(Legacy aliases)把 APB2 的宏错误地映射到了 APB1 的宏,所以 ARMCC 报 "incompatible redefinition"。
你这里的结构是:
11574~11578:正确的 APB2 位定义(数值 0x00000001 / 0x00000002 / 0x00010000...)
11581~11585 :又把同名宏重新
#define成DBGMCU_APB1_FZ_DBG_TIMx_STOP(这明显不对:APB2 不应该 alias 到 APB1)所以每次包含
stm32f4xx.h都会产生 5 条 warning,累计就 200+。
推荐修法(最干净,warning 清零,语义也正确)
在
stm32f4xx.h里把 "Legacy aliases" 这 5 行改成 不覆盖已有定义:把 11580~11585 这一段改成这样(加
#ifndef防重定义):
cpp/* Legacy aliases */ #ifndef DBGMCU_APB2_FZ_DBG_TIM1_STOP #define DBGMCU_APB2_FZ_DBG_TIM1_STOP DBGMCU_APB1_FZ_DBG_TIM1_STOP #endif #ifndef DBGMCU_APB2_FZ_DBG_TIM8_STOP #define DBGMCU_APB2_FZ_DBG_TIM8_STOP DBGMCU_APB1_FZ_DBG_TIM8_STOP #endif #ifndef DBGMCU_APB2_FZ_DBG_TIM9_STOP #define DBGMCU_APB2_FZ_DBG_TIM9_STOP DBGMCU_APB1_FZ_DBG_TIM9_STOP #endif #ifndef DBGMCU_APB2_FZ_DBG_TIM10_STOP #define DBGMCU_APB2_FZ_DBG_TIM10_STOP DBGMCU_APB1_FZ_DBG_TIM10_STOP #endif #ifndef DBGMCU_APB2_FZ_DBG_TIM11_STOP #define DBGMCU_APB2_FZ_DBG_TIM11_STOP DBGMCU_APB1_FZ_DBG_TIM11_STOP #endif这样做的效果是:
由于前面 11574~11578 已经定义过了,
#ifndef会阻止再次定义warning 直接消失
保留了"如果某些老芯片头文件没给 APB2 定义时,还能兜底 alias"的意图
你也可以更激进:直接把 11581~11585 这 5 行删掉/注释掉。
但加
#ifndef更"温和",更不容易引入别的兼容性问题
