PPT 参考图 -- 课程介绍
| 项目 | 参数 |
|---|---|
| 内核 | 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 中断嵌套。
PPT 参考图 -- 开发板
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。
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 | ... | ... | ... | ... |
| BOOT1 | BOOT0 | 启动区域 |
|---|---|---|
| X | 0 | 主Flash (0x08000000) |
| 0 | 1 | 系统存储器(System Loader, 0x1FFF0000) |
| 1 | 1 | 内嵌SRAM (0x20000000) |
实际使用:BOOT0=0 (接GND) 从Flash启动。ISP下载时:BOOT0=1, BOOT1=0。
PPT 参考图 -- 面包板与硬件电路
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 对各放一个 |
PPT 参考图 -- 软件准备
| 工具 | 用途 |
|---|---|
| Keil MDK v5.38+ | 编译环境 (AC5 / AC6) |
| STM32F1xx_DFP | Keil 器件包 |
| ST-Link Utility / STM32CubeProgrammer | 调试下载 |
| CH340 / FT232 | 串口 ISP 下载 (FlyMcu) |
| USB-TTL 模块 | 串口通信 |
PPT 参考图 -- 新建工程与下载
从 ST 官网下载 STM32F10x_StdPeriph_Lib_V3.5.0 或更高版本。
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/ (编译输出)
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) |
| 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(中容量)
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
$PROJ_DIR$\CMSIS
$PROJ_DIR$\STM32F10x_StdPeriph_Driver\inc
$PROJ_DIR$\User
| 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 |
PPT 参考图 -- C语言基础知识
Reset_Handler
→ SystemInit() (system_stm32f10x.c)
→ RCC配置: HSE→PLL(x9)→SYSCLK=72MHz
→ AHB/APB1/APB2 分频器设置
→ Flash 预取缓冲/等待周期配置
→ __main (C库初始化)
→ 变量初始化 (ZI/BSS清零, RW复制)
→ 跳转 main()
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
上电后,STM32 从 0x08000000 取出复位向量,加载栈指针 MSP 后跳转到 Reset_Handler。该过程由硬件自动完成:CPU 读取向量表前 4 字节作为栈顶地址,后 4 字节作为复位入口地址。
SystemInit 执行完整的时钟树配置:
HSERDY 标志置位)PLLCLK = 8MHz × 9 = 72MHzHPRE 为 /1,即 HCLK = SYSCLK / 1 = 72MHzPPRE1 为 /2,PCLK1 = HCLK / 2 = 36MHzPPRE2 为 /1,PCLK2 = HCLK / 1 = 72MHzADCPRE 为 /6,ADCCLK = PCLK2 / 6 = 12MHz分频器公式汇总:
HCLK = SYSCLK / AHB_PrescalerPCLK1 = HCLK / APB1_Prescaler(最大 36MHz)PCLK2 = HCLK / APB2_Prescaler(最大 72MHz)ADCCLK = PCLK2 / ADC_Prescaler(最大 14MHz)启动文件执行流程的硬件行为:
Reset_Handler 执行时,Flash 控制器处于默认状态(0 等待周期),此时 CPU 直接从 Flash 取指令SystemInit 完成后,CPU 时钟切换到 72MHz,Flash 等待周期同步设为 2(FLASH_Latency_2)__main 调用 C 库初始化:清零 BSS 段(__ARM_common_zeroint)、将 RW 段从 Load 区复制到执行区,最后调用 main()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
}
PPT 参考图 -- 试炼与总结
_md.s,用 _hd.s 会导致 FLASH 地址映射错误无法运行USE_STDPERIPH_DRIVER — 编译报错 stm32f10x.h 不包含外设定义STM32F10X_MD — 外设寄存器地址映射错误stm32f10x.h