当前位置: 首页 > news >正文

STM32F407实现内部FLASH的读写功能

文章目录

  • 前言
  • 一、FLASH 简介
  • 二、读数据
  • 三、写数据
  • 四、最终效果
  • 五、完整工程


前言

我们通过仿真器下到芯片的程序一般会保存到eflash里面,在我们的STM32F407里面这里的空间挺大的,我所使用的芯片型号是STM32F407ZGT6,FLASH 容量为 1024K 字节。不同的项目会选择不同的芯片进行开发。

一、FLASH 简介

FLASH 是 EEPROM 的一种,是带电可擦除可编程的只读存储器,本文特指 STM32 内部的 Flash,主要用于存储用户程序代码以及必要的配置信息。
特性:
非易失性:数据在断电后依旧存储在数据中,适合存储程序代码和关键配置信息。
快速访问:FLASH 具有较快的读取速度
较长寿命:一般的 FLASH 可擦除约十万次
先擦再写:FLASH 的写操作只能将数据位从 1 写成 0,而不能从 0 写成 1,如果一个数据位已经写成 0 了,那 FLASH 必须先将该位所处的扇区或区块先擦除,才能重新写入。
FLASH 的擦除操作其实就是将对应扇区、区块或者全部区块的数据位全擦除为 1,所以FLASH的默认值是0xFF.

在这里插入图片描述
STM32F4 的闪存模块由:主存储器、系统存储器、OPT 区域和选项字节等 4 部分组成。 主存储器,该部分用来存放代码和数据常数(如 const 类型的数据)。分为 12 个扇区,前 4个扇区为 16KB 大小,然后扇区 4是 64KB 大小,扇区5~11 是 128K 大小,不同容量的 STM32F4,拥有的扇区数不一样,比如我们的 STM32F407ZGT6,则拥有全部 12 个扇区。从上图可以看出主存储器的起始地址就是 0X08000000, B0、B1 都接 GND 的时候,就是从 0X08000000 开始运行代码的。
系统存储器,这个主要用来存放 STM32F4 的 bootloader 代码,此代码是出厂的时候就固化在 STM32F4 里面了,专门来给主存储器下载代码的。当 B0 接 V3.3,B1 接 GND 的时候,从该存储器启动(即进入串口下载模式)。
OTP 区域,即一次性可编程区域,共 528 字节,被分成两个部分,前面 512 字节(32 字节为 1 块,分成 16 块),可以用来存储一些用户数据(一次性的,写完一次,永远不可以擦除!!),后面 16 字节,用于锁定对应块。
在没有使用IAP功能的时候我们的程序一般会从0x08000000开始,当然也可以从其他的地址开始,可以在KEIL的魔术棒的target中设置,具体如下图:
在这里插入图片描述
图中框起来的内容前面是起始地址后面是大小,我这里设置的是从0x08000000到0x08100000也就是我们在flash中可存储数据的全部空间1024K 。

二、读数据

STM23F4 的 FLASH 读取是很简单的。例如,我们要从地址 addr,读取一个字(字节为 8位,半字为 16 位,字为 32 位),可以通过如下的语句读取:
data=(vu32)addr;
将 addr 强制转换为 vu32 指针,然后取该指针所指向的地址的值,即得到了 addr 地址的值。类似的,将上面的 vu32 改为 vu16,即可读取指定地址的一个半字。
代码如下:

void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)   	
{u32 i;for(i=0;i<NumToRead;i++){pBuffer[i]=STMFLASH_ReadWord(ReadAddr);//读取4个字节.ReadAddr+=4;//偏移4个字节.	}
}u32 STMFLASH_ReadWord(u32 faddr)
{return *(vu32*)faddr; 
}  

在STMFLASH_Read函数中调用的是STMFLASH_ReadWord,在for循环中每次读取四字节保存到buf中。

三、写数据

STM32F4 的闪存编程由 6 个 32 位寄存器控制,他们分别是:
⚫ FLASH 访问控制寄存器(FLASH_ACR)
⚫ FLASH 秘钥寄存器(FLASH_KEYR)
⚫ FLASH 选项秘钥寄存器(FLASH_OPTKEYR)
⚫ FLASH 状态寄存器(FLASH_SR)
⚫ FLASH 控制寄存器(FLASH_CR)
⚫ FLASH 选项控制寄存器(FLASH_OPTCR)
STM32F4 复位后,FLASH 编程操作是被保护的,不能写入 FLASH_CR 寄存器;通过写入特定的序列(0X45670123 和 0XCDEF89AB)到 FLASH_KEYR 寄存器才可解除写保护,只有在写保护被解除后,我们才能操作相关寄存器。
FLASH_CR 的解锁序列为:
1, 写 0X45670123 到 FLASH_KEYR
2, 写 0XCDEF89AB 到 FLASH_KEYR
通过这两个步骤,即可解锁 FLASH_CR,如果写入错误,那么 FLASH_CR 将被锁定,直到下次复位后才可以再次解锁。
STM32F4 的 FLASH 在编程的时候,也必须要求其写入地址的 FLASH 是被擦除了的(也就是其值必须是 0XFFFFFFFF),否则无法写入。STM32F4 的标准编程步骤如下:
1,检查 FLASH_SR 中的 BSY 位,确保当前未执行任何 FLASH 操作。
2,将 FLASH_CR 寄存器中的 PG 位置 1,激活 FLASH 编程。
3,针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作:
—并行位数为 x8 时按字节写入(PSIZE=00)
—并行位数为 x16 时按半字写入(PSIZE=01)
—并行位数为 x32 时按字写入(PSIZE=02)
—并行位数为 x64 时按双字写入(PSIZE=03)
4,等待 BSY 位清零,完成一次编程。
代码如下:

void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)	
{ FLASH_Status status = FLASH_COMPLETE;u32 addrx=0;u32 endaddr=0;	if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;	//非法地址FLASH_Unlock();									//解锁 FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存addrx=WriteAddr;				//写入的起始地址endaddr=WriteAddr+NumToWrite*4;	//写入的结束地址if(addrx<0X1FFF0000)			//只有主存储区,才需要执行擦除操作!!{while(addrx<endaddr)		//扫清一切障碍.(对非FFFFFFFF的地方,先擦除){if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区{   status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!!if(status!=FLASH_COMPLETE)break;	//发生错误了}else addrx+=4;} }if(status==FLASH_COMPLETE){while(WriteAddr<endaddr)//写数据{if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据{ break;	//写入异常}WriteAddr+=4;pBuffer++;} }FLASH_DataCacheCmd(ENABLE);	//FLASH擦除结束,开启数据缓存FLASH_Lock();//上锁
} 

四、最终效果

在这里插入图片描述

在上图可以看到在0x0800C004这个地址开始写入了数据,就是const u8 TEXT_Buffer[]={“STM32 FLASH TEST”};这个内容只不过是16进制。
在这里插入图片描述
将存进去的数据再读出来,通过串口打印。

五、完整工程

我用夸克网盘分享了「FLASH读写.rar」
链接:https://pan.quark.cn/s/b544c17570f1

相关文章:

  • 【MySQL】MySQL数据库 —— 简单认识
  • 第3篇:深入 Framer Motion Variants:掌握组件动画编排的艺术
  • django项目之添加资产信息功能
  • YOLOv3模型架构与原理详解
  • Python 冷门魔术方法
  • Redis 高可用集群搭建与优化实践
  • 波束形成(BF)从算法仿真到工程源码实现-第十节-非线性波束形成
  • vue中使用swiper坑记录
  • 二、The Power of LLM Function Calling
  • 京东商品详情API接口调用讲解(实战案例)
  • Day56 | 99. 恢复二叉搜索树、103. 二叉树的锯齿形层序遍历、109. 有序链表转换二叉搜索树、113. 路径总和 II
  • 使用openpyxl时的一些注意点
  • 1.2 腾讯校招通关指南-面试官评分标准:技术岗/产品岗核心考核点揭秘
  • 【自相关】全局 Moran’s I 指数
  • OPPO Android 移动设备日志文件目录结构及其内容分析
  • git合并分支原理
  • 适合stm32 前端adc使用的放大器芯片
  • jetson orin nano 开发板conda 的 base 环境在 shell 启动时自动激活
  • 如何解决服务器文件丢失或损坏的问题?
  • JAVA学习-Stream
  • 加快从数量增长向品质跃升转变,促进生态空间与城市功能有机共生!龚正调研公园城市建设工作
  • 天工摘得全球首个人形机器人半马冠军:中国机器人产业正努力跑向人机共生社会
  • 华夏幸福:累计未能如期偿还债务金额合计为227.91亿元
  • 观察|如何推动再保险交易规模上量增加话语权,行业在临港新片区共倡议
  • “一城双白金”就在脚下!这场半马将以最高标准打造
  • 重庆警方通报“货车轮胎滚进服务区致人死亡”:正进一步调查