历史上的今天
今天是:2025年07月26日(星期六)
2019年07月26日 | 读写stm32的内置Flash(附代码)
2019-07-26 来源:eefocus
最近尝试了一下对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进行持续地重复擦写。
下一篇:STM32 flash读写源程序
史海拾趣
|
豪华的单片机开发系统498元 可稳定视频输出的: S3C2410 ARM9开发板780元DSP5402学习开发板II200元 暑期大优惠:S3C44B0开发板(标准版)350元 单片机以太网开发板 180元 DSP5402学习开发板II200元 LABTOOL-48UXP &nb ...… 查看全部问答> |
|
1、输入端与输出端的边线应避免相邻平行, 以免产生反射干扰。必要时应加地线隔离;两相邻层的布线要互相垂直,平行容易产生寄生耦合。 2、地线>电源线>信号线,通常信号线宽为:8mil~12mil;电源线为50mil~100mil。对数字电路 ...… 查看全部问答> |
|
EVC中是不是不支持settimer的SLIDER_TIMER参数?? EVC中是不是不支持settimer的SLIDER_TIMER参数?? mSliderTimer = SetTimer(SLIDER_TIMER, 100, NULL); 报错是:error C2065: \'SLIDER_TIMER\' : undeclared identifier… 查看全部问答> |
|
我写了一个很简单的程序,窗口上就两个按钮,用于动态分配和释放内存.打开WinCE.net的SystemProperties的Memory选项卡查看内存情况,发现分配可以,但按了释放内存的按钮却不能释放内存,不知原因,望高手指点!… 查看全部问答> |
|
报名参与:『ADI实验室电路DIY大赛』正式启动!https://bbs.eeworld.com.cn/thread-293726-1-1.html ADI实验室电路品种繁多,涉及面很广,如何选择合适的DIY项目可能是件容易令人困扰的事,但深究起来,其实可玩性是很大的,从今天开始,我将陆续 ...… 查看全部问答> |
|
大家帮看看为什么DeviceIoControl访问OID_802_11_BSSID_LIST老是失败 如题,下面一段程序中,DeviceIoControl访问OID_802_11_BSSID_LIST老是失败(见下面红色),也就是说bResult一直等于0;为什么?请教牛人!!!可能的问题出现在哪?为什么第二个DeviceIoControl失败?#include \"stdafx.h\"#include <windows.h ...… 查看全部问答> |
|
卓跃教育发现随着采用Android系统的谷歌手机、平板电脑等产品逐渐扩大市场占有率,Android平台人才的缺口日益显现。据业内统计,目前国内的3G研发人才缺口有三、四百万,其中Android研发人才缺口至少30万。&n ...… 查看全部问答> |




