STM32实现掉电保存多个数据(FLASH)

本文介绍如何在STM32上实现掉电数据保存,包括初步认识Flash、Flash写入多个数及读取存储数值。文章详细讲解了在STM32闪存中存储数据的过程,包括写入和读取数据的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STM32实现掉电保存多个数据

本篇文章的具体内容:
1. 初步认识Flash
2. Flash写入多个数
3. 读取Flash中存储的数值

一、初步认识FLASH

如果想要实现掉电存储,首要的任务就是找到一个地方可以存放这些数据,当这些数据发生改变的时候,把数据存放进去,并且保证上电后不会被擦除。这么一来,等在次上电之后,通过读取掉电前存储的数据,实现掉电存储功能。
可以存放数据的地方可分为在两种片上flash和片外flash,常见的片上闪存有EEPROM,片外的存储芯片有W25QXXX。本篇文章使用的是直接在FLASH中存储。根据不同的芯片类型,闪存的大小都是不一样的。如下图(其他博客截取来的):
在这里插入图片描述
主控芯片的内存一般可分为8块:存放初始化程序的固化部分、数据段、代码段、堆空间、栈空间等。掉电存储数据的地方在第0块中的某个位置(0X0800 0000 ~0X0808 0000,这个的大小对应芯片闪存大小)只要存放的数据不超出这个范围,一切都好说。

二、FLASH写入数据

通过对上面的了解,大概知道了存放的位置。之后就可以向这个位置里面为所欲为啦?当然不是。下面以STM32标准库为例,你需要在工程里面加入stm32f10x_flash.c文件,这个文件抱恨了很多对flash操作的方法,我们只需要调用这些方法才可以为所欲为。(膜拜驱动大佬)。
怎么实现为所欲为呢?一般有两种:读和写。
写入:检查状态–>解锁–>擦除–>写入–>上锁–>完事。
读取:解锁–>读取–>上锁–>完事。

/*
功能:向flash中写入数据
参数:addr:地址  flashdata1:写入的数据  len:写入长度
返回值:
 */
void FLASH_WriteByte(u32 addr ,uint64_t *flashdata1,uint8_t len)
{
	
		int i = 0;
	
		FLASH_Status FLASHstatus = FLASH_COMPLETE;
		FLASH_Unlock(); //解锁flash

		FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);  //清除标志位

		FLASHstatus=FLASH_ErasePage(addr);   //擦除指定地址页
		
		for(i=0; i<len;i++)
		{
			FLASHstatus=FLASH_ProgramHalfWord(addr+i*4, flashdata1[i]);//从指定的地址写入数据
		}
		FLASH_Lock();//上锁 
}

有了这个函数之后,在封装一个函数,把想要存储的变量数据对应放到一个数组里面,然后将整一个数组写到flash中,实现最终的写入功能。

三、读取FLASH中存储的数据

通过上面的写入函数,就可以把数据写入到flash中了,之后找到同一个地址,将数据读取出来,读取的长度和写进去的长度一致,之后将数据存到一个数组当中,再将数组的值对应赋值给保存进来的时的变量,就可以实现读取功能。

/*
功能:读取FLASH中指定地址的值
参数:addr:起始地址  len:读取的长度
返回值:无
 */
void Read_Flash(uint32_t addr,uint8_t len)
{
	
	uint64_t NEW_ParArry[13] = {0};
	u8 i=0;
	
	uint64_t rdata = 0;
	
	FLASH_Unlock();//解锁flash
	
	for(i=0;i<len;i++)
	{
		NEW_ParArry[i] = *(u16 *)(addr + i*4);    //读取flash地址中的值
	}
	
	FLASH_Lock();//上锁
	
/*********** 重新赋值给变量 ********/		
	
	S_num = NEW_ParArry[0];
    F_num	= NEW_ParArry[1];
	R_num = NEW_ParArry[2];
	total = NEW_ParArry[3];  
	
	I_reg  = NEW_ParArry[4];
	VL_reg = NEW_ParArry[5];
	VH_reg = NEW_ParArry[6]; 
	T_reg  = NEW_ParArry[7]; 
	
	line1 = NEW_ParArry[8];
	line2 = NEW_ParArry[9];
	line3 = NEW_ParArry[10];
	line4 = NEW_ParArry[11];
	line5 = NEW_ParArry[12];
}

最后,只需要在主程序中的适当位置,调用闪存写入函数(一般是当数据发生改变时写入)。但尽量减少写入的次数,flash的读写次数在十万次左右。
STM32实现掉电保存功能的详细工程
点击即可跳转下载。
https://download.youkuaiyun.com/download/janson_24/12629396

STM32是一款基于ARM Cortex-M内核的微控制器,广泛应用于工业控制、智能家居等嵌入式系统设计领域。由于这些应用场景中常常需要在断电后仍能保留关键数据,因此STM32Flash存储器操作成为了一个重要环节,尤其是如何实现掉电数据保存。本文将深入探讨STM32实现多个数据掉电保存Flash的方法,并通过分析提供的“flash”文件来理解其具体实现方式。 STM32Flash存储器是一种非易失性存储区域,即使在电源切断后,存储在其中的数据也不会丢失。不过,Flash存储器的擦写次数是有限的,因此在进行写入操作时需要谨慎,以延长其使用寿命。实现掉电保存功能通常需要以下步骤: 首先,需定义存储结构,明确要保存数据类型和数量,并创建相应的数据结构。例如,若要保存多个整数,可定义一个整数数组。其次,选择一个安全的存储位置,避免覆盖固件或系统重要信息。STM32的用户可编程Flash区域一般从0x08000000地址开始。接着,编写写入函数,该函数要处理Flash的擦除、校验及错误检查等操作。STM32的HAL库提供了HAL_FLASH_Program系列函数用于Flash编程,在写入前需确保数据已正确格式化。然后,创建读取函数,用于从Flash恢复数据,该函数可根据读取数据的个数动态调整,通过参数指定读取的起始地址和长度。 此外,还需考虑异常处理,以确保在系统掉电或意外关机时数据的完整性。可以在中断服务例程中保存关键状态,或者在程序运行过程中定期将数据备份到Flash。同时,为防止数据被篡改,可以引入安全策略,例如通过特定密钥进行加密或签名来实现访问控制。 在提供的“flash”文件中,可能包含了Flash初始化、写入和读取函数以及数据保存结构的具体代码示例。通过分析这些代码,能够更深入地理解STM32如何实现有效的掉电保护功能。 总之,STM32实现掉电保存F
### STM32实现断电保存功能 在STM32微控制器中,实现断电保存数据的功能通常有两种主要方式:使用内部Flash存储器或外部EEPROM芯片。以下是两种方法的具体介绍。 #### 一、使用内部Flash存储器 STM32的内部Flash是一种非易失性存储器,在电源关闭后仍能保持数据不变。然而,需要注意的是,Flash的擦写寿命有限(一般为10万次左右)。因此,频繁写入操作可能会影响其可靠性[^1]。 为了减少磨损并提高效率,可以采用分页管理的方式。具体做法如下: - 将需要保存数据分配到固定的Flash页面。 - 在每次更新前先读取旧数据,再将其覆盖至新位置。 - 如果某一页接近使用寿命,则切换到备用页面继续记录。 这种方法虽然简单有效,但在实际应用中有一定局限性——比如执行速度较慢以及存在上述提到的风险等问题。所以当面对高频率更改需求时需谨慎考虑此选项[^2]。 ```c // 示例代码展示如何向指定地址写入字节 void Flash_Write(uint32_t Address, uint8_t Data){ HAL_FLASH_Unlock(); // 解锁flash访问权限 FLASH_EraseInitTypeDef EraseInitStruct; uint32_t PAGEError; /* 配置要清除区域 */ EraseInitStruct.TypeErase = TYPEERASE_PAGES; EraseInitStruct.PageAddress = Address & (uint32_t)(~(FLASH_PAGE_SIZE - 1)); EraseInitStruct.NbPages = 1; if(HAL_OK != HAL_FLASHEx_Erase(&EraseInitStruct,&PAGEError)){ Error_Handler(); } *(__IO uint8_t*)Address = Data ; HAL_FLASH_Lock(); // 锁定flash防止误修改 } ``` #### 二、利用外部I²C接口连接独立型EEPROM器件 相比起内置资源而言,外接专用集成电路(IC)如AT24CXX系列提供了更大的容量与更高的耐久度。它们通过标准串行总线通信协议(I²C/SPI),允许主机设备轻松存取远程节点上的任意单元格内容而无需额外逻辑电路支持。 不过值得注意的一点在于初始化阶段必须正确设置SCL/SDA管脚模式及其上下拉电阻参数;另外还要留意工作电压范围是否匹配目标平台供电规格以免损坏元件或者造成不可预期的行为表现出来[^3]。 下面给出一段基于库函数完成基本读写的例子供参考: ```c #include "stm32f1xx_hal.h" #define EEPROM_I2C_ADDR 0xA0 << 1 // 设备地址左移一位得到7bit形式 #define WRITE_DELAY_MS 5 // 延迟时间确保写入成功 /** * @brief 向eeprom特定偏移量处写入单字节数据. */ HAL_StatusTypeDef eeprom_write_byte(uint16_t MemAddr,uint8_t data){ return HAL_I2C_Mem_Write(&hi2c1,(uint16_t)EEPROM_I2C_ADDR, MemAddr,I2C_MEMADD_SIZE_8BIT,&data,sizeof(data),WRITE_DELAY_MS); } /** * @brief 从eeprom特定偏移量处读取单字节数据. */ HAL_StatusTypeDef eeprom_read_byte(uint16_t MemAddr,uint8_t *pdata){ return HAL_I2C_Mem_Read(&hi2c1,(uint16_t)EEPROM_I2C_ADDR, MemAddr,I2C_MEMADD_SIZE_8BIT,pdata,sizeof(*pdata),WRITE_DELAY_MS); } ``` 综上所述,无论是选择哪种途径达成目的都各有优劣之处,开发者应依据项目实际情况做出合理判断后再行动实施最佳策略组合起来运用最为理想状态下的解决方案才是王道!
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值