01-环境搭建
STM32 简介
| 项目 |
参数 |
| 内核 |
ARM Cortex-M3 (ARMv7-M) |
| 主频 |
72MHz (HSE 8MHz PLL 9倍频) |
| SRAM |
20KB |
| Flash |
64KB |
| 封装 |
LQFP48 |
| 电压 |
2.0V~3.6V (典型 3.3V) |
| 温度 |
-40℃~+85℃ |
Cortex-M3 特性:Thumb-2 指令集、硬件乘除法、64MHz→72MHz PLL、位带操作、SysTick 定时器、NVIC 中断嵌套。
片上外设总览
graph TD
subgraph CORE
ARM_CORTEX_M3["ARM Cortex-M3<br/>72MHz"]
end
subgraph BUS
ICODE["ICode Bus<br/>(Flash Instruction)"]
DCODE["DCode Bus<br/>(Flash Data)"]
SYSTEM["System Bus<br/>(SRAM/FSMC)"]
AHB["AHB<br/>72MHz"]
APB2["APB2<br/>72MHz"]
APB1["APB1<br/>36MHz"]
end
subgraph PERIPHERALS_APB2
GPIO_A["GPIO A/B/C/D/E"]
USART1["USART1"]
SPI1["SPI1"]
TIM1["TIM1 (高级)"]
ADC1["ADC1/2"]
EXTI["EXTI"]
AFIO["AFIO"]
end
subgraph PERIPHERALS_APB1
TIM2_4["TIM2/3/4 (通用)"]
TIM5_7["TIM5/6/7"]
USART2_3["USART2/3"]
SPI2_3["SPI2/3"]
I2C1_2["I2C1/2"]
PWR["PWR"]
BKP["BKP"]
IWDG["IWDG"]
WWDG["WWDG"]
RTC["RTC"]
DMA["DMA"]
CAN["CAN"]
USB["USB"]
end
ARM_CORTEX_M3 --> ICODE
ARM_CORTEX_M3 --> DCODE
ARM_CORTEX_M3 --> SYSTEM
SYSTEM --> AHB
AHB --> APB2
AHB --> APB1
APB2 --> PERIPHERALS_APB2
APB1 --> PERIPHERALS_APB1
系统总线结构
| 总线 |
频率 |
连接 |
| ICode |
72MHz |
Cortex-M3 → Flash(指令) |
| DCode |
72MHz |
Cortex-M3 → Flash(数据) |
| System |
72MHz |
Cortex-M3 → SRAM / FSMC |
| AHB |
72MHz |
桥接 APB2 / APB1 / DMA / RCC |
| APB2 |
72MHz |
高速外设 (GPIO, USART1, SPI1, TIM1, ADC, EXTI, AFIO) |
| APB1 |
36MHz |
低速外设 (TIM2~7, USART2/3, SPI2/3, I2C1/2, PWR, BKP, IWDG, WWDG, RTC, DMA, CAN, USB) |
注意:APB1 最高 36MHz,如需 72MHz 必须使用 APB2。
引脚定义 (LQFP48)
graph TD
subgraph LQFP48_top
direction LR
PD0["PD0 (OSC_IN)"] --- PD1["PD1 (OSC_OUT)"]
PD1 --- NRST["NRST"]
NRST --- PC13["PC13 (TAMPER-RTC)"]
end
功能引脚速查
| 引脚 |
默认功能 |
复用功能 |
| PA0 |
GPIO |
TIM2_CH1_ETR / USART2_CTS / WKUP / ADC12_IN0 |
| PA1 |
GPIO |
TIM2_CH2 / USART2_RTS / ADC12_IN1 |
| PA2 |
GPIO |
TIM2_CH3 / USART2_TX / ADC12_IN2 |
| PA9 |
GPIO |
USART1_TX / TIM1_CH2 |
| PA10 |
GPIO |
USART1_RX / TIM1_CH3 |
| PB6 |
GPIO |
I2C1_SCL / TIM4_CH1 |
| PB7 |
GPIO |
I2C1_SDA / TIM4_CH2 |
| PB8 |
GPIO |
I2C1_SCL / TIM4_CH3 |
| PB9 |
GPIO |
I2C1_SDA / TIM4_CH4 |
| PC13 |
GPIO |
RTC_TAMPER |
完整引脚序号
| 编号 |
引脚 |
编号 |
引脚 |
编号 |
引脚 |
编号 |
引脚 |
| 1 |
PE2(VDD_1) |
13 |
PA13(SWDIO) |
25 |
PA0 |
37 |
PB9 |
| 2 |
PE3(VSS_1) |
14 |
PA14(SWCLK) |
26 |
PA1 |
38 |
PB8 |
| 3 |
NRST |
15 |
PA15(JTDI) |
27 |
PA2 |
39 |
BOOT0 |
| 4 |
PC13 |
16 |
PB3(JTDO) |
28 |
... |
40 |
PB7 |
| 5 |
PC14(OSC32_IN) |
17 |
PB4(JNTRST) |
... |
... |
41 |
PB6 |
| 6 |
PC15(OSC32_OUT) |
18 |
PB5 |
... |
... |
... |
... |
BOOT 启动配置
| BOOT1 |
BOOT0 |
启动区域 |
| X |
0 |
主Flash (0x08000000) |
| 0 |
1 |
系统存储器(System Loader, 0x1FFF0000) |
| 1 |
1 |
内嵌SRAM (0x20000000) |
实际使用:BOOT0=0 (接GND) 从Flash启动。ISP下载时:BOOT0=1, BOOT1=0。
最小系统电路
graph TD
subgraph POWER
VDD33["VDD (3.3V)"] --> VDD1["VDD_1"]
VDD33 --> VDD2["VDD_2"]
VDD33 --> VDDA["VDDA"]
VSS1["VSS_1"] --> GND["GND"]
VSS2["VSS_2"] --> GND
VSSA["VSSA"] --> GND
end
subgraph OSCILLATOR
HSE["8MHz HSE"] --> X1["X1<br/>PD0(OSC_IN)"]
HSE --> X2["X2<br/>PD1(OSC_OUT)"]
LSE["32.768kHz LSE"] --> X32_IN["PC14(OSC32_IN)"]
LSE --> X32_OUT["PC15(OSC32_OUT)"]
end
subgraph RESET
NRST_PIN["NRST"] --> R10k["10kΩ → 3.3V"]
NRST_PIN --> C100nF["100nF → GND"]
end
subgraph BOOT
BOOT0_PIN["BOOT0"] --> R10k_GND["10kΩ → GND"]
end
| 元件 |
参数 |
备注 |
| HSE 晶振 |
8MHz + 20pF ×2 |
主时钟源 |
| LSE 晶振 |
32.768kHz + 12.5pF ×2 |
RTC 时钟源 |
| 复位电容 |
100nF |
NRST 对地 |
| 复位上拉 |
10kΩ |
NRST 接 3.3V |
| 去耦电容 |
100nF × N |
每个 VDD/VSS 对各放一个 |
开发环境
| 工具 |
用途 |
| Keil MDK v5.38+ |
编译环境 (AC5 / AC6) |
| STM32F1xx_DFP |
Keil 器件包 |
| ST-Link Utility / STM32CubeProgrammer |
调试下载 |
| CH340 / FT232 |
串口 ISP 下载 (FlyMcu) |
| USB-TTL 模块 |
串口通信 |
标准库工程搭建步骤
1. 固件库文件下载
从 ST 官网下载 STM32F10x_StdPeriph_Lib_V3.5.0 或更高版本。
2. 目录结构
Project/
├── CMSIS/
│ ├── core_cm3.c
│ ├── core_cm3.h
│ ├── startup_stm32f10x_md.s
│ ├── stm32f10x.h
│ ├── system_stm32f10x.c
│ └── system_stm32f10x.h
├── STM32F10x_StdPeriph_Driver/
│ ├── inc/ (所有外设头文件)
│ └── src/ (所有外设源文件)
├── User/
│ ├── main.c
│ ├── stm32f10x_conf.h
│ ├── stm32f10x_it.c
│ └── stm32f10x_it.h
└── Output/ (编译输出)
3. 关键宏定义
Keil C/C++ Compiler → Define:
USE_STDPERIPH_DRIVER, STM32F10X_MD
| 宏 |
说明 |
USE_STDPERIPH_DRIVER |
启用标准外设驱动库 |
STM32F10X_MD |
Medium Density (64KB~128KB Flash, C8T6 用此) |
STM32F10X_HD |
High Density (256KB~512KB Flash) |
STM32F10X_CL |
Connectivity Line (STM32F105/107) |
4. 启动文件选择
| Flash容量 |
芯片后缀 |
启动文件 |
| 16~32KB |
C4/C6/T4/T6 |
startup_stm32f10x_ld.s |
| 64~128KB |
C8/CB/T8/TB |
startup_stm32f10x_md.s |
| 256~512KB |
RC/RE/RF/VC/VE/VF/ZC/ZE/ZF |
startup_stm32f10x_hd.s |
| 768KB~1MB |
RG/VG/ZG |
startup_stm32f10x_xl.s |
C8T6 → startup_stm32f10x_md.s(中容量)
5. Keil 分组设置
Project Targets:
├── Startup
│ └── startup_stm32f10x_md.s
├── StdPeriph
│ ├── misc.c
│ ├── stm32f10x_gpio.c
│ ├── stm32f10x_rcc.c
│ ├── stm32f10x_tim.c
│ ├── stm32f10x_usart.c
│ ├── stm32f10x_exti.c
│ ├── stm32f10x_i2c.c
│ ├── stm32f10x_spi.c
│ ├── stm32f10x_adc.c
│ ├── stm32f10x_dma.c
│ ├── stm32f10x_pwr.c
│ ├── stm32f10x_bkp.c
│ └── stm32f10x_flash.c
├── User
│ ├── main.c
│ ├── stm32f10x_it.c
│ ├── system_stm32f10x.c
│ └── Delay.c
└── Doc
└── readme.txt
6. C/C++ 头文件路径
$PROJ_DIR$\CMSIS
$PROJ_DIR$\STM32F10x_StdPeriph_Driver\inc
$PROJ_DIR$\User
7. 魔术棒设置
| Tab |
设置 |
| Device |
STM32F103C8 |
| Target |
Xtal: 8.0MHz, Use Cross-Module Optimization |
| Output |
Select Folder for Objects... → Output |
| Listing |
Select Folder for Listings... → Output |
| Debug |
ST-Link Debugger → Settings → SW |
启动文件流程
Reset_Handler
→ SystemInit() (system_stm32f10x.c)
→ RCC配置: HSE→PLL(x9)→SYSCLK=72MHz
→ AHB/APB1/APB2 分频器设置
→ Flash 预取缓冲/等待周期配置
→ __main (C库初始化)
→ 变量初始化 (ZI/BSS清零, RW复制)
→ 跳转 main()
SystemInit 时钟树 (默认配置 HSE 8MHz)
HSE (8MHz)
→ PLLSRC (HSE)
→ PLLMUL (x9)
→ PLLCLK = 8MHz × 9 = 72MHz
→ SYSCLK = 72MHz
→ AHB Prescaler (/1) → HCLK = 72MHz
→ APB1 Prescaler (/2) → PCLK1 = 36MHz
→ APB2 Prescaler (/1) → PCLK2 = 72MHz
→ ADC Prescaler (/6) → ADCCLK = 12MHz
SysTick 延时函数
SysTick 是 Cortex-M3 内核的 24 位递减计数器,挂载在 AHB (72MHz)。
// Delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x.h"
void Delay_Init(void);
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
#endif
// Delay.c
#include "Delay.h"
static uint32_t fac_us;
static uint32_t fac_ms;
void Delay_Init(void)
{
fac_us = SystemCoreClock / 1000000; // 72
fac_ms = SystemCoreClock / 1000; // 72000
}
void Delay_us(uint32_t us)
{
uint32_t load = us * fac_us;
// 最大 2^24-1 = 16777215, us 超出会复位
if (load > 0xFFFFFF) return;
SysTick->LOAD = load - 1;
SysTick->VAL = 0;
SysTick->CTRL = 0x01; // 使能, 不中断, 使用 HCLK
while (!(SysTick->CTRL & (1 << 16))); // 等待 COUNTFLAG
SysTick->CTRL = 0; // 关闭
}
void Delay_ms(uint32_t ms)
{
while (ms--) {
Delay_us(1000);
}
}
或用轮回方式(简单无 SysTick 冲突):
void Delay_ms(uint32_t ms)
{
uint32_t i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 7200; j++); // 72MHz 实测约 1ms
}
编译与下载
ST-Link 方式(推荐)
- 连接 SWD: PA13(SWDIO), PA14(SWCLK), GND, 3.3V(可选供电)
- Keil → Flash → Download (Ctrl+F8)
- 使用 ST-Link Utility 或 STM32CubeProgrammer 也可以
ISP 串口下载 (FlyMcu)
- BOOT0=1, BOOT1=0 → 上电/复位 → 进入系统 Loader
- 使用 CH340/FT232 USB-TTL 连接 PA9(TX)→模块RX, PA10(RX)→模块TX
- FlyMcu 选择串口, 勾选"编程后校验", 下载
- 下载完成后 BOOT0=0 → 复位 → 从 Flash 启动
常见坑点/注意事项
- 启动文件选错 — C8T6 用
_md.s,用 _hd.s 会导致 FLASH 地址映射错误无法运行
- 忘记添加
USE_STDPERIPH_DRIVER — 编译报错 stm32f10x.h 不包含外设定义
- 忘记添加
STM32F10X_MD — 外设寄存器地址映射错误
- C/C++ 头文件路径未配置 — 找不到
stm32f10x.h
- 晶振频率与 SystemInit 不符 — 8MHz 用 PLL×9=72MHz;如用 12MHz 晶振需改成 PLL×6 或改配置(HSE_VALUE 宏)
- SysTick 优先级 — 默认内核优先级最高,会影响 HAL_Delay 等;标准库手动实现无冲突
- ST-Link 驱动 — Win10/11 可能需禁用驱动签名或安装旧版驱动
- ISP 下载失败 — 检查 BOOT0/BOOT1 电平,串口 TX/RX 交叉连接,波特率不宜过高(115200或57600)