这一章在干嘛?

FLASH 模拟 EEPROM 实验:F407 内部 Flash 读写、按页/扇区擦除、地址映射。学会后用 Flash 存配置参数,无需外挂 EEPROM。

34.1 STM32F407 FLASH 简介

34.2 硬件设计

34.3 程序设计

34.4 下载验证

34.1 STM32F407 FLASH 简介

F407 内部 Flash 1 MB,分 4 个 16 KB + 1 个 64 KB + 7 个 128 KB 扇区。

扇区大小地址范围
扇区 016 KB0x08000000~0x08003FFF
扇区 116 KB0x08004000~0x08007FFF
扇区 216 KB0x08008000~0x0800BFFF
扇区 316 KB0x0800C000~0x0800FFFF
扇区 464 KB0x08010000~0x0801FFFF
扇区 5~11128 KB0x08020000~0x080FFFFF

原书图 34.1.1:Flash 扇区结构原书图 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.1.1:FLASH 读写流程图

34.3.2 注意

  • 写之前必须擦除;
  • 按扇区擦除(4 KB 起),不能按字节;
  • 写之前 addr 必须已经擦除过(值为 0xFF)。

原书图 34.3.2.1:擦除与编程时序图原书图 34.3.2.1:擦除与编程时序图

34.4 下载验证

写入字符串到扇区 11,重启开发板再读 → 一致。

存配置参数:Flash 适合存少量配置(设备 ID、校准值等);不适合频繁写——Flash 寿命 ~10K 次循环。