嵌入式天天和 bit 打交道:清零 &= ~BIT、置位 |= BIT、取反 ^= BIT、读取 (x & BIT) ? 1 : 0。
#define PI 3.14 文本替换;带参数 #define MAX(a,b) ((a)>(b)?(a):(b)) 注意整体加括号避免运算符优先级坑。
头文件防重包含 #ifndef __STM32_H\n#define __STM32_H ... #endif;区分调试与发布 #ifdef DEBUG ... #endif。
extern uint8_t g_flag; 告诉编译器「这变量在别的文件里定义」,不要分配空间。多文件工程必备。
typedef unsigned int uint32_t; 让代码可移植、易读。C99/C11 的 <stdint.h> 已经替我们做好:uint8_t/uint16_t/uint32_t/uint64_t/int8_t/.../int64_t。
把相关变量打包:struct GPIO_TypeDef { uint32_t MODER; uint32_t OTYPER; ... };。访问用 .(普通变量)或 ->(指针变量)。
STM32 大量用「外设寄存器结构体指针」:#define GPIOA ((GPIO_TypeDef *)0x40020000),然后 GPIOA->BSRR = 0x01; 就是点亮 PA0。指针就是地址,地址就是数字,没什么神秘的。
寄存器 = 特殊功能的内存单元。本质:
(*(unsigned int *)(0x40010C0C)) = 0xFFFF; // 把 GPIOB->ODR 设为 0xFFFF
但可读性差,所以改用结构体:
GPIOB->ODR = 0xFFFF; // 实质等价上一行
寄存器按 32 位组织,每位或几位代表一个开关/参数。命名约定:xxxx_CR1/CR2/CR3 配置寄存器、xxxx_SR 状态寄存器、xxxx_DR 数据寄存器、xxxx_BRR 波特率寄存器。
Cortex-M4 由 ARM 设计,包含 NVIC(嵌套向量中断控制器)、SysTick、MPU、FPU、DSP 指令等。ST 在此基础上集成自家外设(USART/SPI/...)。
F407 有 8 条主控总线:I-Code、D-Code、S-Bus、DMA、FSMC、AHB、APB1、APB2。

整个 4 GB 地址空间划分:
| 地址范围 | 用途 |
|---|---|
| 0x0000_0000~0x1FFF_FFFF | Code 区(Flash 映射) |
| 0x2000_0000~0x3FFF_FFFF | SRAM(192 KB) |
| 0x4000_0000~0x5FFF_FFFF | 外设寄存器 |
| 0x6000_0000~0x7FFF_FFFF | FSMC 扩展(外部 SRAM/NOR) |
| 0x8000_0000~0x9FFF_FFFF | FSMC 扩展(NAND) |
| 0xA000_0000~0xDFFF_FFFF | FSMC 扩展(其它) |
| 0xE000_0000~0xFFFF_FFFF | Cortex-M4 内核(NVIC/SysTick) |

寄存器描述解读:手册里每个寄存器都有「位定义表」,例如 USART_BRR 寄存器:
| 位 | 名称 | 读写 | 功能 |
|---|---|---|---|
| [3:0] | DIV_Fraction | RW | 小数部分 |
| [15:4] | DIV_Mantissa | RW | 整数部分 |
寄存器映射举例:把 USART1 的 BRR 地址算出:
| 外设基地址 | USART 基地址 | 偏移 | 总地址 |
|---|---|---|---|
| 0x40000000 | 0x40011000 | 0x08 | 0x40011008 |
寄存器地址计算:外设基址 + 偏移;外设基址 = 总线基址 + 总线相对偏移;总线基址 = 总线基址基址 + N×总线间距。

stm32f407xx.h 寄存器映射说明:ST 已经把整个 F407 的寄存器映射成结构体,我们直接 USART1->BRR = 0x0683; 即可,不用自己算地址。
a &= ~BIT 清零,a |= BIT 置位。