01-环境搭建.md 6.4 KB

01 环境搭建(HAL 库)

STM32F103C8T6 | CubeMX → Keil MDK → DAP-Link

开发流程总览

flowchart LR
    A["CubeMX<br/>图形化配置"] --> B["生成代码<br/>MDK-ARM Project"]
    B --> C["Keil MDK<br/>编辑/编译"]
    C --> D["DAP-Link<br/>烧录"]
    D --> E["调试<br/>(Debug/串口)"]
    E -.->|修改代码| C
    E -.->|改配置| A

详细工作原理

ARM Cortex-M3 上电启动流程

STM32F103 采用 Cortex-M3 内核,上电复位后固件执行顺序如下:

Reset Vector (0x0000_0004) → SystemInit() → __main() → main()
  1. 复位后内核从 0x0000_0000 读取栈顶指针(MSP),从 0x0000_0004 读取复位向量地址并跳转。
  2. SystemInit():由 CMSIS 库提供,配置 Flash 预取缓冲区、设置系统时钟(HSI → PLL → HCLK/PCLK1/PCLK2),初始化 VTOR(向量表偏移寄存器)。
  3. __main():C 运行时初始化(非 main 函数),包括 ZI 区清零、RW 区复制、堆栈初始化、调用 __rt_entry 进入 C 环境后调用 main()
  4. main():用户代码入口。

启动文件 startup_stm32f103xb.s 关键内容:

  • 栈(Stack)设置:定义 Stack_Size(默认 0x400 = 1KB),在 RAM 末尾分配栈空间,初始化 MSP。
  • 堆(Heap)设置:定义 Heap_Size(默认 0x200 = 512B),供 malloc 等动态分配使用。
  • 中断/异常向量表:从 0x0000_0000 开始依次存放堆栈指针、Reset_Handler、NMI_Handler、HardFault_Handler 等。每个向量占 4 字节(函数地址)。
  • Reset_Handler:调用 SystemInit__main,最终跳转到 main

SWD 必须使能的原因

STM32F103 复位后,PA13(SWDIO)/ PA14(SWCLK)默认功能为 JTAG/SWD 调试接口。若 CubeMX 中 SYS → Debug 不设为 Serial Wire,这两引脚会被初始化为普通 GPIO,之后调试器无法连接芯片,俗称"锁死"。

PB3(JTDO)/ PB4(NJTRST)同样复用为 SWO 等功能。因此所有使用 SWD 调试的项目必须在 CubeMX 中显式开启 Serial Wire(SWD)。

3 种启动模式(BOOT0 / BOOT1)

启动模式

BOOT0 BOOT1 启动区域 地址映射 典型用途
0 X Flash 主存 0x0800_0000 ~ 0x0801_FFFF(128KB) 正常运行
1 0 System Memory 0x1FFF_F000 ~ 0x1FFF_F7FF(内置 Bootloader) 串口 ISP 下载
1 1 SRAM 0x2000_0000 ~ 0x2000_4FFF(20KB) 调试/测试
  • Flash 启动(默认):代码直接从 0x0800_0000 执行,但 Cortex-M3 复位后从 0x0000_0000 取向量——因此 STM32 通过 Flash 地址别名映射将 0x0800_0000 映射到 0x0000_0000。
  • System Memory 启动:进入内置 Bootloader(USART1/USART2/USB DFU),可用串口线通过 ISP 协议擦除/下载 Flash。芯片"锁死"时的救命通道。
  • SRAM 启动:用于调试时将程序直接加载到 RAM 运行,不占用 Flash 写入寿命。

工具链角色

工具 在流程中的角色
STM32CubeMX 图形化配置引脚、时钟、外设参数,生成 HAL 初始化 C 代码
Keil MDK 编辑代码、交叉编译(ARMCC/CLANG)、烧录、调试
DAP-Link / ST-Link SWD 协议调试器,物理连接 PC USB ↔ 开发板 SWDIO/SWCLK
串口助手 通过 USB-TTL 查看 MCU 串口输出的调试信息

CubeMX 生成基础工程

  1. 打开 CubeMX → New Project
  2. MCU Selector → 搜索并选中 STM32F103C8T6
  3. System Core → SYS → Debug → 设为 Serial Wire (SWD)
    • ⚠️ 这一步必须做!否则烧录一次后 SWD 引脚被 GPIO 占用,芯片永久锁死,只能用串口 ISP 擦除
  4. System Core → RCC → HSE → 设为 Crystal/Ceramic Resonator
  5. 时钟树暂时保留默认(HSI 8MHz),第 08 节专门讲 72MHz 配置
  6. Project Manager → Project 标签页:
    • Project Name:LED_Test
    • Toolchain / IDE:MDK-ARM (Keil)
    • Minimum Firmware Version:不影响功能,选最新
  7. GENERATE CODE → 选择目录 → 生成后选择 Open Project 直接启动 Keil

ARMCC 编译器说明

CubeMX 生成 Keil 工程时默认使用 ARMCC V6(即 ARMCLANG)。如果你需要使用老版 V5 编译器(某些旧驱动库只支持 V5):

  1. 将 ARMCC V5.06 目录复制到 Keil 的安装目录(ARMCC 需要单独从 Keil 官网下载)
  2. Keil 中 Project → Manage → Project Items
  3. 在 Folder 视图顶部的 ARM Compiler 下拉框中新增 V5.06 路径
  4. 选中新加的 V5.06 → 重新编译
  5. ⚠️ 若首次配置编译报错,再走一遍上述流程即可通过(常见 bug,原因未知)

如果你的工程使用 CubeMX 默认的 ARMCLANG(V6),不需要任何额外配置。

烧录配置(每次新建工程需配置一次)

  1. Options for Target (Alt+F7) → Debug 标签
  2. 右侧 Use 下拉选择 CMSIS-DAP Debugger
  3. 点击 Settings → 如果 DAP 已正确连接,SWD 设备列表里应该能识别到
  4. 切换到 Flash Download 标签 → 勾选 Reset and Run(烧录后自动复位运行)
  5. 烧录:Flash → Download (F8)

如果 Settings 里没识别到 DAP:检查 SWDIO/SWCLK/GND 三根线是否正确连接,重新插拔 USB

调试功能(Keil Debugger)

  1. Options for Target → Debug → 确认已选 CMSIS-DAP
  2. Debug 标签 → 在右下角关闭编译器优化:-O0(否则变量值和单步行为不准确)
  3. Start/Stop Debug Session (Ctrl+F5) 进入调试模式
  4. 添加 Watch 窗口:View → Watch → Watch1
  5. 在 Watch 窗口输入变量名即可实时查看和修改变量
  6. 常用调试操作:全速运行 (F5)、单步进入 (F11)、单步跳过 (F10)、跳出 (Ctrl+F11)、下断点 (单击行号左侧)

常见问题

问题 原因 解决方法
烧录后无法识别 DAP 接线松动或芯片进入低功耗 重新插拔 USB,检查 SWD 接线
芯片锁死 "No target connected" SWD 引脚被 GPIO 占用 按住复位键 → 点烧录 → 松开复位
编译报错 "..\*.h: No such file" Include Paths 配置丢失 CubeMX 重新生成,或在 Options → C/C++ → Include Paths 中手动添加
串口输出乱码 波特率不一致 确认 MCU 和串口助手都设成了相同波特率(如 115200)