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

STM32快速复习(十二)FLASH闪存的读写

文章目录

  • 一、FLASH是什么?FLASH的结构?
  • 二、使用步骤
    • 1.标准库函数
    • 2.示例函数
  • 总结


一、FLASH是什么?FLASH的结构?

1、FLASH简介

(1)STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程
(2)读写FLASH的用途:
利用程序存储器的剩余空间来保存掉电不丢失的用户数据
通过在程序中编程(IAP),实现程序的自我更新
(3)在线编程(In-Circuit Programming – ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序
(4)在程序中编程(In-Application Programming – IAP)可以使用微控制器支持的任一种通信接口下载程序

stm32寄存器地址介绍
在这里插入图片描述
闪存模块组织
在这里插入图片描述

在这里插入图片描述
FLASH基本结构
在这里插入图片描述
FLASH解锁

(1)FPEC共有三个键值:
RDPRT键 = 0x000000A5(解除读保护的秘钥)
KEY1 = 0x45670123
KEY2 = 0xCDEF89AB
(2)解锁:
复位后,FPEC被保护,不能写入FLASH_CR
在FLASH_KEYR先写入KEY1,再写入KEY2,解锁
错误的操作序列会在下次复位前锁死FPEC和FLASH_CR
(3)加锁:
设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR

使用指针访问存储器
(1)使用指针读指定地址下的存储器:
uint16_t Data = *((__IO uint16_t *)(0x08000000));
(2)使用指针写指定地址下的存储器:
*((__IO uint16_t *)(0x08000000)) = 0x1234;
(3)其中:
#define __IO volatile (易变的数据,防止编译器优化)


程序存储器

编程
在这里插入图片描述
在这里插入图片描述
页擦除
在这里插入图片描述
全擦除
在这里插入图片描述
选项字节
(1)选项字节
a.RDP:写入RDPRT键(0x000000A5)后解除读保护
b.USER:配置硬件看门狗和进入停机/待机模式是否产生复位
c.Data0/1:用户可自定义使用
d.WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)

2)选项字节编程
a.检查FLASH_SR的BSY位,以确认没有其他正在进行的编程操作
b.解锁FLASH_CR的OPTWRE位
c.设置FLASH_CR的OPTPG位为1(即将写入选项字节)
d.写入要编程的半字到指定的地址(指针写入操作)
e.等待BSY位变为0
f.读出写入的地址并验证数据

(3)选项字节擦除
a.检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
b.解锁FLASH_CR的OPTWRE位(选项字节里面有一个单独的解锁)
c.设置FLASH_CR的OPTER位为1(即将擦除选项字节)
d.设置FLASH_CR的STRT位为1(触发芯片,开始干活)
e.等待BSY位变为0
f.读出被擦除的选择字节并做验证

器件电子签名
(1)电子签名(ID号)存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名

(2)闪存容量寄存器:
基地址:0x1FFF F7E0
大小:16位

(3)产品唯一身份标识寄存器:
基地址: 0x1FFF F7E8
大小:96位

二、使用步骤

1.标准库函数

在这里插入图片描述

2.示例函数

代码如下(示例):

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Store.h"
#include "button.h"uint8_t KeyNum;int main(void)
{OLED_Init();Button_Init();Store_Init();//第一次使用时,初始化闪存,把闪存备份的数据加载回SRAM数组,实现SRAM数组上电不丢失OLED_ShowString(1,1,"Flag:");OLED_ShowString(2,1,"Data:");while(1){KeyNum = Button_GetNum();if(KeyNum ==1){Store_Data[1] ++;Store_Data[2] +=2;Store_Data[3] +=3;Store_Data[4] +=4;Store_Save();}if(KeyNum == 2){Store_Clear();}OLED_ShowHexNum(1,6,Store_Data[0],4);OLED_ShowHexNum(3,1,Store_Data[1],4);OLED_ShowHexNum(3,6,Store_Data[2],4);OLED_ShowHexNum(4,1,Store_Data[3],4);OLED_ShowHexNum(4,6,Store_Data[4],4);}
}

最底层:MyFLASH层

#include "stm32f10x.h"                  // Device header/*读取32位的字
*/
uint32_t MyFLASH_ReadWord(uint32_t Address)//地址必须是32位的
{return *((__IO uint32_t *)(Address));
}/*读取16位的半字
*/
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{return *((__IO uint16_t *)(Address));
}/*读取8位的字节
*/
uint8_t MyFLASH_ReadByte(uint32_t Address)
{return *((__IO uint8_t *)(Address));
}/*全擦除
*/
void MyFLASH_EraseAllPages(void)
{FLASH_Unlock();//解锁FLASH_EraseAllPages();//全擦除FLASH_Lock();//锁上
}/*页擦除
*/
void MyFLASH_ErasePage(uint32_t PageAddress)
{FLASH_Unlock();//解锁FLASH_ErasePage(PageAddress);//页擦除FLASH_Lock();//锁上
}/*编程写入一个字
*/
void MyFLASH_ProgramWord(uint32_t Address,uint32_t Data)
{FLASH_Unlock();//解锁FLASH_ProgramWord(Address,Data);//指定地址写字FLASH_Lock();//锁上
}	/*编程写入一个半字
*/
void MyFLASH_ProgramHalfWord(uint32_t Address,uint16_t Data)
{FLASH_Unlock();//解锁FLASH_ProgramHalfWord(Address,Data);//指定地址写半字FLASH_Lock();//锁上
}

Store.c

#include "stm32f10x.h"                  // Device header
#include "MyFLASH.h"#define STORE_START_ADDRESS 0x0800FC00
#define STORE_COUNT  		512uint16_t Store_Data[STORE_COUNT];void Store_Init(void)
{if(MyFLASH_ReadHalfWord(STORE_START_ADDRESS) !=0xA5A5){MyFLASH_ErasePage(STORE_START_ADDRESS);//擦除最后一页MyFLASH_ProgramHalfWord(STORE_START_ADDRESS,0xA5A5);//写入规定的标志位0xA5A5for(uint16_t i=1;i<STORE_COUNT;i++){MyFLASH_ProgramHalfWord(STORE_START_ADDRESS +i*2,0x0000);//写0}}for(uint16_t i=0;i<STORE_COUNT;i++)//在上电的时候,把闪存备份的地址的数据,恢复到SRAM数组里{Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS +i*2);//读闪存数据并存到SRAM数组里}}/*把SRAM的所有内容备份到闪存
*/
void Store_Save(void)
{MyFLASH_ErasePage(STORE_START_ADDRESS);//擦除最后一页for(uint16_t i=0;i<STORE_COUNT;i++)//在上电的时候,把闪存备份的地址的数据,恢复到SRAM数组里{MyFLASH_ProgramHalfWord(STORE_START_ADDRESS +i*2,Store_Data[i]);//把SRAM的所有内容备份到闪存的最后一页}
}	/*把SRAM的所有内容备份到闪存
*/
void Store_Clear(void)
{for(uint16_t i=1;i<STORE_COUNT;i++){Store_Data[i] = 0x0000;}Store_Save();//把这个更改更新到闪存里
}

偷个懒,用了别人的图片,还是要自己敲一下代码。才算学会


总结

偷个懒。。。。。。
存在问题
(1)目前闪存的前面部分存储的是程序文件,最后一页存储的是用户数据,如果程序较大,触及到了最后一页,那程序和用户数据存储的位置就冲突了,这时就可以给程序文件限定一个存储范围,不让它分配到后面我们用户数据的空间来
在这里插入图片描述
(2)配置下载选项,擦除扇区,用到多少就擦除多少,下载速度更快
在这里插入图片描述
(3)想知道目前程序编译后占多大空间
全部编译一下
在这里插入图片描述
or
或者双击Target1查看.map文件
在这里插入图片描述

相关文章:

STM32快速复习(十二)FLASH闪存的读写

文章目录 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f;二、使用步骤1.标准库函数2.示例函数 总结 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f; 1、FLASH简介 &#xff08;1&#xff09;STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&…...

漏洞扫描工具使用

首先把补丁的两个文件复制下来替换原文件 找到C:\ProgramData\Acunetix\shared\license然后替换 然后打开漏扫工具并刷新页面 然后添加要扫描的网站 等他扫描完成 扫描完成就可以生成报告了 一共五十多页的报告...

C++ | Leetcode C++题解之第424题替换后的最长重复字符

题目&#xff1a; 题解&#xff1a; class Solution { public:int characterReplacement(string s, int k) {vector<int> num(26);int n s.length();int maxn 0;int left 0, right 0;while (right < n) {num[s[right] - A];maxn max(maxn, num[s[right] - A]);i…...

利士策分享,动摇时刻的自我救赎

利士策分享&#xff0c;动摇时刻的自我救赎 在人生的长河中&#xff0c;我们每个人都会面临各种挑战与抉择&#xff0c; 那些让人心生动摇的瞬间&#xff0c;如同夜空中偶尔掠过的乌云&#xff0c;遮蔽了前行的星光。 但正是这些动摇&#xff0c;构成了我们成长的轨迹&#x…...

动手学深度学习(李沐)PyTorch 第 1 章 引言

在线电子书 深度学习介绍 安装 使用conda环境 conda create -n d2l-zh python3.8 pip安装需要的包 pip install jupyter d2l torch torchvision下载代码并执行 wget https://zh-v2.d2l.ai/d2l-zh.zip unzip d2l-zh.zip jupyter notebookpip install rise如果不想使用jupyt…...

二叉树(二)深度遍历和广度遍历

一、层序遍历 广度优先搜索&#xff1a;使用队列&#xff0c;先进先出 模板&#xff1a; 1、定义返回的result和用于辅助的队列 2、队列初始化&#xff1a; root非空时进队 3、遍历整个队列&#xff1a;大循环while(!que.empty()) 记录每层的size以及装每层结果的变量&a…...

【算法——双指针】

922. 按奇偶排序数组 II 算法讲解050【必备】双指针技巧与相关题目_哔哩哔哩_bilibili main:vector<int>nums { 3,1,2,4 };int i 0, j 1;int n nums.size() - 1;while (j < nums.size() && i < nums.size()) //如果奇偶任一方排好了&#xff0c;另…...

Rocky Linux 9 中添加或删除某个网卡的静态路由的方法

使用ip命令配置临时路由 添加静态路由 ip route add <目的网络> via <下一跳IP> dev <网卡接口名称>例: 给eth0网卡添加一个到达 192.168.2.0/24 网络&#xff0c;下一跳为 192.168.1.254 的路由 ip route add 192.168.2.0/24 via 192.168.1.254 dev eth0…...

网站建设中常见的网站后台开发语言有哪几种,各自优缺点都是什么?

市场上常见的网站后台开发语言有PHP、Python、JavaScript、Ruby、Java和.NET等。这些语言各有其独特的优缺点&#xff0c;适用于不同的开发场景和需求。以下是对这些语言的具体介绍&#xff1a; PHP 优点&#xff1a;PHP是一种广泛用于Web开发的动态脚本语言&#xff0c;特别适…...

【程序大侠传】应用内存缓步攀升,告警如影随形

前序 在武侠编码的江湖中&#xff0c;内存泄漏犹如隐秘杀手&#xff0c;潜伏于应用程序的各个角落&#xff0c;悄无声息地吞噬着系统资源。若不及时发现和解决&#xff0c;必将导致内存枯竭&#xff0c;应用崩溃。 背景&#xff1a;内存泄漏的由来 内存泄漏&#xff0c;乃程序…...

JavaWEB概述

JavaWEB概述 一、什么是JavaWEB 用Java技术解决web互联网领域的技术栈。要学习JavaWEB首先得知道什么是客户端和服务端 客户端&#xff1a;简而言之&#xff0c;这就是使用方&#xff0c;比如我们下载一个软件去使用&#xff0c;里面有很多我们可以使用的功能&#xff0c;那…...

半结构化知识抽取案例

半结构化知识抽取是指从半结构化数据源&#xff08;如HTML、XML、JSON等&#xff09;中提取有用的信息&#xff0c;并将其转换为更易于理解和使用的知识形式。半结构化数据通常包含一些结构化的标记或标签&#xff0c;但不像完全结构化的数据那样严格。 比如抽取如下网页到neo …...

Oracle Truncate和delete的区别

DropTruncatedelete语句类型 DDl &#xff08;数据定义语言 Data Definition Language DDl &#xff08;数据定义语言 Data Definition Language DML&#xff08;数据操作语言 Data Manipulation Language 速度 快 删除整个表 快 一次性删除 慢 逐行删除 回滚不可不可可del…...

应用层协议 --- HTTP

序言 在上一篇文章中&#xff0c;我们在应用层实现了一个非常简单的自定义协议&#xff0c;我们在我们报文的首部添加了报文的长度并且使用特定的符号分割。但是想做一个成熟&#xff0c;完善的协议是不简单的&#xff0c;今天我们就一起看看我们每天都会用到的 HTTP协议 。 UR…...

网卡Network Interface Card

文章目录 网卡&#xff08;Network Interface Card&#xff0c;简称NIC&#xff09;是一种计算机硬件设备&#xff0c;用于将计算机连接到计算机网络&#xff0c;使计算机能够进行数据通信。它是计算机与外部网络&#xff08;如局域网、互联网&#xff09;之间的接口&#xff0…...

9.1 Linux_I/O_基本知识

文件类型 一切I/O皆文件&#xff0c;文件就是存放在磁盘上面的有序数据的集合。 文件类型&#xff1a; 常规文件 r &#xff1a;就是普通文件目录文件 d &#xff1a;就是目录&#xff0c;是一个索引字符设备文件 c &#xff1a;键盘、鼠标块设备文件 b &#xff1a;U盘、磁…...

[Java]一、面向对象核心编程思想

G:\Java\1.JavaSE 1. 继承 1.1 继承的概述 重点内容:1.知道继承的好处2.会使用继承3.知道继承之后成员变量以及成员方法的访问特点4.会方法的重写,以及知道方法重写的使用场景5.会使用this关键字调用当前对象中的成员6.会使用super关键字调用父类中的成员7.会定义抽象方法以…...

科研绘图系列:R语言多个AUC曲线图(multiple AUC curves)

文章目录 介绍加载R包导入数据数据预处理画图输出结果组图系统信息介绍 多个ROC曲线在同一张图上可以直观地展示和比较不同模型或方法的性能。这种图通常被称为ROC曲线图,它通过比较不同模型的ROC曲线下的面积(AUC)大小来比较模型的优劣。AUC值越大,模型的诊断或预测效果越…...

JavaWeb--纯小白笔记06:使用Idea创建Web项目,Servlet生命周期,注解,中文乱码解决

使用Idea创建一个web项目----详细步骤配置&#xff0c;传送门&#xff1a;http://t.csdnimg.cn/RsOs7 src&#xff1a;放class文件 web&#xff1a;放html文件 out&#xff1a;运行过后产生的文件 一创建一个新的web项目(配置好了后)&#xff1a; 在src创建一个文件…...

jQuery——jQuery的2把利器

1、jQuery 核心函数 ① 简称&#xff1a;jQuery 函数&#xff0c;即为 $ 或者 jQuery ② jQuery 库向外直接暴露的是 $ 或者 jQuery ③ 引入 jQuery 库后&#xff0c;直接使用 $ 即可 当函数用&#xff1a;$&#xff08;xxx&#xff09; 当对象用&#xff1a;$.xxx&#x…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...