操作顺序
先解锁Flash,再擦除片区,再写入,写完了别忘了加锁。
c
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase();
HAL_FLASH_Program();
HAL_FLASH_Lock();
擦除操作
首先有个问题,我们为什么要擦除,不能直接覆写吗?答案是不能!!!。Flash存储器是一种非易失性存储器,其存储单元在未编程的时候处于1
状态(对于Nor Flash,通常擦除后为全1
),写操作是将某些比特位变为0
,而只有擦除操作才能将位从0
变为1
。
c
typedef struct {
uint32_t TypeErase; // 擦除类型
uint32_t Banks; // 指定操作的目标 Bank
uint32_t Sector; // 起始扇区号
uint32_t NbSectors; // 要擦除的扇区数量
uint32_t VoltageRange; // 工作电压范围
} FLASH_EraseInitTypeDef;
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError);
TypeErase
:指定要执行的擦除操作类型。
可选值:
FLASH_TYPEERASE_SECTORS
:擦除指定扇区(最常用)FLASH_TYPEERASE_MASSERASE
:整片擦除(全芯片擦除)FLASH_TYPEERASE_PAGES
:按页擦除(某些系列如 STM32L0/L1)
Banks :目标存储区,指定要操作的 Flash Bank(存储区)
可选值:
FLASH_BANK_1
:操作 Bank1FLASH_BANK_2
:操作 Bank2FLASH_BANK_BOTH
:同时操作两个 Bank
注意事项:
- 仅对支持多 Bank 的芯片有效(如 STM32F4/F7/H7)
- 单 Bank 芯片固定使用
FLASH_BANK_1
Sector :指定擦除操作的起始扇区
取值范围:
FLASH_SECTOR_0
到FLASH_SECTOR_11
(具体取决于芯片型号)- 不同芯片的扇区划分不同:
- STM32F4:扇区0-3(16KB), 扇区4(64KB), 扇区5-11(128KB)
- STM32F7:扇区0-7(32KB), 扇区8-11(128KB)
- STM32H7:扇区0-7(128KB), 扇区8(256KB)
NbSectors :指定要连续擦除的扇区数量
注意事项:
- 必须大于0
- 扇区必须连续(不能跳过中间扇区)
- 最大数量受芯片实际扇区数限制
VoltageRange:指定芯片当前工作电压范围,影响编程时间和精度
可选值:
FLASH_VOLTAGE_RANGE_1
:1.7V - 2.1VFLASH_VOLTAGE_RANGE_2
:2.1V - 2.7VFLASH_VOLTAGE_RANGE_3
:2.7V - 3.6V(最常用)FLASH_VOLTAGE_RANGE_4
:2.7V - 3.6V(特定芯片)
c
void erase_flash_sectors(uint32_t start_sector, uint32_t num_sectors) {
HAL_FLASH_Unlock(); // 解锁Flash
FLASH_EraseInitTypeDef erase_init;
uint32_t sector_error = 0;
// 配置擦除参数
erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;
erase_init.Banks = FLASH_BANK_1; // F407系列只有Bank1
erase_init.Sector = FLASH_SECTOR_11;
erase_init.NbSectors = 1;
erase_init.VoltageRange = FLASH_VOLTAGE_RANGE_3;
// 执行擦除
if (HAL_FLASHEx_Erase(&erase_init, §or_error) != HAL_OK) {
// 错误处理
if (sector_error != 0xFFFFFFFF) {
// sector_error包含失败扇区号
Error_Handler();
}
}
HAL_FLASH_Lock(); // 重新锁定Flash
}
写入操作
c
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
参数 | 含义 | 可选值/要求 |
---|---|---|
TypeProgram |
指定编程数据类型宽度 | FLASH_TYPEPROGRAM_BYTE (8位) FLASH_TYPEPROGRAM_HALFWORD (16位) FLASH_TYPEPROGRAM_WORD (32位) FLASH_TYPEPROGRAM_DOUBLEWORD (64位) |
Address |
写入的目标 Flash 地址 | 必须按数据类型对齐(如32位写入需4字节对齐) |
Data |
要写入的数据(实际使用时会根据类型截断) | 最大支持64位,超宽数据需分多次写入 |
c
void write_word(uint32_t address, uint32_t data) {
HAL_FLASH_Unlock(); // 解锁Flash
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); // 清除错误标志
// 执行写入
HAL_StatusTypeDef status = HAL_FLASH_Program(
FLASH_TYPEPROGRAM_WORD,
address,
(uint64_t)data
);
HAL_FLASH_Lock(); // 重新上锁
if (status != HAL_OK) {
uint32_t error = HAL_FLASH_GetError();
Error_Handler(error);
}
}
// 调用示例
write_word(0x080E0000, 0x12345678); // 向扇区5起始地址写入数据
读取操作
读取操作很简单,没有调用函数,直接按照地址取值即可。
c
// 读取验证
uint32_t read_val = *(__IO uint32_t*)address;
if (read_val != expected_val) {
// 检查地址/擦除状态
}