Flash读写

FLASH简单的读、写操作

主存储器是以页为单位划分的。stm32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。

在这里插入图片描述

  • 主存储块用于保存具体的程序代码和用户数据。起始地址0x08000000,b0和b1接GND从这里开始执行程序。
  • 信息块用于负责由stm32出厂时放置2KB的启动程序(BootLoader)和512B的用户配置信息区。启动程序代码,是用来存储 ST 自带的启动程序,b0接3.3v,b1接GND运行的就是这部分代码 ,用作串口下载代码。
  • 闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制机构 。在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理 。
操作流程(详见STM32F1 开发指南(精英板-库函数版) )
  1. 检查 FLASH_CR 的 LOCK 是否解锁,如果没有则先解锁
  2. 检查 FLASH_SR 寄存器的 BSY 位,以确认没有其他正在进行的闪存操作
  3. 设置 FLASH_CR 寄存器的 PER 位为’ 1’
  4. 用 FLASH_AR 寄存器选择要擦除的页
  5. 设置 FLASH_CR 寄存器的 STRT 位为’ 1’
  6. 等待 BSY 位变为’ 0’
  7. 读出被擦除的页并做验证
库函数级的操作流程
  1. 确定要写入Flash的首地址(稍后介绍确定地址的方法)
  2. 解锁Flash
  3. 对Flash进行操作(写入数据)
  4. 对Flash重新上锁

要想选定安全的Flash地址进行读写,可以根据自己的STM32 MCU型号,查找数据手册,确定FLASH的地址区段,因为起始段会存储代码,所以一定要避开起始段,以避免数据错误。(我一般是根据Flash大小计算Flash的最末尾地址,往前推一段地址空间,在这里一般不会对代码中的数据产生覆盖等影响)这里采用的是STM32F103(大容量产品)写入的首地址为0x0807F800;

  • 添加STM32 flash底层固件库文件stm32f10x_flash.c

编写自己的Flash驱动库文件,如下

Flash.h
#ifndef __FLASH_H
#define __FLASH_H 			   
#include "sys.h"
 

void FLASH_W(u32 add,u16 dat);
u16 FLASH_R(u32 add);

#endif
Flash.c
#include "flash.h"

//FLASH写入数据
void FLASH_W(u32 add,u16 dat){ //参数1:32位FLASH地址。参数2:16位数据
//	 RCC_HSICmd(ENABLE); //打开HSI时钟
	 FLASH_Unlock();  //解锁FLASH编程擦除控制器
     FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位
     FLASH_ErasePage(add);     //擦除指定地址页
     FLASH_ProgramHalfWord(add,dat); //从指定页的addr地址开始写
     FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位
     FLASH_Lock();    //锁定FLASH编程擦除控制器
}

//FLASH读出数据
u16 FLASH_R(u32 add){ //参数1:32位读出FLASH地址。返回值:16位数据
	u16 a;
    a = *(u16*)(add);//从指定页的addr地址开始读
return a;
}
main.c
#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h" 

#include "flash.h" 

#define FLASH_START_ADDR  0x0807F800	  //写入的起始地址


int main (void){//主程序
	u8 key;
	u16 a; //定义变量
	//初始化程序
	RCC_Configuration(); //时钟设置
	LED_Init();//LED初始化
	KEY_Init();//按键初始化

  a = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH

	//GPIO_Write(LEDPORT,a); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)

	//主循环
	while(1){
		key = KEY_Scan(0);
		if(key == WK_UP_PRES){
				a++;
				if(a>1)a=0;
				FLASH_W(FLASH_START_ADDR,a);
		}else{
				delay_ms(10);
		}
		LED0=a;
		
    }
}
Flash操作注意事项:
  1. 操作一定要先擦后写
  2. 每页是1024个地址,起始地址0x08000000
  3. 擦除操作以页为单位,写操作必须以16位宽度为单位,允许跨页写入。
  4. STM32内置Flash擦或写时,必须打开外部/内部高速振荡器。
  5. Flash可最多擦写10万次,不可死循环擦写。
  6. 擦写时要避开用户程序存储的区域,否则会擦掉用户程序导致错误。
  7. 擦除一页要10ms(对于1k大小的一页),比较慢,而且不能单个字节的擦写。
  • 8
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值