这一章在干嘛?
FLASH 模拟 EEPROM 实验:F407 内部 Flash 读写、按页/扇区擦除、地址映射。学会后用 Flash 存配置参数,无需外挂 EEPROM。
34.1 STM32F407 FLASH 简介
F407 内部 Flash 1 MB,分 4 个 16 KB + 1 个 64 KB + 7 个 128 KB 扇区。
| 扇区 | 大小 | 地址范围 |
|---|---|---|
| 扇区 0 | 16 KB | 0x08000000~0x08003FFF |
| 扇区 1 | 16 KB | 0x08004000~0x08007FFF |
| 扇区 2 | 16 KB | 0x08008000~0x0800BFFF |
| 扇区 3 | 16 KB | 0x0800C000~0x0800FFFF |
| 扇区 4 | 64 KB | 0x08010000~0x0801FFFF |
| 扇区 5~11 | 128 KB | 0x08020000~0x080FFFFF |
原书图 34.1.1:Flash 扇区结构
操作流程:
- 解锁:
HAL_FLASH_Unlock(); - 擦除:
HAL_FLASHEx_Erase(&erase, &err);(必须按扇区擦) - 编程:
HAL_FLASH_Program(TYPEPROGRAM_BYTE, addr, data); - 上锁:
HAL_FLASH_Lock();
Flash 操作期间中断要屏蔽:擦/写过程不能被打断,否则指令错误。
34.2 硬件设计
本实验使用 USART1 读写 FLASH → 串口显示。
34.3 程序设计
34.3.1 关键代码
#define FLASH_ADDR 0x080E0000 // 扇区 11
void flash_write(uint32_t addr, uint8_t *buf, uint32_t len) {
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef e = {0};
e.TypeErase = FLASH_TYPEERASE_SECTORS;
e.Sector = FLASH_SECTOR_11;
e.NbSectors = 1;
uint32_t err;
HAL_FLASHEx_Erase(&e, &err);
for (uint32_t i = 0; i < len; i++) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr + i, buf[i]);
}
HAL_FLASH_Lock();
}
void flash_read(uint32_t addr, uint8_t *buf, uint32_t len) {
for (uint32_t i = 0; i < len; i++) {
buf[i] = *(__IO uint8_t *)(addr + i);
}
}
原书图 34.3.1.1:FLASH 读写流程图
34.3.2 注意
- 写之前必须擦除;
- 按扇区擦除(4 KB 起),不能按字节;
- 写之前 addr 必须已经擦除过(值为 0xFF)。
原书图 34.3.2.1:擦除与编程时序图
34.4 下载验证
写入字符串到扇区 11,重启开发板再读 → 一致。
存配置参数:Flash 适合存少量配置(设备 ID、校准值等);不适合频繁写——Flash 寿命 ~10K 次循环。
F407 内部 Flash 容量?
1 MB。
Flash 写入之前为什么必须先擦除?
Flash 只能 1 写 0,擦除才能把所有位变 1。
Flash 寿命?
约 10K 次擦写循环。