2. 开发环境搭建:Keil MDK安装与破解、STM32CubeMX安装、固件库下载与工程模板建立

做嵌入式开发,第一步就是把家伙事儿备齐。我见过不少新手,上来就急着写代码,结果编译报错半天找不到原因——最后发现是工具链没装对。这一章咱们就把环境彻底捋顺,后面写驱动、调DMA的时候才不会卡在第一步。

2.1 开发工具全景图

先看看咱们这一章要装哪些东西,它们之间是什么关系。说白了,就是三件套:

  • Keil MDK:写代码、编译、调试的IDE,ARM内核的标配工具
  • STM32CubeMX:图形化配置工具,帮你生成初始化代码,省去手写寄存器配置的麻烦
  • 固件库(HAL/LL库):ST官方提供的驱动库,封装了底层寄存器操作

这三者的关系,我画了张图,你看一眼就明白了:

STM32F103 OLED驱动开发工具链 用户应用程序 STM32 HAL / LL 固件库 CMSIS + 硬件寄存器层 STM32F103 硬件 Keil MDK(编译/调试) STM32CubeMX(配置生成) 固件库(HAL/LL)

嗯,这张图你看懂了,后面每一步你都知道自己在干什么。

2.2 Keil MDK安装与破解

Keil MDK是ARM生态里最常用的IDE,没有之一。我最早用IAR,后来转到Keil,说实话,Keil的调试界面更顺手,尤其是看变量和寄存器的时候。

2.2.1 下载与安装

  1. 获取安装包:去Keil官网(www.keil.com)下载MDK-Arm版本。目前主流版本是MDK 5.38或5.39。我个人建议用5.36以后的版本,对STM32F103支持更稳定。
  2. 运行安装程序:双击exe,一路Next。注意安装路径不要有中文,我见过有人装在“D:\开发工具\Keil”这种路径,编译时莫名其妙报错——其实就是中文空格惹的祸。
  3. 选择组件:安装过程中会提示选择要安装的器件支持包。默认全选就行,后面可以单独添加。
注意:安装路径建议用纯英文,比如 C:\Keil_v5。不要用带空格或中文的路径,否则后面调试器驱动可能会出问题。

2.2.2 破解(License激活)

Keil MDK是收费软件,但ST官方提供了免费的License限制版——代码大小限制在32KB以内。咱们做OLED驱动和DMA传输,代码量不大,其实免费版也够用。但如果你后面要做复杂项目,建议还是用破解版。

破解步骤:

  1. 以管理员身份运行Keil MDK
  2. 点击 File → License Management
  3. 复制CID码(一串16进制数字)
  4. 运行注册机(Keygen),粘贴CID,选择Target为ARM
  5. 点击Generate生成激活码,复制回Keil的License窗口
  6. 点击Add LIC,看到提示"License Added Successfully"就OK了
避坑指南:我曾经遇到过破解成功后,编译还是报"License Error"的情况。后来发现是没以管理员身份运行注册机。记住:注册机和Keil都要以管理员身份运行,否则写不到注册表。

2.3 STM32CubeMX安装

STM32CubeMX是ST官方出的图形化配置工具。说实话,早期我都是手写寄存器配置,后来用了CubeMX,真香。尤其是时钟树配置,手写容易算错分频系数,CubeMX帮你自动算好。

2.3.1 安装步骤

  1. 下载:去ST官网搜索"STM32CubeMX",下载最新版。需要注册ST账号,免费。
  2. 安装:解压后运行安装程序,选择安装路径。同样,路径不要有中文。
  3. 安装固件包:首次启动CubeMX时,会提示下载固件包。选择STM32F1系列,下载对应版本。我建议下载HAL库版本,LL库虽然更轻量,但HAL库的兼容性更好。
个人建议:CubeMX的固件包下载速度有时候很慢。你可以去ST官网手动下载固件包,然后放到CubeMX的Repository路径下。路径一般在:C:\Users\你的用户名\STM32Cube\Repository。

2.4 固件库下载与工程模板建立

固件库就是ST官方提供的驱动代码。咱们做OLED驱动,主要用到GPIO、SPI(或I2C)、DMA这几个外设的HAL库函数。

2.4.1 固件库版本选择

固件库版本 特点 适用场景
HAL库 功能完整,移植性好,代码量大 初学者、快速开发、复杂外设
LL库 轻量级,接近寄存器操作,效率高 对性能要求高、资源受限的场景
标准外设库 ST早期库,已停止更新 老项目维护,不推荐新项目使用

咱们这个课程用HAL库。为什么?因为DMA传输涉及中断回调、超时处理,HAL库把这些都封装好了,你只需要关注业务逻辑。LL库虽然快,但你要自己处理中断状态机——嗯,等你把HAL库玩熟了再回头用LL库也不迟。

2.4.2 使用CubeMX生成工程模板

这是咱们后面每章都会用到的操作,我详细说一下:

  1. 新建项目:打开CubeMX,点击"New Project"
  2. 选择芯片:在Part Number搜索框输入"STM32F103C8T6",双击选中
  3. 配置时钟:进入Clock Configuration页面,HCLK输入72,回车,系统自动分配时钟树
  4. 配置外设:在Pinout & Configuration页面,使能你要用的外设(比如SPI1、DMA1)
  5. 生成代码:点击Project → Generate Code,选择Toolchain为MDK-ARM V5
小技巧:生成代码时,CubeMX会问你是否要初始化所有外设。我建议选"Initialize all peripherals",这样生成的main函数里已经包含了外设初始化代码,你直接往里填业务逻辑就行。

2.4.3 手动建立工程模板(备选方案)

有时候你不想用CubeMX,或者项目需要更精细的控制,可以手动建工程。步骤:

  1. 在Keil中新建项目,选择芯片型号
  2. 添加启动文件(startup_stm32f103xb.s)
  3. 添加HAL库源文件(stm32f1xx_hal.c、stm32f1xx_hal_gpio.c等)
  4. 添加系统时钟配置文件(system_stm32f1xx.c)
  5. 配置工程选项:选择C99标准、添加宏定义USE_HAL_DRIVER、STM32F103xB

我个人更推荐用CubeMX生成模板。为什么?因为手动建工程容易漏文件,尤其是DMA相关的文件——我早期就吃过这个亏,编译通过但调试时DMA不工作,查了半天发现是没加stm32f1xx_hal_dma.c。

2.5 验证环境是否搭建成功

装完了,怎么知道好不好使?写个最简单的程序验证一下:

#include "main.h"

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    
    // 点亮PC13上的LED(大部分STM32F103最小系统板都有的板载LED)
    __HAL_RCC_GPIOC_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    while (1)
    {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        HAL_Delay(500);
    }
}

编译通过,下载到板子上,LED以1秒频率闪烁——恭喜你,环境搭建成功了!

常见问题:如果编译报错"Error: L6218E: Undefined symbol SystemClock_Config",说明你没有添加系统时钟配置文件。回到CubeMX重新生成代码,或者手动添加system_stm32f1xx.c文件。

2.6 本章小结

这一章咱们把开发环境彻底搞定了。你手头现在应该有:

  • 一个能编译、能调试的Keil MDK
  • 一个能生成初始化代码的STM32CubeMX
  • 一个基于HAL库的工程模板
  • 一个验证通过的LED闪烁程序