You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
    }
}

你之前遇到问题的可能原因

  1. 没擦除扇区:直接覆盖写入,Flash无法修改原有0位,导致写入失败
  2. 地址未对齐:用TYPEPROGRAM_WORD但地址不是4字节对齐,编程失败
  3. 没解锁Flash:忘记调用HAL_FLASH_Unlock(),Flash处于锁定状态无法写入

先试试上面的代码,记得先擦除扇区再写入,应该就能解决多字节写入的问题啦~

内容的提问来源于stack exchange,提问作者Manuel Illueca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:01:39