简介:《野火EmbedFire STM32 HAL库开发实战指南—基于F103》面向零基础及入门阶段的嵌入式学习者,围绕STM32F103与意法半导体HAL库展开,帮助读者跨越从寄存器操作到标准化API编程的门槛,建立可移植的嵌入式开发思路。全书从STM32基础概念讲起,依次覆盖KEIL5安装与芯片包配置、DAP仿真器硬件连接与Debug参数设置,再深入到GPIO、中断、定时器、串口、ADC等外设的HAL库配置方法,并以LED闪烁、串口通信及简单控制与数据采集项目收尾,配合技术论坛便于交流答疑。资源为单个PDF文件,压缩包约43.41MB,内容完整、目录清晰,适合按章节顺序系统学习或作为外设配置速查手册。目前已有1883人学习下载,可作为STM32 HAL库入门与实战练习的参考教材。
1. 从一块“点不亮”的 F103 最小系统板说起
上周帮一个做毕业设计的同学收拾烂摊子:板子焊好了,Keil5 装了三遍,DAP 仿真器插上去电脑能认,可一点下载就报 “No Cortex-M Device found”,LED 死活不亮。翻他电脑一看,芯片包装的是 F4 的,工程器件选的是 F103C8,调试器配置里又勾了 SW 却没选具体型号——三个坑叠在一起,玄学都救不了。这类场景太常见了:STM32 HAL 库开发的门槛从来不在写代码,而在环境这一关。这份基于 F103-MINI 的实战指南,配套硬件是野火 F103-MINI 开发板,工具链锁定 Keil5 + DAP 仿真器 + STM32CubeMX,适合刚上手 ARM Cortex-M 的嵌入式和物联网方向开发者。装不好会怎样?编译过了下载失败、下载成功跑飞、串口没输出,每一个都能耗掉一整天。下面按我实际装机的顺序,把版本、参数、验证和翻车后的救法一次讲清。
2. 装 Keil5 与芯片包:版本、路径和器件选型
2.1 先定版本再动手,别拿最新版赌兼容
这套指南成文于 2021 年初,围绕 F103 系列展开,工具链的基准是 Keil MDK5(即 Keil5)。我一般会选 MDK5.2x 这一档的版本,原因是它对 Windows 7/10 都友好,且与指南里提到的 DAP 调试配置、STM32CubeMX 生成的工程兼容性最稳。新版 MDK 不是不能用,但高版本对旧工程、旧芯片包的兼容偶尔会出幺蛾子,新手没必要在这里冒险。
安装包获取走正规渠道:Keil 官网下载 MDK-ARM 安装器,芯片包(Device Family Pack)从 Keil 官方 Pack 页面或 ST 官方渠道拿 STM32F1 系列包。指南里“获取 KEIL5 安装包”一节强调的就是别用来路不明的整合包,我踩过的坑是某些第三方整合包夹带旧版编译器,编译 HAL 库时直接报__weak相关错误。
安装前先确认系统环境,这是很多人忽略的一步:
| 项目 | 建议值 | 说明 |
|---|---|---|
| 操作系统 | Windows 10 64 位 | Win7 可用但部分新版 Pack 安装器要求更高 |
| 安装路径 | 全英文、无空格 | 如D:\Keil_v5,中文路径是编译玄学重灾区 |
| 磁盘空间 | 预留 5 GB 以上 | 芯片包和工程缓存占空间 |
| 权限 | 管理员运行安装器 | 否则 Pack 写入失败 |
2.2 安装 Keil5 的实操步骤
双击安装器后,一路 Next,到选择安装路径时改成全英文目录。安装完成后首次启动会弹 Pack Installer,先别急着关。核心动作是装芯片包,指南第 2.4 节“安装 STM32 芯片包”讲的就是这一步。两种方式我都用过:
# 方式一:Pack Installer 在线安装(推荐,版本自动匹配) # 打开 Keil5 -> Pack Installer -> Packs 标签 # 搜索 STM32F1,找到 Keil::STM32F1xx_DFP,点 Install # 等待下载完成,状态变为 Up to date 即可 # 方式二:离线安装(网络不稳时用) # 下载 Keil.STM32F1xx_DFP.x.x.x.pack 后双击 # 安装器会自动识别已装的 Keil 路径并写入在线安装的好处是版本依赖自动处理;离线包适合内网或网络抖动环境。装完在 Pack Installer 的 Installed 里能看到STM32F1xx_DFP才算成功。这里有个细节:芯片包和器件型号是两回事,包提供的是器件描述、启动文件、Flash 算法,工程里选具体型号(如 STM32F103C8)时才有得选。很多人装完包却在新建工程时找不到 F103,多半是包没装全或 Pack 索引没刷新,重启 Keil 即可。
2.3 新建工程时的器件与运行环境选择
指南第 6 章和第 11 章分别讲了寄存器版和库函数版新建工程,HAL 库路线对应的是后者思路。新建工程时选STM32F103C8(按你板子实际型号),然后在 Run-Time Environment 里勾选 CMSIS 的 CORE 和 Device 的 Startup,HAL 库驱动按需勾选。这里我一般会手动管理库文件而不是全靠 RTE,因为 RTE 勾选多了容易把不用的驱动也编进去,工程臃肿还拖慢编译。
一个容易写错的参数是目标器件的 Flash 大小。F103C8 是 64 KB,如果你在 Debug 配置里把 Flash 算法选成 128 KB 的型号,下载时可能报校验失败。这个参数在 Options for Target → Debug → Settings → Flash Download 里,选错就是“下载成功但跑不起来”的经典原因。
3. DAP 仿真器配置:三个选项页决定能不能下载
3.1 硬件连接与供电确认
指南第 3 章把 DAP 仿真器的连接讲得很细,核心就四根线:SWDIO、SWCLK、GND、3.3V(或目标板自供电时只接前三根)。我习惯先只接 SWDIO、SWCLK、GND 三根,目标板单独供电,避免仿真器供电能力不足导致识别不稳。接线顺序上,先接 GND 再接信号线,热插拔容易把调试口打坏,这是血泪经验。
连接完成后,设备管理器里应能看到 DAP 对应的调试器设备。如果看不到,先换 USB 口、换线,再怀疑驱动。DAP 一般免驱,Windows 10 下即插即用;老系统可能需要装调试器厂商提供的驱动。
3.2 Debug 选项页:选对调试器型号
打开 Options for Target → Debug 标签,这是第一个关键页。Use 下拉框里要选你实际用的调试器,DAP 对应的是CMSIS-DAP Debugger。选完后点旁边的 Settings,进入第二个关键页。
Options for Target -> Debug Use: CMSIS-DAP Debugger Settings -> Debug 标签: Port: SW(不是 JTAG) Max Clock: 1 MHz 起步,稳定后可提到 10 MHz SW Device: 应能自动识别出 ARM CoreSight SW-DPPort 选 SW 是硬性要求,F103 的 DAP 调试走 SWD 两线。Max Clock 我一般从 1 MHz 开始,识别稳定后再往上调;线长、板子布线差的时候高频直接连不上,报 “Cannot access target”。SW Device 区域如果能识别出 IDCODE,说明物理链路通了,这是判断“是线的问题还是配置问题”的分水岭。
3.3 Utilities 与 Flash Download 配置
Utilities 标签页决定下载走哪个工具。勾选Use Debug Driver,让下载复用 Debug 页配置的调试器,省得两处不一致。然后点 Settings 进 Flash Download,确认三件事:
- Programming Algorithm 里要有
STM32F10x Med-density Flash(对应 64/128 KB 的 F103 中容量型号),没有就点 Add 添加; - 勾选
Reset and Run,下载完自动复位运行,省一次手动按复位; Verify建议勾上,下载后校验,能提前发现 Flash 算法不匹配。
参数取舍上,Reset and Run在调试阶段很方便,但如果你在代码里做了特殊的启动延时或外设初始化顺序,自动运行可能掩盖问题,这时可以临时取消勾选,手动复位观察。这是熟手和新手的差别:新手图省事全勾,熟手知道什么时候该关。
3.4 下载验证与首次点灯
配置完成后点 Download(快捷键 F8),Output 窗口出现Programming Done. Verify OK.才算真正下载成功。指南第 12 章“GPIO 输出—使用固件库点亮 LED”是第一个可验证的实验,代码结构大致如下:
/* 基于 HAL 库的 LED 初始化与翻转,对应指南 GPIO 输出章节 */ #include "stm32f1xx_hal.h" int main(void) { HAL_Init(); /* 初始化 HAL 库,配置 SysTick */ SystemClock_Config(); /* 配置系统时钟,指南第 15 章 RCC 内容 */ __HAL_RCC_GPIOB_CLK_ENABLE(); /* 使能 GPIOB 时钟,漏了这句灯永远不亮 */ GPIO_InitTypeDef gpio = {0}; gpio.Pin = GPIO_PIN_0; /* 按板子原理图确认 LED 接在哪个引脚 */ gpio.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */ gpio.Pull = GPIO_NOPULL; gpio.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &gpio); while (1) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); HAL_Delay(500); /* 依赖 SysTick,HAL_Init 里已配好 */ } }这段代码里两个参数最容易翻车:一是__HAL_RCC_GPIOB_CLK_ENABLE(),HAL 库把时钟使能拆成宏,忘了就是“代码没错但引脚无输出”;二是HAL_Delay依赖 SysTick 中断,如果HAL_Init没调或中断被关,程序会卡死在延时里。下载后 LED 以 500 ms 周期闪烁,说明工具链、下载链路、时钟、GPIO 全链路通了,这是最省事的端到端验证。
4. STM32CubeMX 建工程:Java 依赖与代码生成
4.1 Java 环境是前置条件,不是可选项
指南第 10 章开篇就是“安装 Java 软件”,这不是凑字数。STM32CubeMX 是 Java 应用,早期版本对 JRE 版本有明确要求,装错版本会直接闪退或界面空白。我一般装 JRE 8(1.8)这一档,兼容性最广。安装后验证:
# 命令行验证 Java 是否可用 java -version # 期望输出类似: # java version "1.8.0_xxx" # Java(TM) SE Runtime Environment如果提示“不是内部或外部命令”,说明 JAVA 的 bin 目录没进 PATH,手动加系统环境变量即可。这一步翻车的典型现象是 CubeMX 双击没反应,任务管理器里进程一闪而过,八成就是 Java 没配好。
4.2 CubeMX 新建工程的配置顺序
CubeMX 装好后,新建工程的顺序指南写得很清楚:选 CPU 型号 → 确认时钟源 → 配置 IO → 配系统时钟 → 配 IO 具体属性 → 配工程属性 → 生成代码。这个顺序不能乱,尤其是时钟树要在 IO 配置之后、生成代码之前调,否则外设时钟分频对不上。
关键参数我列一下,都是生成代码时会写进SystemClock_Config的:
| 配置项 | F103-MINI 常用值 | 影响 |
|---|---|---|
| HSE | 8 MHz 晶振 | 外部高速时钟源,板载晶振频率要对上 |
| PLL 倍频 | ×9 | 8 MHz × 9 = 72 MHz 系统主频 |
| AHB 分频 | /1 | 72 MHz |
| APB1 分频 | /2 | 36 MHz,F103 的 APB1 上限 |
| APB2 分频 | /1 | 72 MHz |
| Debug | Serial Wire | 保留 SWD 调试口,别选 Disable |
APB1 超过 36 MHz 是 F103 的硬限制,CubeMX 里如果配错会标红,但有人强行生成后外设行为异常,查半天查不到原因。工程属性里 Toolchain/IDE 选 MDK-ARM,版本号和你装的 Keil 对上,生成后直接打开就能编译。
4.3 生成代码后的用户代码区约定
CubeMX 生成的代码里有/* USER CODE BEGIN */和/* USER CODE END */成对注释,用户代码必须写在这两个标记之间,否则下次重新生成会被覆盖。这是 CubeMX 工作流的核心纪律,我见过有人把业务逻辑写在标记外面,改一次配置全没了,只能重写。生成后先编译一次空工程,确认 0 error,再往里加测试代码,把“工具链问题”和“业务代码问题”分开定位。
5. 避坑与排查:五个高频翻车现场
5.1 下载报 “No Cortex-M Device found”
现象:点下载,Output 窗口直接报找不到设备,Debug Settings 里 SW Device 区域空白。
原因:物理链路或调试口配置问题。常见的有 SWDIO/SWCLK 接反、目标板没供电、Port 选成了 JTAG、Max Clock 太高。
解决:先量目标板 3.3V 是否正常,再把 Port 改回 SW、时钟降到 1 MHz 重试。还不行就检查芯片是否被读保护,用 ST-LINK Utility 之类的工具解保护后再试。这一步能解决八成“找不到设备”。
5.2 编译报错找不到stm32f1xx_hal.h
现象:工程能打开,一编译满屏cannot open source input file。
原因:HAL 库驱动文件没加进工程,或头文件包含路径没配。CubeMX 生成的工程一般不会出这问题,手动建工程时最容易漏。
解决:在 Options for Target → C/C++ → Include Paths 里补上 HAL 库的Inc目录,并在工程树里把Src下的.c文件加进来。我一般会对照 CubeMX 生成的标准工程结构逐项核对,缺什么补什么,比盲猜快。
5.3 下载成功但程序不跑
现象:Output 显示 Programming Done,但 LED 不闪、串口无输出。
原因:Flash 算法选错(容量不匹配)、没勾 Reset and Run、启动文件不对、时钟配置错误导致程序卡在时钟初始化。
解决:先确认 Flash Download 里的算法和芯片容量一致;再手动按复位键看是否运行;仍不行就用调试器单步,看程序停在哪。卡在SystemClock_Config里等 HSE 就绪,多半是晶振没起振或频率配错。
5.4 CubeMX 生成代码覆盖用户逻辑
现象:改完 CubeMX 配置重新生成,之前写的业务代码没了。
原因:代码写在了USER CODE标记之外。
解决:养成习惯,所有用户代码只写在成对标记之间。已经丢了的只能从版本管理里找,所以工程一建好就纳入 git,这是后悔药。
5.5 串口乱码或没输出
现象:串口助手收到乱码,或干脆收不到数据。
原因:波特率不匹配、系统时钟配错导致实际波特率偏移、TX/RX 接反、没使能串口时钟。
解决:先核对波特率和时钟树,F103 在 72 MHz 下配 115200 是常规操作;再查接线,TX 接 RX 是常识但每次都有人接错;最后确认__HAL_RCC_USART1_CLK_ENABLE()有没有调。乱码优先怀疑时钟,没数据优先怀疑接线和时钟使能。
6. 装完怎么验证:一套五分钟跑通的检查清单
环境装完别急着写业务,先按这套清单走一遍,能把问题挡在写代码之前。我现在的习惯是每台新机器配完环境,都强制跑一遍这个流程,省得后面调试时分不清是环境问题还是代码问题。
第一步,编译验证。打开指南配套的 GPIO 点灯工程或 CubeMX 生成的空工程,全编译一次,确认 0 error 0 warning(warning 里如果有未使用变量可以忽略,但涉及类型转换的要看一眼)。编译不过说明工具链或库路径有问题,回到第 2 章核对。
第二步,下载链路验证。Debug Settings 里确认 SW Device 能识别 IDCODE,Flash Download 里算法和容量匹配,点下载看到Verify OK。这一步过了,说明仿真器、接线、Flash 算法全对。
第三步,运行验证。下载后 LED 按预期闪烁,或用调试器打断点能停在main里。如果 LED 不亮但下载成功,按 5.3 排查。
第四步,外设链路验证。接串口,用指南第 13 章按键检测或串口通信的例子,确认能收到数据且不乱码。串口通了,说明时钟树、GPIO 复用、中断配置这一整条链路是通的。
第五步,重新生成验证。用 CubeMX 改一个无关紧要的配置(比如改个引脚标签),重新生成代码,确认用户代码区没被覆盖、工程仍能编译下载。这一步验证的是工作流纪律,比单次跑通更重要。
| 验证项 | 通过标准 | 失败先查 |
|---|---|---|
| 编译 | 0 error | 库路径、芯片包 |
| 下载 | Verify OK | 调试器配置、Flash 算法 |
| 运行 | LED 闪烁 | 时钟、GPIO 时钟使能 |
| 串口 | 数据正确不乱码 | 波特率、接线、时钟 |
| 重生成 | 用户代码保留 | USER CODE 标记 |
这套清单跑完,F103 + HAL 库 + Keil5 + DAP 这条链路就算真正落地了。从那以后我每次给新板子配环境,都强制走一遍这五步,宁可花五分钟,也不愿在业务代码里跟环境问题纠缠一整天。希望帮到你。
本文还有配套的精品资源,点击获取