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是什么?FLASH的结构?二、使用步骤1.标准库函数2.示例函数 总结 一、FLASH是什么?FLASH的结构? 1、FLASH简介 (1)STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&…...

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

C++ | Leetcode C++题解之第424题替换后的最长重复字符
题目: 题解: 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…...

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

二叉树(二)深度遍历和广度遍历
一、层序遍历 广度优先搜索:使用队列,先进先出 模板: 1、定义返回的result和用于辅助的队列 2、队列初始化: root非空时进队 3、遍历整个队列:大循环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()) //如果奇偶任一方排好了,另…...

Rocky Linux 9 中添加或删除某个网卡的静态路由的方法
使用ip命令配置临时路由 添加静态路由 ip route add <目的网络> via <下一跳IP> dev <网卡接口名称>例: 给eth0网卡添加一个到达 192.168.2.0/24 网络,下一跳为 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等。这些语言各有其独特的优缺点,适用于不同的开发场景和需求。以下是对这些语言的具体介绍: PHP 优点:PHP是一种广泛用于Web开发的动态脚本语言,特别适…...

【程序大侠传】应用内存缓步攀升,告警如影随形
前序 在武侠编码的江湖中,内存泄漏犹如隐秘杀手,潜伏于应用程序的各个角落,悄无声息地吞噬着系统资源。若不及时发现和解决,必将导致内存枯竭,应用崩溃。 背景:内存泄漏的由来 内存泄漏,乃程序…...

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

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

Oracle Truncate和delete的区别
DropTruncatedelete语句类型 DDl (数据定义语言 Data Definition Language DDl (数据定义语言 Data Definition Language DML(数据操作语言 Data Manipulation Language 速度 快 删除整个表 快 一次性删除 慢 逐行删除 回滚不可不可可del…...

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

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

9.1 Linux_I/O_基本知识
文件类型 一切I/O皆文件,文件就是存放在磁盘上面的有序数据的集合。 文件类型: 常规文件 r :就是普通文件目录文件 d :就是目录,是一个索引字符设备文件 c :键盘、鼠标块设备文件 b :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项目----详细步骤配置,传送门:http://t.csdnimg.cn/RsOs7 src:放class文件 web:放html文件 out:运行过后产生的文件 一创建一个新的web项目(配置好了后): 在src创建一个文件…...

jQuery——jQuery的2把利器
1、jQuery 核心函数 ① 简称:jQuery 函数,即为 $ 或者 jQuery ② jQuery 库向外直接暴露的是 $ 或者 jQuery ③ 引入 jQuery 库后,直接使用 $ 即可 当函数用:$(xxx) 当对象用:$.xxx&#x…...

Day29笔记-Python操作pdfPython发送邮件
一、Python操作PDF【了解】 1.pdf 简介 PDF是Portable Document Format的缩写,这类文件通常使用.pdf作为其扩展名。在日常开发工作中,最容易遇到的就是从PDF中读取文本内容以及用已有的内容生成PDF文档这两个任务。 在Python中,可以使用名为P…...

Seata分布式事务实践
理论篇 什么是事务 关于事务我们一定会想到下面这四大特性: 原子性:所有操作要么全都完成,要么全都失败。 一致性: 保证数据库中的完整性约束和声明性约束。 隔离性:对统一资源的操作不会同时发生的。 持久性:对事务完成的操作最终会持久化到数据库中。 理解&…...

数字IC设计\FPGA 职位经典笔试面试整理--基础篇2
1. 卡诺图 逻辑函数表达式可以使用其最小项相加来表示,用所有的最小项可以转换为卡诺图进行逻辑项化简 卡诺图讲解资料1 卡诺图讲解资料2 卡诺图讲解资料3 最小项的定义 一个函数的某个乘积项包含了函数的全部变量,其中每个变量都以原变量或反变量的形…...

(务必收藏)推荐市面上8款AI自动写文献综述的网站
在当前的学术研究和论文写作中,AI技术的应用已经变得越来越普遍。特别是在文献综述这一环节,AI工具能够显著提高效率并减少人工劳动。以下是市面上8款推荐的AI自动写文献综述的网站: 一、千笔-AIPassPaper 是一款备受好评的AI论文写作平台&…...

【python】运算符
学习目标 了解 Python 中常见 算术(数学)运算符赋值运算符 算术(数学)运算符 a 是 10,b 是 20 运算符描述实例加两个对象相加 a b 输出结果 30-减得到负数或是一个数减去另一个数 a - b 输出结果 -10*乘两个数相…...

C++深入学习string类成员函数(1):默认与迭代
引言 在 C 编程中,std::string 类是处理字符串的核心工具之一。作为一个动态管理字符数组的类,它不仅提供了丰富的功能,还通过高效的内存管理和操作接口,极大地方便了字符串操作。通过深入探讨 std::string 的各类成员函数&#…...

DataGrip远程连接Hive
学会用datagrip远程操作hive 连接前提条件: 注意:mysql是否是开启状态 启动hadoop集群 start-all.sh 1、启动hiveserver2服务 nohup hiveserver2 >> /usr/local/soft/hive-3.1.3/hiveserver2.log 2>&1 & 2、beeline连接 beelin…...

go 读取excel
一、安装依赖 go get github.com/tealeg/xlsx二、main.go package mainimport "fmt" import "github.com/tealeg/xlsx"type Student struct {Name stringSex string }func (student Student) show() {fmt.Printf("Name:%s Sex:%s\r\n", stude…...

Linux进阶系列(四)——awk、sed、端口管理、crontab
目录 1. 写在前面2. awk —— 强大的文本处理工具2.1 awk 概述2.2 awk 脚本结构2.3 awk 的内置变量2.4 awk 的高级用法2.5 awk实践 3. sed —— 流式文本编辑器3.1 sed 的基本语法3.2 sed 常用命令3.3 sed 的高级用法 4. Linux 端口管理4.1 端口的概念4.2 查看端口状态4.3 开放…...

利用Metasploit进行信息收集与扫描
Metasploit之信息收集和扫描 在本文中,我们将学习以下内容 使用Metasploit被动收集信息 使用Metasploit主动收集信息 使用Nmap进行端口扫描 使用db_nmap方式进行端口扫描 使用ARP进行主机发现 UDP服务探测 SMB扫描和枚举 SSH版本扫描 FTP扫描 SMTP枚举 …...