FLASH代码部分

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操作核心规则
  1. STM32F10x 内部FLASH 最小操作单位为 半字(2字节),故读写均以半字为单位。

  2. FLASH 编程前必须先 擦除对应页(不能直接覆盖写入),擦除后所有位均为1(0xFFFF)。

  3. 地址计算:第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数组
	}
}
初始化关键流程
  1. 标志位判断:通过读取FLASH起始地址的半字数据,与自定义标志位 0xA5A5 对比,判断是否为第一次使用。

  2. 第一次初始化:擦除对应FLASH页 → 写入标志位 → 初始化所有有效数据为0x0000,完成FLASH初始化。

  3. 上电加载:无论是否为第一次使用,均将FLASH中存储的所有数据(包含标志位)加载到SRAM数组,确保程序运行时操作的是最新数据。


三. 核心函数用法

  1. Store_Init(参数存储模块初始化) void Store_Init(void);

    • 核心作用:初始化FLASH(第一次使用时),并将FLASH中的数据加载到SRAM数组 Store_Data,为后续参数读写做准备。

    • 使用时机:程序上电后,其他模块初始化完成后调用(如OLED、按键初始化后)。

  2. 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_Datai); //SRAM数组→FLASH

    }

    }`

    复制代码
    - 核心作用:将SRAM数组 `Store_Data` 中的所有数据(包含标志位),同步写入到内部FLASH,确保掉电后数据不丢失。
    
    - 核心流程:擦除FLASH页 → 逐一半字写入数据(因FLASH不能直接覆盖,需先擦除)。
    
    - 使用时机:当 `Store_Data` 数组中的参数修改后,需调用此函数保存(如参数设置完成后)。
  1. Store_Clear(有效数据清0)
  • 函 数:参数存储模块将所有有效数据清0

  • 参 数:无

  • 返 回 值:无

  • 核心功能:清0 SRAM数组有效数据,并同步到FLASH

    */

    void Store_Clear(void)

    {

    for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环清0(跳过第一个标志位,保留标志位)

    {

    Store_Datai = 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();							//加锁
}
相关推荐
wuqingshun3141595 小时前
请描述简单工厂模式的工作原理
java·简单工厂模式
anno5 小时前
Agent 新手 Skill 优先级指南:从第一套必装工作流,到专业能力补全
前端·后端
大不点wow5 小时前
Spring 中 @Bean、@Component 与 @Configuration 的作用及底层逻辑
java·spring
anno5 小时前
别再把文档“一刀切”:用 LangChain.js 做好 RAG 的第一公里
前端·后端
用户713874229005 小时前
claude_rules 深度解析:Claude Code 的模块化路径作用域规则
后端
IvorySQL5 小时前
云环境下PostgreSQL的Cgroup内存管理实践
java·数据库·postgresql
卡卡罗特AI5 小时前
曾经狂推的 Superpowers,今天我终于把它卸载了! 臃肿,Token吞金兽!
后端·chatgpt·ai编程
不定积分要+C_yyy5 小时前
Java基础核心精讲:基本数据类型与包装类区别、自动装箱拆箱与缓存陷阱实战解析
java·开发语言
jvmind_dev5 小时前
第三章:GC 日志深度分析(上)——多版本、多收集器的统一解析
java·agent
xingxiliang5 小时前
ReliableAgent:类似工程级可用的agent示例
java·开发语言·agent