FLASH
一. 核心参数定义
C
#define STORE_START_ADDRESS 0x0800FC00 // FLASH存储起始地址(需对应FLASH页地址)
#define STORE_COUNT 512 // 存储数据的个数(半字,1个半字=2字节)
uint16_t Store_Data[STORE_COUNT]; // SRAM缓存数组(掉电丢失,需同步到FLASH实现掉电保存)
关键参数说明
-
存储地址:
0x0800FC00为STM32F10x FLASH的某一页起始地址(需根据芯片FLASH容量调整,确保地址对齐),用于存储标志位和参数数据。 -
存储个数:
STORE_COUNT = 512,表示可存储512个半字(uint16_t)数据,总存储容量 = 512 × 2 = 1024字节(1KB)。 -
SRAM数组:
Store_Data作为缓存,程序运行时操作该数组,通过Store_Save()同步到FLASH,实现掉电不丢失。
FLASH操作核心规则
-
STM32F10x 内部FLASH 最小操作单位为 半字(2字节),故读写均以半字为单位。
-
FLASH 编程前必须先 擦除对应页(不能直接覆盖写入),擦除后所有位均为1(0xFFFF)。
-
地址计算:第i个数据(半字)的FLASH地址 = 起始地址 + i × 2(因每个半字占2字节)。
二. 初始化(FLASH参数存储模块)
初始化函数
C
/**
* 函 数:参数存储模块初始化
* 参 数:无
* 返 回 值:无
* 核心功能:判断是否第一次使用,初始化FLASH并加载数据到SRAM
*/
void Store_Init(void)
{
/*判断是不是第一次使用(通过FLASH标志位判断)*/
if (MyFLASH_ReadHalfWord(STORE_START_ADDRESS) != 0xA5A5) //读取起始地址的标志位,不相等则为第一次使用
{
MyFLASH_ErasePage(STORE_START_ADDRESS); //擦除存储起始地址所在的FLASH页
MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5); //在起始地址写入标志位0xA5A5,标记已初始化
for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环初始化所有有效数据(跳过标志位)
{
MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, 0x0000); //有效数据全部清0
}
}
/*上电加载:将FLASH中存储的数据加载回SRAM数组,实现掉电不丢失*/
for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环读取所有数据(包含标志位)
{
Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i * 2); //FLASH数据→SRAM数组
}
}
初始化关键流程
-
标志位判断:通过读取FLASH起始地址的半字数据,与自定义标志位
0xA5A5对比,判断是否为第一次使用。 -
第一次初始化:擦除对应FLASH页 → 写入标志位 → 初始化所有有效数据为0x0000,完成FLASH初始化。
-
上电加载:无论是否为第一次使用,均将FLASH中存储的所有数据(包含标志位)加载到SRAM数组,确保程序运行时操作的是最新数据。
三. 核心函数用法
-
Store_Init(参数存储模块初始化)
void Store_Init(void);-
核心作用:初始化FLASH(第一次使用时),并将FLASH中的数据加载到SRAM数组
Store_Data,为后续参数读写做准备。 -
使用时机:程序上电后,其他模块初始化完成后调用(如OLED、按键初始化后)。
-
-
Store_Save(数据保存到FLASH)
-
函 数:参数存储模块保存数据到闪存
-
参 数:无
-
返 回 值:无
-
核心功能:将SRAM数组数据同步到FLASH,实现掉电保存
_/
void Store_Save(void)
{
MyFLASH_ErasePage(STORE_START_ADDRESS); //先擦除对应FLASH页(必须擦除后才能编程)
for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环写入所有数据(包含标志位)
{
MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i _ 2, Store_Data[i]); //SRAM数组→FLASH
}
}`
- 核心作用:将SRAM数组 `Store_Data` 中的所有数据(包含标志位),同步写入到内部FLASH,确保掉电后数据不丢失。 - 核心流程:擦除FLASH页 → 逐一半字写入数据(因FLASH不能直接覆盖,需先擦除)。 - 使用时机:当 `Store_Data` 数组中的参数修改后,需调用此函数保存(如参数设置完成后)。
- Store_Clear(有效数据清0)
-
函 数:参数存储模块将所有有效数据清0
-
参 数:无
-
返 回 值:无
-
核心功能:清0 SRAM数组有效数据,并同步到FLASH
*/
void Store_Clear(void)
{
for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环清0(跳过第一个标志位,保留标志位)
{
Store_Data[i] = 0x0000; //SRAM数组有效数据清0
}
Store_Save(); //调用保存函数,将清0后的数据同步到FLASH
}`
- 核心作用:将SRAM数组中除标志位(第一个数据)外的所有有效数据清0,并同步到FLASH,实现参数重置。 - 注意:不清除标志位 `0xA5A5`,避免下次上电被判定为"第一次使用",重新初始化。
四. MyFLASH函数
c
#include "stm32f10x.h" // Device header
/**
* 函 数:FLASH读取一个32位的字
* 参 数:Address 要读取数据的字地址
* 返 回 值:指定地址下的数据
*/
uint32_t MyFLASH_ReadWord(uint32_t Address)
{
return *((__IO uint32_t *)(Address)); //使用指针访问指定地址下的数据并返回
}
/**
* 函 数:FLASH读取一个16位的半字
* 参 数:Address 要读取数据的半字地址
* 返 回 值:指定地址下的数据
*/
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{
return *((__IO uint16_t *)(Address)); //使用指针访问指定地址下的数据并返回
}
/**
* 函 数:FLASH读取一个8位的字节
* 参 数:Address 要读取数据的字节地址
* 返 回 值:指定地址下的数据
*/
uint8_t MyFLASH_ReadByte(uint32_t Address)
{
return *((__IO uint8_t *)(Address)); //使用指针访问指定地址下的数据并返回
}
/**
* 函 数:FLASH全擦除
* 参 数:无
* 返 回 值:无
* 说 明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在
*/
void MyFLASH_EraseAllPages(void)
{
FLASH_Unlock(); //解锁
FLASH_EraseAllPages(); //全擦除
FLASH_Lock(); //加锁
}
/**
* 函 数:FLASH页擦除
* 参 数:PageAddress 要擦除页的页地址
* 返 回 值:无
*/
void MyFLASH_ErasePage(uint32_t PageAddress)
{
FLASH_Unlock(); //解锁
FLASH_ErasePage(PageAddress); //页擦除
FLASH_Lock(); //加锁
}
/**
* 函 数:FLASH编程字
* 参 数:Address 要写入数据的字地址
* 参 数:Data 要写入的32位数据
* 返 回 值:无
*/
void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
FLASH_Unlock(); //解锁
FLASH_ProgramWord(Address, Data); //编程字
FLASH_Lock(); //加锁
}
/**
* 函 数:FLASH编程半字
* 参 数:Address 要写入数据的半字地址
* 参 数:Data 要写入的16位数据
* 返 回 值:无
*/
void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
FLASH_Unlock(); //解锁
FLASH_ProgramHalfWord(Address, Data); //编程半字
FLASH_Lock(); //加锁
}