STM32-Flash闪存

目录

一、简介

1、闪存模块组织

2、FLASh基本结构

3、FLash写入和读取操作

4、编程流程

5、选项字节格式

6、选项字节编程步骤

二、读写芯片内部FLASH编程

三、器件电子签名

1、简介

2、编程实现


一、简介

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

ROM和RAM存储 :

1、闪存模块组织

主存储器利用页单元来存储数据,每个页的大小为1KByte,C8T6芯片64KByte ,所以只用了前64页。

启动程序代码即系统存储器,大小为2KByte

 

2、FLASh基本结构

 

 3、FLash写入和读取操作

  • 先解锁

FPEC(闪存编程/擦除控制器)共有三个键值:

RDPRT键0x000000A5
KEY10x45670123
KEY20xCDEF89AB

  解锁:

        复位后,FPEC被保护,不能写入FLASH_CR     

       在FLASH_KEYR先写入KEY1,再写入KEY2,解锁   

        错误的操作序列会在下次复位前锁死FPEC和FLASH_CR

  加锁:

        设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR

  • 读写
    • 使用指针指定地址下的存储器:     uint16_t Data = *((__IO uint16_t *)(0x08000000));
    • 使用指针指定地址下的存储器:     *((__IO uint16_t *)(0x08000000)) = 0x1234;
    • 其中:     #define    __IO    volatile

 volatile告诉编译器这个变量是易变的,不要去优化它,每次必须从内存中读取。

4、编程流程

FLASH_CR寄存器中某位:

  • LOCK:锁,只能写’1’。 当该位为’1’时表示FPECFLASH_CR被锁住。在检测到正确的解 锁序列后,硬件清除此位为’0’。 在一次不成功的解锁操作后,下次系统复位前,该位不能再被改变。
  • PG:编程,选择编程操作,置’1‘。
  • PER:页擦除,选择整页擦除,置’1‘。
  • START:开始,当该位为1时将触发一次擦除操作。该位只可由软件置1,并在BSY变为’1‘时,清为’0‘。
  • MER:全擦除,选择擦除所有用户页,置’1‘

FLASH_SR寄存器中某位:

  • BSY:忙,该位指示闪存操作正在进行。在闪存操作开始时,该位被设置为’1‘;在操作结束或发生错误时该位被清除为‘0’

  • 编程过程

  • 闪存页擦除

 

  • 闪存全擦除

5、选项字节格式

每个选择位都在信息 块中有它的反码位,在装载选择位时反码位用于验证选择位是否正确,如果有任何的差别,将 产生一个选择字节错误标志(OPTERR)

  • RDP:写入RDPRT键(0x000000A5)后解除读保护
  • USER:配置硬件看门狗和进入停机/待机模式是否产生复位
  • Data0/1:用户可自定义使用 WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量) 

 6、选项字节编程步骤

  • 选项字节编程
    • 检查FLASH_SR的BSY位,以确认没有其他正在进行的编程操作
    • 解锁FLASH_CR的OPTWRE(允许写选择字节),当该位为1时 ,允许对选择字节进行编程操作。当在FLASH_OPTKETR寄存器写入正确的键序列后,该位被置为‘1’。软件可清除此位。
    • 设置FLASH_CR的OPTPG位为1
    • 写入要编程的半字到指定的地址
    • 等待BSY位变为0
    • 读出写入的地址并验证数据
  • 选项字节擦除
    • 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
    • 解锁FLASH_CR的OPTWRE位
    • 设置FLASH_CR的OPTER位为1
    • 设置FLASH_CR的OPTER位为1
    • 等待BSY位变为0
    • 读出被擦除的选择字节并做验证

二、读写芯片内部FLASH编程

MyFlash.c:
 

#include "stm32f10x.h"                  // Device headeruint32_t MyFlash_ReadWord(uint32_t Address)
{return *((__IO uint32_t *)(Address));     //32位
}uint16_t MyFlash_ReadHalfWord(uint32_t Address)
{return *((__IO uint16_t *)(Address));
}uint8_t MyFlash_ReadByte(uint32_t Address)
{return *((__IO uint16_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();}

MyFlash.h:

#ifndef _MYFLASH_H
#define _MYFLASH_Huint32_t MyFlash_ReadWord(uint32_t Address);uint16_t MyFlash_ReadHalfWord(uint32_t Address);uint8_t MyFlash_ReadByte(uint32_t Address);void MyFlash_EraseAllPages(void);void MyFlash_ErasePage(uint32_t PageAddress);void MyFlash_ProgramWord(uint32_t Address,uint32_t Data);void MyFlash_ProgramHalfWord(uint32_t Address,uint16_t Data);#endif

Store.c:

用来在Flash内部储存数据

#include "stm32f10x.h"                  // Device header
#include  "MyFlash.h"#define STORE_START_ADDRESS   0x0800FC00
#define STORE_COUNT  512uint16_t Store_Data[STORE_COUNT];
uint16_t i=0;void Store_Init(void)
{if(MyFlash_ReadHalfWord(STORE_START_ADDRESS)!=0xA5A5){MyFlash_ErasePage(STORE_START_ADDRESS);MyFlash_ProgramHalfWord(STORE_START_ADDRESS,0xA5A5);for(i=1;i<STORE_COUNT;i++){MyFlash_ProgramHalfWord(STORE_START_ADDRESS+i*2,0x0000);}}for(i=0;i<STORE_COUNT ;i++){Store_Data[i]=MyFlash_ReadHalfWord(STORE_START_ADDRESS+i*2);}
}void Store_Save(void)
{MyFlash_ErasePage(STORE_START_ADDRESS);for(i=0;i<STORE_COUNT;i++){MyFlash_ProgramHalfWord(STORE_START_ADDRESS+i*2,Store_Data[i]);}}void Store_Clear(void)
{for(i=1;i<STORE_COUNT;i++){Store_Data[i]=0x0000;}Store_Save();
}

Store.h:

#ifndef _STORE_H
#define _STORE_Hextern uint16_t Store_Data[];void Store_Init(void);void Store_Save(void);void Store_Clear(void);#endif

main.c:
 

#include  "stm32f10x.h"                  // Device header
#include  "OLED.h"
#include  "delay.h"
#include  "Store.h"
#include  "MyFlash.h"int main(void)
{OLED_Init();Store_Init();//擦除后数据位全都变为1//MyFlash_EraseAllPages();  OLED_ShowString(1,1,"Flag:");OLED_ShowString(2,1,"Data:");	while(1) {OLED_ShowHexNum(1,6,Store_Data[0],4);OLED_ShowHexNum(2,6,Store_Data[1],4);OLED_ShowHexNum(3,6,Store_Data[2],4);Store_Data[1]++;Store_Data[2]+=2;Store_Save();Delay_ms(1000);}}

三、器件电子签名

1、简介

  • 电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名
  • 闪存容量寄存器:     
    基地址:0x1FFF F7E0     大小:16位
  • 产品唯一身份标识寄存器:     
    基地址: 0x1FFF F7E8     大小:96位

2、编程实现

main.c:

#include  "stm32f10x.h"                  // Device header
#include  "OLED.h"
#include  "delay.h"int main(void)
{OLED_Init();OLED_ShowString(1,1,"F_SIZE:");OLED_ShowHexNum(1,8,*(__IO uint16_t *)(0x1FFFF7E0),4);OLED_ShowString(2,1,"U_ID:");OLED_ShowHexNum(2,6,*(__IO uint16_t *)(0x1FFFF7E8),4);OLED_ShowHexNum(2,11,*(__IO uint16_t *)(0x1FFFF7E8+0x02),4);OLED_ShowHexNum(3,1,*(__IO uint32_t *)(0x1FFFF7E8+0x04),8);OLED_ShowHexNum(4,1,*(__IO uint32_t *)(0x1FFFF7E8+0x08),8);while(1) {}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10676.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构之带头双向循环链表

前言&#xff1a;前面我们实现了顺序表和单链表&#xff0c;这次来实现一个结构更复杂的链表-----带头双向循环链表。不要被它的名字吓到哦&#xff0c;只是结构复杂而已&#xff0c;它的结构更有利于代码的实现。 1 双向循环链表的介绍 有了单链表的基础&#xff0c;要实现这…

10个最常用的Python包,程序员必备!

世界上有超过200,000个Python程序包&#xff08;这只是基于官方的Python程序包索引PyPI托管的程序包&#xff09;。 这就引出了一个问题&#xff1a;拥有这么多的软件包&#xff0c;每个Python程序员都需要学习哪些软件包是最重要的&#xff1f; 为了帮助回答这个问题&#x…

线上问题的排查-java死锁问题如何排查

这里写目录标题 1.java死锁如何排查2.具体步骤1.1识别死锁现象1.2收集线程转储1.3分析线程转储1.4代码审查1.5重现问题1.6使用调试工具1.7.优化和验证 3. 解决方案总结 1.java死锁如何排查 在Java应用程序中&#xff0c;死锁是一个经典的并发问题&#xff0c;它会导致线程永久阻…

shodan(4-5)

以下笔记学习来自B站泷羽Sec&#xff1a; B站泷羽Sec 1. 查看自己的出口IP 可以知晓自己是哪个IP连接的公网 shodan myip2. 指定标题搜索 http.title:内容搜索被挂黑页的网页&#xff1a;获得标题中含有hacked by的IP shodan search --limit 10 --fields ip_str,port htt…

三种风格截然不同的实验室工控界面

三种风格截然不同的实验室工控界面各具特色。一种可能是简洁现代风&#xff0c;以简洁的线条、纯净的色彩和直观的图标&#xff0c;呈现出高效与专业。 另一种或许是科技未来风&#xff0c;运用炫酷的光影效果和立体感十足的设计&#xff0c;展现实验室的前沿科技感。 还有一…

Redis如何保证数据不丢失(可靠性)

本文主要以学习为主&#xff0c;详细参考&#xff1a;微信公众平台 Redis 保证数据不丢失的主要手段有两个&#xff1a; 持久化 多机部署 我们分别来看它们两的具体实现细节。 1.Redis 持久化 持久化是指将数据从内存中存储到持久化存储介质中&#xff08;如硬盘&#xf…

STM32F405RGT6单片机原理图、PCB免费分享

大学时机创比赛时画的板子&#xff0c;比到一半因为疫情回家&#xff0c;无后续&#xff0c;&#xff0c;&#xff0c;已打板验证过&#xff0c;使用stm32f405rgt6做主控 下载文件资源如下 原理图文件 pcb文件 外壳模型文件 stm32f405例程 功能 以下功能全部验证通过 4路…

“穿梭于容器之间:C++ STL迭代器的艺术之旅”

引言&#xff1a; 迭代器&#xff08;Iterator&#xff09;是C STL&#xff08;标准模板库&#xff09;中非常重要的一部分&#xff0c;它提供了一种统一的方式来遍历容器中的元素。无论容器是数组、链表、树还是其他数据结构&#xff0c;迭代器都能够以一致的方式访问这些数据…

jmeter常用配置元件介绍总结之用linux服务器压测

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之用linux服务器压测 1.编写测试脚本2.执行测试脚本 1.编写测试脚本 在linux服务器上进行压测&#xff0c;由于是没有界面的&#xff0c;因此我们可以先在界面上把压测脚本写好&#xff1a; 如图&#xff1a;我这里简单的写…

Ubuntu 的 ROS 操作系统安装与测试

引言 机器人操作系统&#xff08;ROS, Robot Operating System&#xff09;是一个用于开发机器人应用的开源框架&#xff0c;它提供了一系列功能丰富的库和工具&#xff0c;能够帮助开发者构建和控制机器人。 当前&#xff0c;ROS1的最新版本为Noetic Ninjemys&#xff0c;专为…

计算机组成原理——编码与纠错(汉明编码)

校验码放在2^x次方的位置——即1&#xff0c;2&#xff0c;4——将检测位按序排列p3p2p1 汉明编码从左到右数某个位置位1&#xff08;位数&#xff09;&#xff0c;就表示第几组 奇偶校验 例题 纠错过程 汉明编码的最小距离是3

fabric操作canvas绘图(1)共32节

对于前端而言&#xff0c;离不开canvas就像鱼离不开水&#xff0c;前端canvas神器fabric你值得拥有&#xff01;接下来我们就来一步步揭开她的面纱。 一、fabric的理解 用原生的canvas来实现&#xff0c;代码量会比较大&#xff0c;而且还要处理很多细节&#xff0c;而Fabric…

C++ 内存分布及 new , delete 分配问题( ~~~ 面试重要 ~~~)

文章目录 前言一、内存分布二、new 、delete 分配问题总结 前言 本篇文章笔者将会对 C 中的内存问题简单的讲解 , 同时对 new , delete 的面试题进行重点讲解. 一、内存分布 ● C语言和C 分布情况是一样的, 如下 : ● 栈 ○ 栈 的管理是由编译器自动管理 , 不需要我们人为做…

数据结构-哈夫曼树

一.什么是哈夫曼树 不同搜索树的效率是不一样的,根据不同的频率构造效率比较好或者最好的搜索树就是哈夫曼树 二.哈夫曼树的定义 将带权路径的长度降低最低 每个叶子节点到根节点的距离乘权值&#xff0c;再全都加起来就得到了WPL值 第一颗二叉树:从上到下计算 5x14x23x32x41…

双11精选网络安全书单:打造数字世界的钢铁长城!

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 &#x1f31f;双11火热来袭&#xff0c;网络安全书单推荐&#x1f680; 随着数字化浪潮的汹涌澎湃&#xff0c;网络安全已经成为了每个从业者不可回避的重要议…

WebGUI之Gradio:Gradio 5的简介、安装和使用方法、案例应用之详细攻略

WebGUI之Gradio&#xff1a;Gradio 5的简介、安装和使用方法、案例应用之详细攻略 目录 Gradio 5的简介 1、Gradio的适用场景 2、Gradio 5 的主要改进包括&#xff1a; Gradio 5的安装和使用方法 1、安装和使用方法 2、使用方法 2.1、文本内容 (1)、简单的输入/输出组件…

初始Python篇(5)—— 集合

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 集合 相关概念 集合的创建与删除 集合的操作符 集合的相关操作方法 集合的遍历 集合生成式 列表、元组、字典、集合的…

探索Python的Shell力量:Plumbum库揭秘

文章目录 探索Python的Shell力量&#xff1a;Plumbum库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;Plumbum是什么&#xff1f;第三部分&#xff1a;如何安装Plumbum&#xff1f;2. 创建管道3. 重定向4. 工作目录操作5. 前台和后台执行 第五部分&#xff1a;场景应用…

大模型时代,算法岗到底哪个最有前景?什么样的算法工程师更吃香?

毫无疑问&#xff0c;全栈型的算法工程师将更为抢手&#xff0c;如果你精通大模型从训练到应用的整个流程&#xff0c;你走到哪里都不怕。 但往往人的精力有限&#xff0c;如果从数据、预训练、微调、对齐、推理、应用几个方面来看的话&#xff0c;个人觉得 “预训练>数据&…

Linux系统之sleep命令的基本使用

Linux系统之sleep命令的基本使用 一、sleep命令介绍二、sleep的使用帮助2.1 查看帮助信息2.2 基本语法 三、sleep命令的基本使用3.1 指定暂停时间长度3.2 结合多个时间单位 四、在脚本中应用五、注意事项 一、sleep命令介绍 sleep命令是一个在Unix和类Unix操作系统中常见的命令…