简介《野火 EmbedFire STM32 HAL 库开发实战指南—基于 F103》PDF 教程面向零基础或刚接触 ARM Cortex-M 内核的嵌入式学习者围绕意法半导体 HAL 库的标准化 API 展开帮助读者从开发环境搭建走到外设驱动与项目实践降低 STM32 入门门槛。全书按学习路径编排先说明本书用法与配套硬件再依次讲解 KEIL5 安装与 STM32 芯片包配置、DAP 仿真器的硬件连接与 Debug、Utilities 参数设置、程序下载随后进入 STM32 基础概念与 HAL 库对 GPIO、中断、定时器、串口、ADC 等外设的配置方法并以 LED 闪烁、串口通信、数据采集等实战项目收束附带技术论坛交流渠道。资源为单个 PDF 文件压缩包约 43.41MB章节编号与目录完整便于按模块检索或打印查阅。目前已有 1881 人学习下载适合配合野火 F103-MINI 开发板边读边练逐步建立可移植的 HAL 库编程思路与调试习惯。1. 从一块 F103-MINI 说起HAL 库环境装不对例程一行都跑不起来很多人入门 stm32 arm hal库 的第一块板子就是 F103-MINIKeil5 装上、CubeMX 一点、例程编译一下看着像十分钟能收工的活。真实情况是卡住人的地方从来不在 HAL 库的 API 上而在装环境这一步——器件包没装、宏写成了STM32F103xB却拿着 256KB 板子的启动文件、DAP 仿真器在 Debug 页选成了别的下载器于是编译报错、下载失败、灯不亮一条条全冒出来。这套环境本身不复杂Keil MDK5 加 STM32F1 器件支持包、STM32CubeMX 加 Java 运行环境、一个 CMSIS-DAP 仿真器三样对齐就能跑通。难的是版本和参数对不上时没人告诉你错在哪报错信息还经常指错方向。下面按我实际装机的顺序走一遍从装包到点灯每一步都留了能回退的检查点。2. 装 Keil MDK5 与 F1 器件包安装路径和器件支持决定能不能编译2.1 安装包版本、路径和权限先明确要装的是两样东西MDK-ARM 5.x 主程序和 STM32F1 系列的器件支持包DFP。版本上不用追最新Keil5 各小版本对 F1 系列的支持差异很小反倒是新版本默认把编译器换成了 ARM Compiler 6而野火那批例程是按 AC5 写的直接编译会冒出一堆语法层面的报错。装 MDK5.2x 这一档默认带 AC5最省事如果机器上只有 5.36 之后的版本得单独补装 Legacy 支持包。路径上有两个硬要求不要装在C:\Program Files或Program Files (x86)下面UAC 会拦住器件包解压和 Flash 算法的写入不要带中文和空格。我一般直接装D:\Keil_v5工程目录也一并放在英文路径下。# 安装前先把目录建好别让安装器一半装 C 盘一半装 D 盘 mkdir -p /d/Keil_v5 mkdir -p /d/STM32Cube/Repository第一行是主程序和器件包的根目录第二行是 CubeMX 存固件包的仓库第 3 章会用到。Windows 下用 Git Bash 就写/d/这种形式用 cmd 就写D:\Keil_v5。安装器里会问 Core Components 和 Pack 两个路径都指到D:\Keil_v5下面。分着装的后患是重装系统时器件包全丢工程打开一片红还得重新对一遍版本。2.2 主程序安装与授权L250 这道坎绕不过去安装过程基本是一路下一步中间只在那两个路径处停一下。装完第一次打开会弹 License Management 窗口这一步必须处理掉。Keil 评估版有 32KB 代码限制。HAL 库工程空着就有十几 K加上 GPIO、串口和 printf 重定向很容易顶到上限链接阶段直接给你一句*** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED这个报错跟代码质量没关系是授权状态不对改代码改到天亮也没用。常见做法是通过官方渠道获取正式授权或者确认自己手上是合法授权的版本。这一步别想着绕过去省下来的时间后面会加倍还回去——我见过有人在链接选项里反复调优化等级、删 printf折腾一下午最后发现问题根本不在代码里。装完之后顺手确认一下编译器Project → Manage → Project Items → Folders/Extensions 里能看到 ARM Compiler 的版本5.x 那一档是我们要的。2.3 装 STM32F1 器件支持包没有器件包Options for Target 的 Device 页里根本搜不到 STM32F103工程都建不起来。两种装法在线装。打开 Pack Installer切到 Packs 标签左边展开 Keil找到Keil::STM32F1xx_DFP点右边的 Install等右下角进度条走完。网络不稳的时候会卡在 Downloading 半天不动重开一次 Pack Installer 就行。离线装。拿到.pack文件直接双击安装器会自己找 Keil 的安装路径也可以在 Pack Installer 里 File → Import 导入。装完验证两点D:\Keil_v5\ARM\PACK\Keil\STM32F1xx_DFP\下面应该出现一个2.x.x版本的文件夹进去之后能看到Device和Flash两个子目录。Flash里面那些.FLM文件就是下载算法后面第 4 章挂 Flash 算法时用的就是它们很多人下载失败根子在这一步没装全。2.4 装完先自检空工程编译过再碰例程顺序是这样Project → New μVision Project → 选一个英文目录 → Device 页输入STM32F103RC选中对应型号 → 弹出 Run-Time Environment 窗口勾上 CMSIS 分组里的 CORE 和 Device 分组里的 Startup → OK → 直接 Build。目标很明确Build Output 里出现0 Error(s), 0 Warning(s)再往下走。这一步看着多余作用是先把“装环境的问题”和“例程的问题”隔开。空工程都编不过说明是 Keil 本体或者器件包的问题别去例程里翻空工程能过、例程编不过问题范围就缩到宏定义和头文件路径上直接对应第 4 章那几行配置。装环境最怕的就是一上来拿例程试报错几十条分不清哪条是真问题。3. STM32CubeMX 与 Java 环境从选型到生成一份能编译的 HAL 工程3.1 Java 运行环境先确认 JRE再装 CubeMX老版 CubeMX 本质是个 Java 程序启动时找不到 JVM 就一声不响——双击图标转两圈没了连报错窗口都不给。这种黑匣子现象最浪费时间因为你连往哪个方向查都不知道。java -version # 期望看到类似输出重点是 1.8 这一档 # java version 1.8.0_xxx # Java(TM) SE Runtime Environment (build 1.8.0_xxx-bxx) # Java HotSpot(TM) 64-Bit Server VM要的是 Java 8 这一档1.8 就是 Java 8。装 11 或 17 上去老版本 CubeMX 可能起不来。新版 6.x 的安装包已经自带 JRE先直接装 CubeMX能起来就不用管 Java起不来再回头补 JRE 8。补装之后要重开一个终端再执行一次java -version环境变量没生效的话检查系统变量 Path 里有没有%JAVA_HOME%\bin改完重启终端别在旧窗口里反复试。3.2 新建工程与选型型号、封装、宏三者必须对上打开 CubeMX → New Project → 在 Commercial Part Number 里输入型号。以板子丝印为准F103-MINI 常见的是STM32F103RCTxLQFP64 封装。选中之后右侧会显示 Flash 大小和引脚数这两个数字要跟丝印对得上再往下走。型号不只是个名字它决定了后面两件事代码里写哪个宏Keil 里挂哪个启动文件。搞错了会掉进最难查的那类问题——能编译、能下载、一运行就跑飞。型号Flash容量等级工程宏启动文件STM32F103C8T664KB中容量STM32F103xBstartup_stm32f103xb.sSTM32F103RCT6256KB大容量STM32F103xEstartup_stm32f103xe.sSTM32F103ZET6512KB大容量STM32F103xEstartup_stm32f103xe.s表里的宏不是随手写的。HAL 库的寄存器定义文件靠它挑对应型号的寄存器映射和外设数量写小了256KB 的板子写成STM32F103xB编译器认定的 Flash 和 RAM 都比实际小越过边界的那部分变量会在链接时被裁掉运行起来就是随机异常。启动文件同理它决定了中断向量表有多长。3.3 时钟树HSE 8MHz 走 PLL 到 72MHz要改两处。Pinout Configuration → System Core → RCC → High Speed Clock (HSE) 选Crystal/Ceramic Resonator对应板载那颗 8MHz 无源晶振。然后切到 Clock Configuration 页Input frequency 填 8PLL Source Mux 选 HSEPLLMul 选 ×9System Clock Mux 选 PLLCLKAHB Prescaler 保持 /1得到 72MHzAPB1 Prescaler 选 /2得到 36MHzAPB2 Prescaler 保持 /1也是 72MHz。注意 APB1 的上限是 36MHz超了 CubeMX 会把那个框标红。这条限制跟串口直接相关USART1 挂在 APB2 上USART2/3 挂在 APB1 上波特率算出来不对、串口助手收一堆乱码十有八九是这两条总线频率和你以为的不一样。板子上要是没焊外部晶振就把 HSE 换成 HSI。内部 RC 也是 8MHz走 PLL 最高只能到 64MHz而且精度差高波特率下容易出错。用内部时钟先把程序跑起来可以长期用还是老老实实接晶振。3.4 工程属性与代码生成选项Project Manager 页有几项要手动确认Project Name 和 Project Location 全英文、无空格Toolchain/IDE 选MDK-ARMVersion 选V5选成 V4 生成的工程 Keil5 打不开选成别的 IDE 后面第 4 章的配置项名字都不一样。Code Generator 标签里勾两个Copy only the necessary library files——固件包只复制用到的.c工程体积小也不会在 Keil 里把一堆没用到外设的文件全编进去。Generate peripheral initialization as a pair of .c/.h files per peripheral——每个外设的初始化单独成文件后面手动改参数不用在 main.c 里翻。改完点 GENERATE CODE弹窗里点 Open ProjectKeil 会自己把工程拉起来。3.5 生成出来的工程Core 和 Drivers 两层打开之后工程树大概是这个结构Core/ Inc/ main.h、stm32f1xx_hal_conf.h、外设头文件 Src/ main.c、stm32f1xx_it.c、stm32f1xx_hal_msp.c、时钟配置 Drivers/ STM32F1xx_HAL_Driver/ HAL 库源码 CMSIS/ 内核与设备头文件 MDK-ARM/ .uvprojx 工程文件main.c里凡是夹在/* USER CODE BEGIN */和/* USER CODE END */之间的代码重新生成不会被覆盖写在这两行外面的下次点 GENERATE CODE 就没了。这条规矩从第一天就得当回事我在第 6 章写点灯代码时会严格放在用户区里。另外注意stm32f1xx_hal_conf.hHAL 库的各个外设模块靠里面的宏开关控制编不编进来。工程里明明加了串口代码却报HAL_UART_Init未定义就是这里的HAL_UART_MODULE_ENABLED没打开。4. HAL 工程的目标配置宏、头文件路径与 DAP 下载三件套4.1 C/C 页的宏USE_HAL_DRIVER 和型号宏Options for Target → C/C 标签 → Define 一栏USE_HAL_DRIVER, STM32F103xE第一项是 HAL 库的总开关。没有它stm32f1xx.h里根本不会把 HAL 的头文件包含进来编译直接报一堆类型未定义。第二项是型号宏跟第 3 章那张表里的一列对齐。两个宏之间用英文逗号分隔不要加分号不要加引号。写成STM32F103xE;这种Keil 会把分号当成宏名的一部分等于没定义报错信息还特别模糊。CubeMX 生成的工程这两行是自动写好的只有像书里第 11 章那样手工建库函数版工程时才需要自己填。同一页下面的 Optimization 先保持-O0或-O1。调-O3之后单步调试会跳行变量被优化掉看不到值调不通的时候先把优化关掉再说话。4.2 Include Paths五条路径缺一条就是一堆 cannot openC/C 页的 Include Paths 里以 MDK-ARM 目录为基准这五条必须存在..\Core\Inc ..\Drivers\STM32F1xx_HAL_Driver\Inc ..\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy ..\Drivers\CMSIS\Device\ST\STM32F1xx\Include ..\Drivers\CMSIS\Include第一条给main.h、stm32f1xx_hal_conf.h第二条给stm32f1xx_hal_gpio.h这些外设头文件第三条是旧版 API 的兼容层用到早期__HAL_风格之外的函数时才会命中留着不占地方后两条分别给设备头文件和core_cm3.h这类内核头文件少了它们报的是 CMSIS 层的错跟 HAL 一点关系都没有。排查有个笨办法但特别快报错信息cannot open source input file后面跟的那个文件名去Drivers目录下搜一遍它在哪个文件夹把那个文件夹加进 Include Paths比对着教程一行行抄路径靠谱得多。4.3 Debug 页CMSIS-DAP 的三项配置书里第 3 章讲 DAP 仿真器配置落到 Keil 里就是三处。Options for Target → Debug 标签Use 下拉选CMSIS-DAP Debugger然后点右边的 Settings。弹出的窗口里 Port 选SW不要选 JTAGMax Clock 先降到 1MHz。左边 SW Device 框里应该能看到 IDCODE 和 Device Name看到这两行才算握手成功。这一页是空的后面全是白搭。空的时候按顺序查三件事板子有没有独立供电、SWDIO / SWCLK / GND 三根线有没有接反板子上都有丝印别信杜邦线的颜色、上一次调试是不是没正常退出导致调试口被占用。实在连不上把 Max Clock 降到 100kHz 再试一次线长一点的时候这个很管用。接着切到 Flash Download 标签勾上Reset and Run这样下载完程序自己就跑起来不用手动按复位。Programming Algorithm 里点 Add按容量等级选算法64KB / 128KB 的中容量型号 →STM32F10x Med-density Flash256KB / 512KB 的大容量型号 →STM32F10x High-density Flash算法选错的表现很典型进度条走到一半停住报Cannot access target或者Programming error 0x08000000看着像硬件坏其实是算法地址范围跟芯片对不上。4.4 Utilities 页别让它去调别的下载器Utilities 标签页跟 Debug 页必须是同一个调试器。勾Use Debug Driver和 Debug 页保持一致勾Update Target before Debugging避免下载进去的还是上一版程序在跑。这一页最容易出的问题是Debug 页改成了 DAPUtilities 页还停在 ULINK 或 J-LINK点下载走的是另一条通路报错信息跟仿真器本身完全对不上。有人在接线和驱动上折腾一晚上最后发现就是这两页不一致。4.5 启动文件与向量表型号对不上就是 HardFault工程树里启动文件叫startup_stm32f103xe.s跟第 3 章表里的型号宏一一对应两个必须同时改。大容量板子挂了中容量的启动文件中断向量表只覆盖到中容量那部分外设一开定时器中断或者串口中断中断号越界程序直接跳到HardFault_Handler里死循环。这个现象特别迷惑main 里的代码一行没执行错就是灯不亮。还有一处system_stm32f1xx.c里的VECT_TAB_OFFSET一般保持0x0。做 IAP 或者带 bootloader 的工程才需要改改了但没配套调整分散加载文件程序会从错误的地址取向量表表现同样是 HardFault。新手阶段别碰这个宏。5. 装完最容易翻车的五处按现象、原因、解决逐条排查5.1 编译阶段的两条头文件找不到、代码超限现象一cannot open source input file stm32f1xx_hal.h: No such file or directory原因有两种。一种是 Include Paths 里漏了..\Drivers\STM32F1xx_HAL_Driver\Inc另一种是手工建工程时压根没把 HAL 库源码复制进工程目录路径写了但目录是空的。解决先按 4.2 把五条路径补齐。补完还报就去工程目录下看Drivers\STM32F1xx_HAL_Driver\Inc里到底有没有文件空的就回 CubeMX 重新 GENERATE CODE并确认勾了 Copy only the necessary library files。从别处拷来的例程最容易出这个问题——对方的目录结构和你本地的不是一回事。现象二*** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED原因就一个Keil 评估版 32KB 上限。HAL 库工程本身就大加个串口和 printf 轻松超线。解决File → License Management 看授权状态走正规渠道处理。别在这上面折腾编译优化和裁剪代码那只是把问题往后拖等工程再大一点照样撞墙。5.2 下载阶段的两条仿真器连不上、Flash 算法不对现象三No Cortex-M Device found in JTAG chain或RDDI-DAP Error原因通常是三个SWD 接线有问题SWDIO、SWCLK、GND 三根必须接有的板子还要接 3.3V 参考电压Port 还停在 JTAG 没切成 SW调试时钟太快杜邦线稍微长一点就握手失败。解决Port 改 SWMax Clock 从 1MHz 甚至 100kHz 起步能连上再往上加接线按板子丝印一对一核对。还连不上就按一下板子复位再点下载或者把 Utilities 页的 Update Target before Debugging 取消试一次这个选项在某些板子上反而会干扰连接。现象四Programming error 0x08000000或Cannot access target原因Flash 算法跟芯片容量等级不匹配或者芯片被读保护了下载器读不到 Flash。解决按 4.3 换成对应容量等级的算法。如果是读保护用 STM32CubeProgrammer 连一次做全片擦除把保护解除再回 Keil 正常下载。这一步会把芯片里原有程序清掉心里有数再动手。5.3 运行阶段的一条下载成功但灯不亮现象五下载显示成功复位后没反应调试器一挂上去就停在HardFault_Handler原因有三种常见情况。一是宏定义和启动文件跟实际型号不匹配这是最高频的二是中断服务函数重名——HAL 库的回调机制下中断里应该调HAL_XXX_IRQHandler业务逻辑写在HAL_XXX_Callback里自己又照着手册写一遍同名中断函数链接时不一定报错运行时行为就乱了三是自己写了SystemInit或HAL_Init的替代实现把原来的覆盖掉。解决先对着第 3 章那张表核宏和启动文件两分钟能排掉大半再看stm32f1xx_it.c里的中断函数有没有重复定义最后在HardFault_Handler里打断点看 LR 寄存器和栈里的返回地址能直接定位到出事的那行代码。这一招比盲猜快得多值得提前学会。6. 装完怎么验证编译产物、下载日志和板子上那盏灯环境装没装好不看 Keil 有没有打开看三样东西。第一样是编译产物。Build 一次之后MDK-ARM目录下应该有.axf和.hexBuild Output 里那行Program Size: Codexxxx RO-dataxxx RW-dataxxx ZI-dataxxx的四个数字都不为 0。Code 是 0 说明工程里一个.c都没参与编译多半是文件没加进 Target跟环境无关但同样跑不起来。第二样是下载日志。点完 DownloadBuild Output 底部应该依次出现Erase Done、Programming Done、Verify OK、Application running ...。四行齐了才算真的写进 Flash只出现前两行、卡在 Verify回去看 4.3 的算法选择。第三样是板上现象。在main.c的/* USER CODE BEGIN 3 */和/* USER CODE END 3 */之间写点灯/* USER CODE BEGIN 3 */ while (1) { HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); /* 翻转 LED 引脚电平 */ HAL_Delay(500); /* 依赖 SysTick 的毫秒延时 */ } /* USER CODE END 3 */HAL_GPIO_TogglePin的两个参数来自 CubeMX 生成的宏定义引脚在 GPIO 配置里标了 User Label 之后才会有LED_G_Pin这种名字HAL_Delay的节拍来自 SysTick时钟树没配对的话500ms 会变成 300ms 或 700ms肉眼看不出来但用示波器一量就露馅。三步对照着看定位很快检查项正常表现异常指向编译产物有 .axf/.hexProgram Size 四项非 0文件没加进 Target或宏缺失下载日志四行全过Application runningFlash 算法、读保护、接线板上现象LED 按 500ms 稳定翻转时钟配置、启动文件、中断冲突想再验一步就把串口带上CubeMX 里开 USART1波特率 115200在 while 循环里加一句HAL_UART_Transmit(huart1, (uint8_t *)ok\r\n, 4, 100);串口助手里连续收到ok说明时钟和总线频率都对收到乱码就回去查 APB2 是不是 72MHz、HSE 是不是真的起来了。从那以后我每次装完这套环境都强制走一遍“空工程编译 → 点灯 → 串口发一行”这三步一步不过就不往下看例程。装环境这事没有后悔药前面少验一步后面就得拿半天去猜是代码问题还是配置问题。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?