简介:STM32Cube_FW_F1_V1.8.0 是意法半导体面向 STM32 F1 系列微控制器推出的官方固件库封装包,配套 STM32CubeMX 图形化配置工具,适用于使用 Keil、IAR 进行嵌入式开发的初学者与工程师。它解决了外设寄存器手动配置繁琐、代码移植性差的问题,通过 HAL 与 LL 两套标准化 API,让开发者可快速完成时钟、GPIO、ADC、定时器、串口等外设初始化并生成工程代码。压缩包共约 2000 个文件,整体 109.82MB,以 c 与 h 源码、html 与 js 文档页面、s 汇编启动文件、icf 与 ld 链接脚本、uvprojx 与 ewp 工程文件为主,另含 png 图示、pdf 手册及少量 lib、bin 等二进制资源,覆盖驱动、示例与文档多个层面。目前已有 3461 人学习下载。借助该库,读者可获得 F1 全系列外设驱动源码、可直接导入 Keil/IAR 的工程模板与丰富示例,便于对照官方文档快速搭建项目框架、排查底层配置问题,提升开发效率与代码兼容性。
1. 从一次 Keil 编译报错说起:为什么我坚持用 STM32Cube_fw_F1_V1.8.0
前阵子帮一个做工业控制的朋友排查问题,他的 Keil 工程编译到一半突然报undefined symbol HAL_GPIO_Init,查了半天发现是 CubeMX 生成的代码引用了新版 HAL 库,但工程里挂的还是老版固件包,版本对不上。这种坑在 STM32F1 系列开发里太常见了——CubeMX 的 F1 封装库版本和 Keil、IAR 的器件支持包稍微错位,轻则编译报错,重则下载后外设不工作,调试起来像在黑匣子里摸路。
STM32Cube_fw_F1_V1.8.0 是 ST 官方为 F1 全系(从 F100 到 F107)提供的完整固件封装库,里面包含 HAL 驱动、LL 驱动、CMSIS 设备支持、中间件以及每个外设的例程工程。它和 CubeMX 配合使用,是 F1 开发环境搭建的地基。这份资源适合正在用 CubeMX 生成 F1 工程、需要在 Keil MDK 或 IAR EWARM 里编译下载的开发者,尤其是那些从旧版库迁移过来、或者第一次搭 F1 环境的新手。装不好这套库,后面所有外设调试都是空中楼阁。
2. 装前先对齐版本:CubeMX、Keil、IAR 和固件包的兼容矩阵
2.1 为什么 V1.8.0 是 F1 的稳定分水岭
STM32CubeF1 的版本迭代不算快,但每个大版本之间 HAL 层的 API 有细微调整。V1.8.0 是 F1 系列里比较成熟的一个版本,它对应的 CubeMX 版本是 6.x 系列,Keil MDK 需要 5.30 以上,IAR 需要 8.50 以上。我一般会先确认三件事:CubeMX 里能不能选到 F1 的 V1.8.0 固件包、Keil 的 Pack Installer 里有没有装 STM32F1xx_DFP、IAR 的器件支持文件是否覆盖 F1 全系。
如果你用的是 CubeMX 6.5 以下版本,它内置的 F1 固件包可能是 V1.7.x 或更早。这时候直接让 CubeMX 下载 V1.8.0 会提示版本不匹配,因为 CubeMX 的固件包仓库地址和本地缓存路径是绑定的。常见做法是手动把 V1.8.0 的包放到 CubeMX 的 Repository 目录下,再在 CubeMX 的 Help -> Manage embedded software packages 里勾选本地导入。
提示:CubeMX 的固件包默认存放在用户目录下的
STM32Cube/Repository/,Windows 是C:\Users\你的用户名\STM32Cube\Repository\,Linux 是~/STM32Cube/Repository/。手动放包时目录名必须和包内.package.xml里的版本号一致,否则 CubeMX 认不出来。
2.2 Keil 和 IAR 的器件支持包怎么选
Keil MDK 这边,STM32F1 的器件支持包叫Keil.STM32F1xx_DFP,目前主流版本是 2.4.0 以上。这个 DFP 包里包含了启动文件、系统初始化代码和 Flash 算法,和 CubeF1 的 HAL 库是两套东西,但必须同时装。我见过有人只装了 DFP 没放 CubeF1 的 HAL 源码,结果 CubeMX 生成的工程里#include "stm32f1xx_hal.h"直接飘红。
IAR 那边对应的是IAR Embedded Workbench for ARM的器件支持文件,安装时勾选 STM32F1 系列即可。IAR 对 CubeF1 的兼容性比 Keil 稍好,因为 IAR 的工程模板里已经预置了 CMSIS 和 HAL 的路径引用,但前提是你把 CubeF1 的包解压到 IAR 能识别的目录,或者在工程里手动指定Drivers/STM32F1xx_HAL_Driver的路径。
| 工具 | 最低版本 | 关键组件 | 常见问题 |
|---|---|---|---|
| CubeMX | 6.0 | F1 固件包 V1.8.0 | 包路径不对导致无法生成代码 |
| Keil MDK | 5.30 | STM32F1xx_DFP 2.4.0 | DFP 和 HAL 版本错位 |
| IAR EWARM | 8.50 | STM32F1 器件支持 | 头文件搜索路径未包含 HAL |
| CubeF1 | V1.8.0 | HAL/LL/CMSIS/中间件 | 解压后目录结构被改动 |
2.3 下载和目录结构确认
拿到 STM32Cube_fw_F1_V1.8.0 的包之后,先别急着解压到工程目录。我一般会把它放在一个独立的固件库根目录,比如D:\STM32\STM32Cube_FW_F1_V1.8.0\,然后检查里面的关键文件夹是否完整:
# 检查 CubeF1 包的核心目录结构 ls STM32Cube_FW_F1_V1.8.0/ # 预期输出: # Drivers/ # HAL、LL、CMSIS 驱动 # Middlewares/ # USB、FatFs、FreeRTOS 等中间件 # Projects/ # 各开发板的例程工程 # Utilities/ # 辅助工具和配置文件Drivers/STM32F1xx_HAL_Driver/下面是 HAL 的源码和头文件,Drivers/CMSIS/Device/ST/STM32F1xx/下面是启动文件和系统初始化。这两个路径在 Keil 和 IAR 里都要手动加到工程的 Include Paths 里。如果解压后发现Projects/文件夹是空的,说明下载的包不完整,需要重新获取。
3. 在 Keil MDK 里挂载 CubeF1 V1.8.0 并生成第一个工程
3.1 CubeMX 生成代码时的关键选项
打开 CubeMX,新建工程选 STM32F103C8T6(或者你实际用的型号),在 Project Manager 里设置 Toolchain 为 MDK-ARM V5。这里有个容易翻车的地方:CubeMX 的Firmware Package选项里要确认选的是STM32Cube FW_F1 V1.8.0,而不是默认的最新版。如果下拉框里没有 V1.8.0,就去 Help -> Manage embedded software packages 里手动导入。
生成代码前,在 Code Generator 里勾选Copy only necessary library files,这样 CubeMX 只会把用到的 HAL 源文件复制到工程目录,而不是把整个 CubeF1 包塞进去。对于 F1 这种 Flash 只有 64KB 或 128KB 的芯片,这个选项能省不少空间。
// 生成后的工程里,main.c 会自动包含 HAL 初始化 #include "main.h" #include "stm32f1xx_hal.h" // CubeMX 生成的 SystemClock_Config 会调用 HAL_RCC_OscConfig // 如果 HAL 库版本不对,这里会报未定义引用生成之后,工程目录下会出现Drivers/STM32F1xx_HAL_Driver/和Drivers/CMSIS/,这两个文件夹就是从 CubeF1 V1.8.0 里复制过来的。如果发现Drivers文件夹是空的,说明 CubeMX 的固件包路径没配对,需要回到 Manage embedded software packages 里检查。
3.2 Keil 工程里手动补路径和宏定义
CubeMX 生成的 Keil 工程通常已经配好了 Include Paths,但如果你是从旧工程迁移过来的,或者手动新建的 Keil 工程,就需要自己加。在 Keil 的 Options for Target -> C/C++ -> Include Paths 里,至少要有这几条:
# Keil Include Paths 需要包含的目录 ..\Drivers\STM32F1xx_HAL_Driver\Inc ..\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy ..\Drivers\CMSIS\Device\ST\STM32F1xx\Include ..\Drivers\CMSIS\Include ..\Core\IncInc\Legacy这个目录容易被忽略,但如果你用了旧版 HAL 的 API,比如HAL_GPIO_WritePin的老式写法,就需要它。另外在 Define 里要加上USE_HAL_DRIVER和STM32F103xB(根据你的芯片型号改),这两个宏决定了 HAL 库编译时包含哪些外设模块。
注意:Keil 的 DFP 包和 CubeF1 的 HAL 库不能混用启动文件。DFP 里的
startup_stm32f103xb.s和 CubeF1 里的startup_stm32f103xb.s内容基本一致,但如果你两个都加了,链接时会报重复定义。我一般只保留 CubeF1 里的启动文件,把 DFP 的启动文件从工程里移除。
3.3 编译验证和常见报错处理
第一次编译时,最常见的报错是cannot open source input file "stm32f1xx_hal_conf.h"。这个文件在 CubeF1 的Projects/STM32F103RB-Nucleo/Inc/或者你自己工程的Core/Inc/下。CubeMX 生成工程时会自动在Core/Inc/里放一份,但如果手动迁移工程,就需要从 CubeF1 的例程里复制一份过来,然后根据实际用到的外设取消对应的#define HAL_XXX_MODULE_ENABLED注释。
另一个高频报错是L6218E: Undefined symbol HAL_Init,这通常是因为stm32f1xx_hal.c没有被加到工程里。CubeMX 生成的工程会自动把 HAL 源文件加到 Application/User 分组下,但手动新建工程时容易漏。检查 Keil 工程窗口里有没有stm32f1xx_hal.c、stm32f1xx_hal_gpio.c、stm32f1xx_hal_rcc.c这几个核心文件。
# 如果编译报错找不到 HAL 源文件,用这条命令快速检查 find . -name "stm32f1xx_hal.c" -o -name "stm32f1xx_hal_gpio.c" # 预期输出应该在 Drivers/STM32F1xx_HAL_Driver/Src/ 下编译通过后,下载到芯片之前还要确认 Flash 算法选的是STM32F10x 128K或对应你芯片容量的算法。Keil 的 DFP 包里自带这些算法,在 Options for Target -> Debug -> Settings -> Flash Download 里能看到。
4. IAR EWARM 下的工程配置和 CubeF1 路径绑定
4.1 IAR 工程模板的导入方式
IAR 对 CubeF1 的支持方式和 Keil 不太一样。IAR 没有类似 DFP 的独立器件包,而是通过IAR Embedded Workbench安装目录下的arm/config/devices/里的器件描述文件来识别 STM32F1。CubeF1 V1.8.0 的Projects/文件夹里已经包含了 IAR 的工程模板,比如STM32F103RB-Nucleo/IAR/下的.eww文件,直接双击打开就能用。
但如果你是用 CubeMX 生成 IAR 工程,CubeMX 会生成.ewp和.eww文件,这时候需要手动把 CubeF1 的 HAL 源文件路径加到 IAR 的 Project -> Options -> C/C++ Compiler -> Preprocessor 里。IAR 的路径引用用的是相对路径,所以最好把 CubeF1 的Drivers文件夹复制到工程目录下,保持和 CubeMX 生成的结构一致。
// IAR 工程里 main.c 的 HAL 初始化调用和 Keil 一致 // 但 IAR 的启动文件是 startup_stm32f103xb.s,在 Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/iar/ 下 // 这个启动文件需要加到工程里,否则链接会报 __vector_table 未定义4.2 预编译宏和链接器配置
IAR 的预编译宏在 Project -> Options -> C/C++ Compiler -> Preprocessor -> Defined symbols 里设置。和 Keil 一样,需要加USE_HAL_DRIVER和STM32F103xB。IAR 的宏定义区分大小写,STM32F103xB里的xB是小写,写错了会报器件型号不匹配。
链接器配置里,IAR 需要指定.icf文件,这个文件在 CubeF1 的Projects/STM32F103RB-Nucleo/IAR/下有现成的,比如stm32f103xb_flash.icf。这个文件定义了 Flash 和 RAM 的起始地址和大小,F103C8T6 的 Flash 是 64KB,RAM 是 20KB,如果用了 F103RB 的 icf 文件,链接时会报空间不足。
提示:IAR 的
.icf文件里__ICFEDIT_region_ROM_start__和__ICFEDIT_region_ROM_end__决定了 Flash 范围。F103C8T6 的 ROM 结束地址是0x0800FFFF,RAM 结束地址是0x20004FFF。改错这两个值,程序下载后可能跑飞。
4.3 下载调试和 ST-Link 配置
IAR 下载调试用 ST-Link 时,在 Project -> Options -> Debugger 里选 ST-Link,然后在 Download 里勾选Verify download和Use flash loader。Flash loader 的配置文件在 IAR 安装目录的arm/config/flashloader/ST/STM32F1xx/下,如果找不到,说明 IAR 安装时没勾选 STM32F1 的器件支持。
下载前还要确认 ST-Link 的驱动装好了。Windows 下设备管理器里能看到STMicroelectronics STLink dongle才算正常。如果 IAR 报Failed to initialize ST-Link,先拔插一下 USB,再检查 ST-Link 的固件版本,太老的固件需要升级。
# 用 ST-Link Utility 或者 STM32CubeProgrammer 检查芯片连接 # 命令行方式(STM32CubeProgrammer CLI) STM32_Programmer_CLI -c port=SWD -r32 0x08000000 0x10 # 如果能读出芯片 ID 和 Flash 内容,说明硬件连接正常5. 避坑记录:CubeF1 V1.8.0 安装配置里最容易翻车的五个点
5.1 现象:CubeMX 里找不到 V1.8.0 固件包
原因通常是 CubeMX 的固件包仓库缓存里只有旧版,或者手动放的包目录名不对。CubeMX 识别固件包靠的是包内.package.xml里的<version>标签和文件夹名一致。如果文件夹叫STM32Cube_FW_F1_V1.8.0但 xml 里写的是1.7.0,CubeMX 就会忽略它。
解决方法是打开.package.xml确认版本号,然后把文件夹名改成和 xml 里一致。如果 xml 里没有版本号,就从 CubeF1 的官方发布页重新获取完整包。放好之后重启 CubeMX,在 Manage embedded software packages 里点Refresh,V1.8.0 就会出现在列表里。
5.2 现象:Keil 编译报stm32f1xx_hal_conf.h找不到
这个文件不在 HAL 驱动目录里,而是在工程自己的Core/Inc/下。CubeMX 生成工程时会自动生成一份,但如果你是从 CubeF1 的例程里复制工程,例程的Inc/文件夹里也有。手动新建工程时最容易漏掉这个文件。
解决办法是从 CubeF1 的Projects/STM32F103RB-Nucleo/Inc/下复制一份stm32f1xx_hal_conf.h到你的Core/Inc/,然后根据实际用到的外设取消对应的#define注释。比如用到了 GPIO 和 RCC,就保留HAL_GPIO_MODULE_ENABLED和HAL_RCC_MODULE_ENABLED,其他的可以注释掉以减小代码体积。
5.3 现象:IAR 链接报__vector_table未定义
这是因为启动文件没加到工程里,或者启动文件的路径不对。IAR 的启动文件在Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/iar/下,文件名是startup_stm32f103xb.s。Keil 的启动文件在arm/子目录下,两者不能混用。
解决办法是在 IAR 工程里右键 Add -> Add Files,把startup_stm32f103xb.s加进来。如果工程里已经有 Keil 格式的启动文件,先移除再添加 IAR 格式的。添加后在 Project -> Options -> Linker -> Config 里确认.icf文件选的是对应芯片型号的。
5.4 现象:下载后程序不运行,复位后停在 HardFault
这种玄学问题多半是时钟配置和实际晶振不匹配。CubeMX 里默认的 HSE 是 8MHz,但有些板子用的是 12MHz 或 25MHz 晶振。如果SystemClock_Config里按 8MHz 算 PLL,实际晶振是 12MHz,系统时钟就会超频,跑一会儿就进 HardFault。
解决办法是确认板子上的晶振频率,在 CubeMX 的 Clock Configuration 里把 HSE 的值改成实际频率,重新生成代码。如果不确定晶振频率,可以先用 HSI(内部 8MHz RC)跑,在SystemClock_Config里把RCC_OscInitStruct.HSEState改成RCC_HSE_OFF,用 HSI 作为 PLL 源。
5.5 现象:Keil 和 IAR 共用同一份 CubeF1 源码时路径冲突
有些团队为了省空间,让 Keil 和 IAR 工程共用同一份Drivers文件夹。但 Keil 的 DFP 包里也有启动文件和系统文件,如果 Include Paths 里同时包含了 DFP 的路径和 CubeF1 的路径,编译器可能会找到两个版本的system_stm32f1xx.c,导致重复定义。
解决办法是明确分工:CubeF1 提供 HAL 和 CMSIS 核心文件,DFP 只提供 Flash 算法和器件描述。在 Keil 的 Include Paths 里,DFP 的路径放在 CubeF1 路径之后,或者干脆不添加 DFP 的头文件路径,只保留 DFP 的 Flash 算法。IAR 那边同理,只用 CubeF1 的源文件,IAR 自带的器件支持只用于调试配置。
6. 装完怎么验证:从点灯到串口输出的完整检查链
验证 CubeF1 V1.8.0 装没装好,最直接的办法是跑一个 GPIO 点灯加串口输出的最小工程。在 CubeMX 里配置 PA5 为 GPIO_Output(F103C8T6 的板载 LED 通常接 PA5),USART1 为 Asynchronous 模式,波特率 115200。生成代码后,在main.c的while(1)里加这几行:
// 点灯和串口输出验证代码 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 翻转 PA5 HAL_Delay(500); // 延时 500ms printf("CubeF1 V1.8.0 running, tick=%lu\r\n", HAL_GetTick()); // 串口输出printf需要重定向fputc到 USART1,在main.c里加:
// 重定向 printf 到 USART1 int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100); return ch; }编译下载后,如果 LED 以 1Hz 闪烁,串口助手能收到CubeF1 V1.8.0 running和递增的 tick 值,说明 HAL 库、启动文件、时钟配置、外设初始化全部正常。如果 LED 不亮但串口有输出,检查 GPIO 的时钟使能和引脚配置;如果串口没输出但 LED 闪,检查 USART 的波特率和引脚映射。
我一般还会多做一个检查:在stm32f1xx_hal_conf.h里确认HAL_MODULE_ENABLED和实际用到的外设模块一致,然后在 Keil 或 IAR 的 map 文件里看HAL_Init、SystemClock_Config这些函数的地址有没有被正确链接。map 文件里如果出现HAL_GPIO_Init被优化掉的情况,说明HAL_GPIO_MODULE_ENABLED没打开。
从那以后我每次搭 F1 环境,都会先跑这个点灯加串口的验证工程,确认 CubeF1 V1.8.0 的 HAL 层和工具链完全打通,再去动实际项目的业务代码。这个习惯帮我省掉了至少三次因为库版本错位导致的通宵排查。希望帮到你。
本文还有配套的精品资源,点击获取