STM32¶
STM32 是 ST 公司基于 ARM Cortex-M 内核的 32 位微控制器系列,广泛应用于嵌入式开发、机器人控制、物联网等领域。本板块系统梳理 STM32 的核心外设与编程方法。
STM32 是什么?¶
STM32 = ST(意法半导体公司)+ M(Microcontroller,微控制器)+ 32(32 位架构)
它不是一颗芯片,而是一个庞大的产品系列。以最常用的 STM32F103C8T6 为例:
| 字段 | 含义 |
|---|---|
| STM32 | ST 公司的 32 位 MCU |
| F | 基础型(Foundation),还有 L(低功耗)、H(高性能)等 |
| 103 | 系列编号,103 表示增强型,基于 Cortex-M3 内核 |
| C | 48 引脚 |
| 8 | 64KB Flash |
| T | LQFP 封装 |
| 6 | 工作温度范围 -40°C ~ 85°C |
开发板推荐
入门推荐 STM32F103C8T6(蓝色小板 / Blue Pill),便宜好用。进阶推荐 STM32F407 系列,主频更高(168MHz),外设更丰富。
核心架构概览¶
STM32 的内部结构可以抽象为以下几个层次:
graph TB
CPU[Cortex-M 内核 CPU] --> BUS[总线矩阵 Bus Matrix]
BUS --> AHB[AHB 总线]
BUS --> APB1[APB1 总线 低速]
BUS --> APB2[APB2 总线 高速]
AHB --> FLASH[Flash 存储器]
AHB --> SRAM[SRAM 内存]
AHB --> DMA[DMA 控制器]
AHB --> RCC[时钟控制 RCC]
APB2 --> GPIO_A[GPIOA/B/C...]
APB2 --> ADC_M[ADC]
APB2 --> TIM1_M[高级定时器 TIM1]
APB2 --> USART1_M[USART1]
APB2 --> SPI1_M[SPI1]
APB1 --> TIM2_M[通用定时器 TIM2/3/4]
APB1 --> USART2_M[USART2/3]
APB1 --> I2C_M[I2C1/2]
APB1 --> SPI2_M[SPI2]
APB1 --> DAC_M[DAC]
总线层级关系
- AHB(Advanced High-performance Bus):挂载高速外设,如 Flash、SRAM、DMA
- APB2(Advanced Peripheral Bus 2):高速外设总线,挂载 GPIO、ADC、USART1、高级定时器
- APB1:低速外设总线,挂载 I2C、SPI2、通用定时器、DAC
APB1 最高频率是 AHB 的一半。理解总线层级有助于理解时钟分频配置。
开发方式¶
STM32 有三种主流开发方式,各有优劣:
直接操作硬件寄存器,每一位都手动控制。
// 点亮 PC13 上的 LED
RCC->APB2ENR |= (1 << 4); // 使能 GPIOC 时钟
GPIOC->CRH &= ~(0xF << 20); // 清除 PC13 配置
GPIOC->CRH |= (0x3 << 20); // 设置为推挽输出,50MHz
GPIOC->ODR &= ~(1 << 13); // PC13 输出低电平(LED 亮)
优点:效率最高,理解最深
缺点:代码可读性差,开发速度慢
ST 官方提供的 C 语言函数库,对寄存器操作做了一层封装。
// 点亮 PC13 上的 LED
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 输出低电平
优点:代码清晰,学习资料丰富
缺点:ST 已停止更新,新芯片不再支持
建议
推荐使用 HAL 库 + CubeMX,这是 ST 官方主推的开发方式,资料丰富、社区活跃,适合快速开发和学习。本笔记所有代码示例均基于 HAL 库。了解寄存器原理有助于排查问题,但日常开发不必手动操作寄存器。
编程的基本流程¶
使用 HAL 库 + CubeMX 的开发流程如下:
graph LR
A[1. CubeMX 配置<br>引脚/时钟/外设] --> B[2. 生成工程代码]
B --> C[3. 在 USER CODE 区域<br>编写业务逻辑]
C --> D[4. 编译下载调试]
- CubeMX 图形化配置:选型号 → 配置引脚功能 → 配置时钟树 → 配置外设参数 → 配置中断和 DMA
- 生成代码:CubeMX 自动生成初始化函数(
MX_GPIO_Init()、MX_TIM2_Init()等),包含时钟使能、引脚配置、外设配置 - 编写用户代码:在
/* USER CODE BEGIN */和/* USER CODE END */之间写业务逻辑,这样重新生成代码时不会被覆盖 - 编译调试:编译下载到开发板,通过串口/调试器观察结果
CubeMX 重要规则
永远只在 USER CODE 标记区域内写代码! 如果写在标记外面,下次用 CubeMX 重新生成时会被覆盖清除。
存储器映射¶
STM32 采用 统一编址 方式,将 Flash、SRAM、外设寄存器全部映射到 4GB 的地址空间中:
| 地址范围 | 用途 | 说明 |
|---|---|---|
0x0000 0000 ~ 0x07FF FFFF |
启动区域 | 根据 BOOT 引脚映射到 Flash 或 SRAM |
0x0800 0000 ~ 0x0807 FFFF |
Flash | 存放程序代码(掉电不丢失) |
0x2000 0000 ~ 0x2000 FFFF |
SRAM | 运行时变量(掉电丢失) |
0x4000 0000 ~ 0x4002 3FFF |
外设寄存器 | GPIO、USART、TIM 等外设的控制寄存器 |
0xE000 0000 ~ 0xE00F FFFF |
内核外设 | NVIC、SysTick 等 Cortex-M 内核组件 |
理解寄存器地址
当我们写 GPIOC->ODR = 0x0001 时,本质上就是向地址 0x4001 100C 写入数据。标准库和 HAL 库只是帮我们把这些地址定义成了结构体和宏。
内容导航¶
本板块按 STM32 的核心外设模块组织,由浅入深:
| 章节 | 核心内容 | 你将学到 |
|---|---|---|
| 时钟系统 | RCC、时钟树、HSI/HSE/PLL | 理解 STM32 的"心跳",学会配置系统时钟 |
| GPIO | 引脚模式、输入输出、复用 | 点灯、按键检测、理解推挽/开漏 |
| 中断系统 | NVIC、EXTI、中断优先级 | 响应外部事件,理解抢占与响应优先级 |
| 定时器 | 基本/通用/高级定时器、PWM | 精确定时、产生 PWM 波形驱动电机和舵机 |
| 通信协议 | UART、SPI、I2C | 与传感器、模块、PC 进行数据通信 |
| ADC 与 DAC | 模数转换、数模转换 | 采集传感器模拟信号,输出模拟电压 |
| DMA | 直接内存访问 | 不占用 CPU 搬运大量数据,提高系统效率 |