【STM32】读写stm32的内置Flash(附代码)

最近尝试了一下对32的内置flash进行读写,众所周知,芯片的flash是用来存放代码指令和变量的,其中的数据即使掉电也不会丢失。而stm32的flash之大,对于初学者的小打小闹完全不用担心不够用的情况。

因此,在需要保存一些芯片掉电之后依旧需要保存的数据(数据量不是特别大)时,运用内置flash的空闲部分可以为我们省去一颗eeprom或外置flash的花销。


知识总结:

1.flash的写入之前需要先擦除,且擦除是直接擦除一页(2KBytes),整个流程为

(1)解锁flash(2)擦除一页或多页(3)写数据(4)锁定flash

2.flash正常写入一次是16bit

3.flash的地址从0x08000000开始,存储代码指令与变量。所以在用户自己写flash时,要注意不要把代码指令与变量给覆盖了。查看编译过的代码使用了多少内存,可在Keil中双击工程名查看*.map文件

基地址加上Size就是代码指令与变量占用的空间。在写入用户数据时,要避开这些地方。

以下是基于正点原子库函数的flash读写代码。在STM32F103RCT6测试通过。可以直接复制使用,好用请为博客点个赞!

flash.h:

#ifndef _FLASH_H
#define _FLASH_H

#include "stm32f10x.h"

extern uint32_t Flash_EraseWriteOnePage(uint32_t WRITE_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress);
extern void Flash_ReadOnePage(uint32_t READ_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress);

#endif

flash.c

/////////////////////////////////////////
//Author: Read Air
//Version: 1.0
//Date:2019/4/18
/////////////////////////////////////////

#include "flash.h"
#include "stm32f10x.h"
///////////////////////////////////////////////////////
//WRITE_START_ADDR 	-- 开始写的地址
//SizeOf_u32 		-- 要写入的32位(双字)的数量
//DataAddress		-- 等待被写入的数据数组(32位的)
//返回值			-- 出现擦除失败故障返回写入地址,正常返回0
///////////////////////////////////////////////////////
uint32_t Flash_EraseWriteOnePage(uint32_t WRITE_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress)
{
	char EraseCounter = 0;
	static FLASH_Status FLASHStatus;
	uint32_t Address;
	u16 Remain_u32 = SizeOf_u32;
	u8 err_time=0;
	/* 解锁 */
	FLASH_Unlock();
	/* 清空所有标志位 */
	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
	/* 擦除一页*/
	FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR);
	/* 尝试擦除*/
	while((FLASHStatus != FLASH_COMPLETE)&&(err_time<5))
	{
		FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR);
		err_time++;
	}
	/* 擦除失败*/
	if (err_time >= 5) return WRITE_START_ADDR;
	/* 向内部 FLASH 写入数据 */
	Address = WRITE_START_ADDR;
	while ((Remain_u32 > 0) && (FLASHStatus == FLASH_COMPLETE)) 
	{
		FLASHStatus = FLASH_ProgramWord(Address, DataAddress[SizeOf_u32-Remain_u32]);
		Address = Address + 4;
		Remain_u32--;
	}
	/* 锁定*/
	FLASH_Lock();
	return 0;
}

///////////////////////////////////////////////////////
//READ_START_ADDR 	-- 开始写的地址
//SizeOf_u32 		-- 要读出的32位(双字)的数量
//DataAddress		-- 等待被读出的数据数组(32位的)
///////////////////////////////////////////////////////
void Flash_ReadOnePage(uint32_t READ_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress)
{	
	uint32_t Address;
	u16 Remain_u32 = SizeOf_u32;
	/* 检查写入的数据是否正确 */
	Address = READ_START_ADDR;
	while ((Remain_u32 > 0)) 
	{
		 DataAddress[SizeOf_u32-Remain_u32] = (*(__IO uint32_t*) Address);
		Address += 4;
		Remain_u32--;	
	}
}

//注意事项: 
//1、对flash进行写入操作,一定要遵循“先擦除,后写入”的原则 
//2、注意到stm32内置flash的擦除操作都是以页为单位进行,而写入操作则必须以16位半字宽度数据为单位,允许跨页写,尝试写入非16位半字数据将导致stm32内部总线错误。 
//3、进行stm32的内置flash编程操作时(写或擦除),必须打开内部的RC振荡器(HSI) 
//4、注意stm32的内置flash最多只有10万次重复擦写的生命周期,谨记切勿在程序中放任死循环对flash进行持续地重复擦写。

发布了44 篇原创文章 · 获赞 203 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/ReadAir/article/details/89389700