STM32 实现内部Flash的读写(HAL库版)

  Flash 中文名字叫闪存,是一种长寿命的非易失性(断电数据不丢失)的存储器。可以对称为块的存储器单元块进行擦写和再编程,在进行写入操作之前必须先执行擦除。一个Nand Flash由多个块(Block)组成,每个块里面又包含很多页(page)。每个页对应一个空闲区域/冗余区域(spare area),这个区域不是用来存储数据的,用于放置数据的校验值检测和纠错的。块,是Nand Flash的擦除操作的基本/最小单位。页,是Nand Flash的写入操作的基本/最小的单位。

  首先简要写一下FLASH的读写流程:

对FLASH写入数据

解锁FLASH

擦除FLASH

写入数据到FLASH

锁住FLASH

FLASH读取数据 (直接读取相应的FLASH地址即可)

  操作MCU里的Flash,还有几个注意事项:

  1、往Flash写入数据的时候,要先对要写入的页进行擦除,如果要写的页里有数据,要先读出来在缓存区,再把页擦除,再写入数据;在擦除页之后,只要这次你写的数据大小不够一页,可以连续写入。

  2、要计算好程序的内存,因为你的程序也是保存在MCU的Flash里的,如果你操作到保存着程序的内存,程序就会死掉,至于程序内存怎么看,你可以生成bin文件,bin文件的大小就是你程序所占内存的大小了,生成bin文件可以参考博客:https://www.cnblogs.com/xingboy/p/10818813.html;程序内存基本都是从Flash内存一开始存起的,这里以STM32Fo72c8t6举例,如下图。

 

 

  看图可以看出,这个芯片的Flash内存范围是 0x0800 0000 ~ 0x0802 0000  ,假设我要烧录进去的bin文件为10K,那我们操作Flash的时候,地址就要从 0x0800 0000 +  (0x400*11) 开始,避开程序的存储位置,Flash地址偏移1位就是1个字节。

  3、要注意MCU一页的大小,一些MCU一页是1KB,一些MCU一页是2KB

   下面举个例子写入数据 0x0001 到Flash中:

uint16_t my_add = 0x0001;     uint32_t Robot_Num_Flash_Add = 0x08005000;  FLASH_EraseInitTypeDef My_Flash; //声明 FLASH_EraseInitTypeDef 结构体为 My_Flash HAL_FLASH_Unlock(); //解锁Flash My_Flash.TypeErase = FLASH_TYPEERASE_PAGES; //标明Flash执行页面只做擦除操作 My_Flash.PageAddress = Robot_Num_Flash_Add; //声明要擦除的地址 My_Flash.NbPages = 1; //说明要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最大页数-初始页的值)之间的值 uint32_t PageError = 0; //设置PageError,如果出现错误这个变量会被设置为出错的FLASH地址 HAL_FLASHEx_Erase(&My_Flash, &PageError); //调用擦除函数擦除 uint16_t Write_Flash_Data = my_add; HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Robot_Num_Flash_Add, Write_Flash_Data); //对Flash进行烧写,FLASH_TYPEPROGRAM_HALFWORD 声明操作的Flash地址的16位的,此外还有32位跟64位的操作,自行翻查HAL库的定义即可 HAL_FLASH_Lock(); //锁住Flash

  写完之后,接着就到读了,Flash写有次数限制,写的次数在1W次还是10W次(忘了)就不可写入了,而读是没有次数限制的,读多少次都可以,下面就把写入到Flash里的数据 0x0001 读出来

uint32_t Robot_Num_Flash_Add = 0x08005000;     ID_Num = *(__IO uint16_t*)( Robot_Num_Flash_Add ); //*(__IO uint16_t *)是读取该地址的参数值,其值为16位数据,一次读取两个字节,*(__IO uint32_t *)就一次读4个字节   printf("ID_num:0x%x\r\n", ID_Num);

  经过上面的程序就可以实现 STM32 中 Flash 数据的读写了,具体怎么读写,每个案子不同,各位就可以根据需求去修改,只要注意好注意事项即可,代码已经实测可用。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )