STM32F4 Discovery Flash读写问题:仅能写单字节,求多字节写入方法
解决STM32F4 Discovery Flash多字节写入问题
嗨,我来帮你搞定这个Flash多字节写入的问题~ 你现在能写单个字节,但没法连续写多个,大概率是没摸清楚STM32F4 Flash的编程规则,或者处理方式不对,咱们一步步来解决:
首先得搞懂STM32F4 Flash的核心规则
STM32F4的Flash不是随便写任意字节的,它有固定的编程粒度,而且必须先擦除扇区才能写入(因为Flash只能从1改成0,不能直接覆盖原有数据):
TYPEPROGRAM_BYTE:写8位单字节,地址可以不对齐TYPEPROGRAM_HALFWORD:写16位半字,地址必须2字节对齐TYPEPROGRAM_WORD:写32位字,地址必须4字节对齐TYPEPROGRAM_DOUBLEWORD:写64位双字,地址必须8字节对齐
你之前改地址没解决,可能是地址没对齐,或者没处理批量写入的逻辑,下面给你两种实用的实现方案:
方案1:按字节逐个写入(简单直接,适合任意长度)
这种方式不用考虑对齐问题,就是循环逐个写每个字节,缺点是效率稍低,但足够满足大部分场景:
#include "stm32f4xx_hal.h" #define FLASH_START_ADDR 0x0800F000 // 选一个用户可用的Flash地址(比如最后一个扇区) uint8_t userConfig[] = {0x01, 0x02, 0x03, 0x04, 0x05}; // 要写入的多字节数据 void Flash_Write_MultiByte(void) { // 1. 解锁Flash(必须先解锁才能编程) HAL_FLASH_Unlock(); // 2. 逐个写入字节 for (uint32_t i = 0; i < sizeof(userConfig); i++) { // 写入单个字节 if (HAL_FLASH_Program(TYPEPROGRAM_BYTE, FLASH_START_ADDR + i, userConfig[i]) != HAL_OK) { // 处理写入错误,比如打印日志或触发指示灯 Error_Handler(); } // 可选:验证写入是否成功 if (*(uint8_t*)(FLASH_START_ADDR + i) != userConfig[i]) { Error_Handler(); } } // 3. 锁定Flash,防止误操作 HAL_FLASH_Lock(); }
方案2:按字/半字批量写入(效率更高,适合大数据量)
如果要写的数据比较多,推荐用这种方式,先写完整的字/半字,再处理剩余的零散字节,效率会高很多:
void Flash_Write_Batch(uint32_t flash_addr, uint8_t* data, uint32_t length) { HAL_FLASH_Unlock(); uint32_t current_addr = flash_addr; uint32_t remaining_len = length; // 先写完整的32位字 while (remaining_len >= 4) { uint32_t word_data = *(uint32_t*)data; if (HAL_FLASH_Program(TYPEPROGRAM_WORD, current_addr, word_data) != HAL_OK) { Error_Handler(); } current_addr += 4; data += 4; remaining_len -= 4; } // 处理剩余的16位半字 if (remaining_len >= 2) { uint16_t halfword_data = *(uint16_t*)data; if (HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, current_addr, halfword_data) != HAL_OK) { Error_Handler(); } current_addr += 2; data += 2; remaining_len -= 2; } // 处理最后1个字节 if (remaining_len == 1) { if (HAL_FLASH_Program(TYPEPROGRAM_BYTE, current_addr, *data) != HAL_OK) { Error_Handler(); } } HAL_FLASH_Lock(); } // 调用示例 // Flash_Write_Batch(0x0800F000, userConfig, sizeof(userConfig));
必须注意的前置步骤:擦除Flash扇区
不管用哪种方式,写入前必须先擦除目标扇区!不然原有数据会干扰写入(比如原有位是0,你没法写成1)。这里给你擦除扇区的代码:
void Flash_Erase_Sector(void) { FLASH_EraseInitTypeDef EraseInitStruct; uint32_t PageError = 0; // 配置擦除参数:擦除第7扇区(对应0x0800F000地址,具体扇区对应关系查STM32F4 datasheet) EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; // 3.3V供电选这个 EraseInitStruct.Sector = FLASH_SECTOR_7; EraseInitStruct.NbSectors = 1; // 执行擦除 if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) { Error_Handler(); } }
你之前遇到问题的可能原因
- 没擦除扇区:直接覆盖写入,Flash无法修改原有0位,导致写入失败
- 地址未对齐:用
TYPEPROGRAM_WORD但地址不是4字节对齐,编程失败 - 没解锁Flash:忘记调用
HAL_FLASH_Unlock(),Flash处于锁定状态无法写入
先试试上面的代码,记得先擦除扇区再写入,应该就能解决多字节写入的问题啦~
内容的提问来源于stack exchange,提问作者Manuel Illueca
相关产品推荐
相关产品推荐

