当前位置: > 财经>正文

STM32操作访问flash,包括写入数据到flash和从flash读取数据 保险金信托的操作流程包括哪些内容呢图片

2023-09-09 02:50:14 互联网 未知 财经

STM32操作访问flash,包括写入数据到flash和从flash读取数据

文章目录 序言:flash相关知识背景一、FLASH操作流程与操作选址1.1 FLASH操作流程1.2 如何查找并选定要写入Flash十六进制地址 二、Flash基本知识点2.1 Flash容量2.2 ST库对Flash操作的支持 三、OK,上干货,上代码3.1 先定义一个Flash操作的**起始地址宏定义**和**Flash状态指示标志位**3.2 编写各个读写函数

序言:flash相关知识背景

STM32中存储区分为:随机存取存储器RAM和只读存储器ROM。 其中:

RAM为常说的内存,比如手机的2G内存4G内存等,就是程序跑起来的时候所占用的存储空间,特点是掉电数据丢失。ROM为常说的硬盘,比如手机的64G和128G等,可以简单的理解为硬盘的存储空间,特点是掉电数据不丢失,所以又叫“非易失性存储器件”。ROM又包含:EEPROM和flash。

画个嵌入式产品存储器件的思维导图如下(如有什么地方不对,恳请大神们进行指正):

作为ROM的一份子,flash的特点自然是掉电数据不丢失。但是,flash在STM32中比较重要,程序也是保存在这个地方,所以轻易不让用户进行随意的读写,以避免不必要的问题。

而这篇博客就先简单记录一下flash的访问流程和方法(读和写),具体原理以后理解深刻了再做补充。

一、FLASH操作流程与操作选址 1.1 FLASH操作流程

Flash操作已经属于嵌入式设备中很底层的操作了,直接对地址进行存取,简单描述,Flash操作大致需要以下流程:

1、确定要写入Flash的首地址(稍后介绍确定地址的方法)2、解锁Flash3、对Flash进行操作(写入数据)4、对Flash重新上锁 1.2 如何查找并选定要写入Flash十六进制地址

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

我此次操作Flash使用的MCU是STM32F103C8T6,所以以该型号MCU为例进行描述:

在数据手册中,可以看到STM32F103C8T6的flash起始地址是0x0800 0000(如下图所示),而STM32F103C8T6的Flash大小为64K,可以计算出STM32F103C8T6的Flash地址范围是:0x0800 0000——0x0800 FFFF(计算方法参考另一篇博客:STM32内存大小与地址的对应关系以及计算方法)。这里选取0x0800 F000作为读写操作的起始地址,对于C8T6这款MCU,操作这个起始地址应该算是很安全的范围了。 二、Flash基本知识点 2.1 Flash容量

Flash根据容量大小可以分为以下三种:

1、小容量产品:Flash大小为1-32KB(STM32F10X_LD)2、中容量产品:Flash大小为64-128KB(STM32F10X_MD)3、大容量产品:Flash大小为256KB以上(STM32F10X_HD) 2.2 ST库对Flash操作的支持

ST库中对Flash操作主要提供了以下几类操作API函数:

1、Flash解锁、锁定函数 void FLASH_Unlock(void); //解锁函数:在对Flash操作之前必须解锁void FLASH_Lock(void); //锁定函数:同理,操作完Flash之后必须重新上锁 2、Flash写操作函数 FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); //32位字写入函数FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); //16位半字写入函数FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data); //用户选择字节写入函数

      注:这里需要说明,32 位字节写入实际上是写入的两次 16 位数据,写完第一次后地址+2,这与我们前面讲解的 STM32 闪存的编程每次必须写入 16 位并不矛盾。写入 8位实际也是占用的两个地址了,跟写入 16 位基本上没啥区别。

3、Flash擦除函数 FLASH_Status FLASH_ErasePage(uint32_t Page_Address);FLASH_Status FLASH_EraseAllPages(void);FLASH_Status FLASH_EraseOptionBytes(void); 4、获取Flash状态 FLASH_Status FLASH_GetStatus(void);

      获取Flash状态函数,主要是为了获取Flash的状态,以便于根据状态对Flash进行操作。该函数返回值是通过枚举类型定义的,在代码中可以看到FLASH_Status类型定义如下(具体含义看注释即可): *

typedef enum { FLASH_BUSY = 1, //忙 FLASH_ERROR_PG, //编程错误 FLASH_ERROR_WRP, //写保护错误 FLASH_COMPLETE, //操作完成 FLASH_TIMEOUT //操作超时}FLASH_Status; 5、等待操作完成函数 FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);

注:在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。所以在每次操作之前,我们都要等待上一次操作完成这次操作才能开始。

三、OK,上干货,上代码

根据ST库提供的上述函数,我们可以自己编写Flash的读写操作代码如下:

3.1 先定义一个Flash操作的起始地址宏定义和Flash状态指示标志位 #define STARTADDR 0x0800F000 //STM32F103C8T6适用volatile FLASH_Status FLASHStatus = FLASH_BUSY; //Flash操作状态变量 3.2 编写各个读写函数 /* * Name: WriteFlashOneWord * Function:向内部Flash写入32位数据 * Input: WriteAddress:数据要写入的目标地址(偏移地址) * WriteData: 写入的数据 */void WriteFlashOneWord(uint32_t WriteAddress, uint32_t WriteData){ FLASH_UnlockBank1(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASHStatus = 1; //清空状态指示标志位 FLASHStatus = FLASH_ErasePage(STARTADDR); if(FLASHStatus == FLASH_COMPLETE) { FLASHStatus = 1; //清空状态指示标志位 FLASHStatus = FLASH_ProgramWord(STARTADDR+WriteAddress, WriteData); //flash.c 中API函数 } FLASHStatus = 1; //清空状态指示标志位 FLASH_LockBank1(); }/* * Name: WriteFlashData * Function:向内部Flash写入数据 * Input: WriteAddress:数据要写入的目标地址(偏移地址) * data[]: 写入的数据首地址 * num: 写入数据的个数 */void WriteFlashData(uint32_t WriteAddress, uint8_t data[], uint32_t num){ uint32_t i = 0; uint16_t temp = 0; FLASH_UnlockBank1(); //解锁flash FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASHStatus = 1; //清空状态指示标志位 FLASHStatus = FLASH_ErasePage(STARTADDR);//擦除整页if(FLASHStatus == FLASH_COMPLETE)//flash操作完成{ FLASHStatus = 1; //清空状态指示标志位 for(i=0; i

版权声明: 本站仅提供信息存储空间服务,旨在传递更多信息,不拥有所有权,不承担相关法律责任,不代表本网赞同其观点和对其真实性负责。如因作品内容、版权和其它问题需要同本网联系的,请发送邮件至 举报,一经查实,本站将立刻删除。