打印
[STM32C0]

利用 STM32 的 Flash 存储来模拟 EEPROM

[复制链接]
41|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
4c1l|  楼主 | 2024-9-30 18:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32 一些型号没有直接的 EEPROM 存储器,但可以通过使用内置的 Flash 存储来模拟 EEPROM。EEPROM 通常用于保存小数据量的用户配置,而 Flash 可以用来实现类似的功能。利用 STM32 的 Flash 存储来模拟 EEPROM

EEPROM 模拟的基本原理
由于 Flash 只能在擦除后才能写入数据,并且擦除操作是以页(Page)为单位的,且 Flash 的写入次数有限,因此在使用 Flash 模拟 EEPROM 时,通常会遵循以下原则:

分区管理:将 Flash 的一部分划分为 EEPROM 模拟区域,可以存储多个小数据块。
擦除操作:只有在数据更新前,才会擦除整个页,保证 Flash 的使用寿命。
写入操作:写入数据时需要判断数据是否需要更新,如果 Flash 中的数据与新数据不同才执行写入操作。
掉电保护:在掉电时,Flash 中的数据仍然保存,因此适合用于存储重要的用户配置数据。


使用特权

评论回复
沙发
4c1l|  楼主 | 2024-9-30 18:01 | 只看该作者
Flash 分区选择
首先选择 Flash 的某个区域作为模拟 EEPROM 的存储区,避免与程序存储区冲突。

c

#define EEPROM_START_ADDRESS  0x08020000  // 假设使用这个地址(根据你的应用程序选择合适的起始地址)
#define EEPROM_PAGE_SIZE      0x4000      // 每页大小,通常为16KB(以 STM32F4 系列为例)

使用特权

评论回复
板凳
4c1l|  楼主 | 2024-9-30 18:01 | 只看该作者
擦除 Flash 页
为了保证 Flash 的写入操作正常进行,在写入前需要先擦除 Flash 页。擦除操作会将整个页的内容重置为 0xFF。

c

void Flash_Erase_Page(uint32_t PageAddress)
{
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0;

    // 解锁 Flash 控制寄存器
    HAL_FLASH_Unlock();

    // 配置要擦除的页
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
    EraseInitStruct.Sector = FLASH_SECTOR_5;  // 根据地址选择扇区
    EraseInitStruct.NbSectors = 1;
    EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

    // 擦除扇区
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
    {
        // 擦除失败时处理
    }

    // 锁定 Flash,防止进一步写操作
    HAL_FLASH_Lock();
}

使用特权

评论回复
地板
4c1l|  楼主 | 2024-9-30 18:01 | 只看该作者
写入数据到 Flash
写入 Flash 的操作需要注意不能重复写入相同的数据,且只能将 1 写为 0,不能将 0 写为 1。因此写入时要确保数据块是新写入或者已经擦除了。

c
void Flash_Write_Word(uint32_t Address, uint32_t Data)
{
    // 解锁 Flash
    HAL_FLASH_Unlock();

    // 写入一个 32 位数据到指定的地址
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, Data) != HAL_OK)
    {
        // 处理写入失败
    }

    // 锁定 Flash
    HAL_FLASH_Lock();
}

使用特权

评论回复
5
4c1l|  楼主 | 2024-9-30 18:01 | 只看该作者
读取数据
读取 Flash 是一个简单的内存操作,直接从指定的地址读取数据即可。

c

uint32_t Flash_Read_Word(uint32_t Address)
{
    return *(__IO uint32_t*)Address;
}

使用特权

评论回复
6
4c1l|  楼主 | 2024-9-30 18:02 | 只看该作者
EEPROM 模拟的高级实现
为了模拟 EEPROM,我们通常会实现一个数据页管理的机制。通过对 Flash 页进行擦除和写入管理,可以有效利用 Flash 寿命并避免频繁擦除。下面是 EEPROM 模拟的简单框架。

初始化 EEPROM 存储区:检查是否需要擦除 Flash 页。
写入数据:检查当前地址的内容,只有在新数据和旧数据不同时才执行擦除和写入操作。
读取数据:从指定的 EEPROM 模拟区域中读取配置数据。

使用特权

评论回复
7
4c1l|  楼主 | 2024-9-30 18:02 | 只看该作者
示例代码
以下是一个 EEPROM 模拟的示例代码,它演示了如何使用 Flash 作为 EEPROM 来存储用户数据:

c

#define EEPROM_START_ADDRESS  0x08020000  // EEPROM 模拟起始地址
#define EEPROM_PAGE_SIZE      0x4000      // Flash 页大小(以 STM32F4 为例)

// 写入 EEPROM 数据
HAL_StatusTypeDef EEPROM_Write(uint32_t VirtualAddress, uint32_t Data)
{
    // 检查当前地址的数据是否与新数据相同
    if (Flash_Read_Word(EEPROM_START_ADDRESS + VirtualAddress) != 0xFFFFFFFF)
    {
        // 数据不同,执行擦除操作
        Flash_Erase_Page(EEPROM_START_ADDRESS);
    }

    // 写入新数据
    Flash_Write_Word(EEPROM_START_ADDRESS + VirtualAddress, Data);

    return HAL_OK;
}

// 读取 EEPROM 数据
uint32_t EEPROM_Read(uint32_t VirtualAddress)
{
    return Flash_Read_Word(EEPROM_START_ADDRESS + VirtualAddress);
}

// 初始化 EEPROM 模拟存储
void EEPROM_Init(void)
{
    // 如果需要,可以在这里初始化 EEPROM 存储区
    // 检查是否需要擦除等
}

// 主函数
int main(void)
{
    HAL_Init();
    EEPROM_Init();

    // 写入数据
    uint32_t data_to_store = 0x12345678;
    EEPROM_Write(0x00, data_to_store);  // 将数据写入到 EEPROM 模拟存储

    // 读取数据
    uint32_t read_data = EEPROM_Read(0x00);  // 从 EEPROM 模拟存储读取数据

    if (read_data == data_to_store)
    {
        // 成功读取
    }

    while (1)
    {
        // 主循环
    }
}

使用特权

评论回复
8
4c1l|  楼主 | 2024-9-30 18:02 | 只看该作者
EEPROM 模拟的其他注意事项
擦写寿命:Flash 的擦写寿命有限,通常为 1 万到 10 万次。可以通过分页机制来减少擦写次数,延长 Flash 的寿命。

使用特权

评论回复
9
4c1l|  楼主 | 2024-9-30 18:02 | 只看该作者
电压要求:在进行 Flash 写操作时,电压必须稳定。如果电压不稳定,可能会导致 Flash 写入错误或损坏。

使用特权

评论回复
10
4c1l|  楼主 | 2024-9-30 18:02 | 只看该作者
掉电保护:Flash 写入操作时,确保有足够的电源供应,防止掉电导致数据丢失。

使用特权

评论回复
11
4c1l|  楼主 | 2024-9-30 18:02 | 只看该作者
通过上述方法,STM32 的 Flash 存储可以很容易地模拟 EEPROM 来存储小数据量的用户配置数据。虽然 Flash 的擦写次数有限,但通过合理的管理和分页机制,可以有效延长其寿命并满足大多数应用的需求。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

552

帖子

2

粉丝