江科大STM32入门:FLASH闪存详解——从结构原理到读写保护
STM32学习笔记适用平台本文基于 STM32F103C8T6中容量产品64KB Flash讲解使用标准库开发。前言为什么非要学FLASH学到这里很多小伙伴可能有个疑问我程序不是已经能跑了吗GPIO、定时器、中断都玩溜了这个FLASH跟我有啥关系别急先想两个问题你的单片机掉电后之前记的数据比如密码、校准参数、运行次数还在吗RAM里的东西可是掉电就丢的。你想过没有以后做产品能不能像手机OTA升级一样通过串口或蓝牙给单片机隔空更新程序这两个问题的答案都指向了今天的主角——内部FLASH。它不只是存程序的地方更是我们能直接操作的掉电不丢失的存储空间。搞懂它你的STM32才算真正入门了。一、FLASH简介它到底是个啥STM32F1系列的内部FLASH说白了就三块东西组成部分作用人话解释程序存储器存放我们烧录的程序代码就是你Keil编译生成的hex文件住的家系统存储器存放ST出厂的Bootloader芯片原厂自带的引导程序用于串口下载选项字节配置读写保护、看门狗等FLASH的设置面板管着安全权限读写FLASH主要有两大用途存用户数据利用程序存储器的剩余空间保存那些掉电不能丢的参数。比如你的智能台灯要记忆亮度档位总不能每次上电都让用户重新调吧IAP在应用编程程序运行过程中通过串口、蓝牙等接口接收新程序把自己更新掉。这就是很多设备在线升级的底层原理。这里还要区分两个概念ICP在线编程通过JTAG、SWD或者系统存储器里的Bootloader把整个FLASH重新烧一遍。这是我们平时用ST-Link下载程序的方式。IAP在程序中编程程序自己跑起来后用代码去改写FLASH里的内容。比如你做一个Bootloader分区专门负责接收新程序。我的理解你可以把ICP想象成拆机换硬盘IAP就是手机在线系统更新。我们平时调程序用ICP做产品升级就要靠IAP了。二、FLASH的内部结构拆解它的五脏六腑2.1 闪存模块组织中容量产品先上一张户型图看看FLASH这块地皮是怎么划分的图1闪存模块组织中容量产品从这张表可以看出STM32F1的FLASH分为三大块1. 主存储器程序存储器中容量产品共有128页Page 0 ~ Page 127每页1KB。等等C8T6不是64KB吗怎么有128页这里要注意中容量产品的定义是64KB或128KBC8T664KB实际上只用到页0~页63。后面多出来的页在C8T6上是不存在的或者说超出范围了。地址从0x0800 0000开始每页递增0x400也就是1024字节。2. 信息块系统存储器地址0x1FFF F000大小2KB住着ST的Bootloader。用户选择字节选项字节地址0x1FFF F800大小16字节专门管配置。3. 闪存存储器接口寄存器从0x4002 2000开始是FPEC闪存编程和擦除控制器的操控面板。包括FLASH_ACR访问控制、FLASH_KEYR密钥、FLASH_SR状态、FLASH_CR控制、FLASH_AR地址等。2.2 FLASH基本结构框图​图2FLASH基本结构框图这张图更直观左边绿色的FPEC闪存编程和擦除控制器是大管家所有擦除和编程操作都必须经过它。右边橙色的三部分就是刚才说的程序存储器、系统存储器、选项字节。注意那个配置读写保护的箭头它告诉我们选项字节可以反过来控制主存储器的访问权限。这就好比小区大门的门禁系统选项字节就是物业的管理后台。我的理解FPEC就像FLASH的保安队长你想动FLASH里的内容得先过它这关。而且它不是摆设写错了钥匙或者操作顺序不对它真给你把门锁死。三、FLASH的解锁机制为什么要有钥匙3.1 三个关键键值FPEC手里有三把钥匙键值名称数值用途RDPRT键0x000000A5解除读保护KEY10x45670123解锁FPEC的第一步KEY20xCDEF89AB解锁FPEC的第二步3.2 解锁流程复位后FPEC默认是上锁状态FLASH_CR寄存器写不进去。这时候你想擦除或编程门儿都没有。正确解锁姿势往FLASH_KEYR密钥寄存器写入KEY1再往同一个寄存器写入KEY2顺序必须对值必须准。这两步走完后FPEC就解锁了你可以操作FLASH_CR了。⚠️ 风险说明如果你解锁时写错了值或者顺序颠倒了FPEC会被锁死在下次复位之前你再也动不了FLASH了。这不是吓唬人是手册里写的。3.3 加锁操作完成后记得设置FLASH_CR的LOCK位为1把FPEC重新锁上。这就像你进房间拿完东西要关门一样防止程序跑飞后误写FLASH。我的理解这个解锁机制其实是ST给我们的一层保险。你想啊如果程序跑飞了指针乱指万一指到FLASH地址上乱写一通那程序不就彻底崩了吗有了这把锁至少得对暗号才能动手大大降低了误操作的风险。四、如何读写FLASH——指针访问与操作流程4.1 使用指针直接访问存储器FLASH本质上就是一片地址空间。程序存储器从0x0800 0000开始那我们直接用指针就能读写读操作uint16_t Data *((__IO uint16_t *)(0x08000000));写操作*((__IO uint16_t *)(0x08000000)) 0x1234;这里__IO被定义为volatile。为什么非要加volatile因为编译器可能会自作聪明地优化掉你的读写操作。加了volatile就是告诉编译器这个地址是硬件寄存器每次读写都必须真去访问内存不准偷懒边界意识STM32F1的主存储器编程最小单位是半字16位。你不能像操作RAM那样一个字节一个字节地写必须16位一起写。而且写入的地址必须是偶数地址半字对齐。4.2 程序存储器编程流程​图5程序存储器编程流程看图说话编程写入的标准流程检查LOCK位如果LOCK1先执行解锁序列KEY1 KEY2。置PG位把FLASH_CR的PG位编程位置1告诉FPEC我要开始写数据了。写入半字在目标地址写入一个16位数据。等待BSY位清零FLASH_SR的BSY位忙标志为1表示FPEC正在干活你得轮询等它变0。读校验写入完成后把刚才的地址读出来看看是不是你写的那个数。⚠️ 核心知识点必考FLASH有个怪脾气——写入前必须先擦除而且擦除后所有位变成1写入只能把1改成0不能把0改成1。如果你直接往已经有数据的地址上写结果会是按位与的关系数据绝对不是你想要的。4.3 程序存储器页擦除流程​图6程序存储器页擦除流程既然写之前必须擦除那怎么擦检查并解锁同上。置PER位把FLASH_CR的PER位页擦除位置1。写地址把要擦除的页的起始地址写入FLASH_AR地址寄存器。置STRT位把FLASH_CR的STRT位开始位置1FPEC就开始擦了。等待BSY0。验证读出这一页确认全是0xFFFF擦除后就是全1。我的理解页擦除就像整块黑板擦掉重写。你不可能只擦掉黑板上的某一个字必须整页擦。所以规划FLASH存储时要把经常改动的数据放在同一页避免频繁擦除影响寿命。4.4 程序存储器全擦除流程​程序存储器全擦除流程全擦除就更简单了解锁。置MER位把FLASH_CR的MER位全擦除位置1。置STRT位开始擦除。等BSY0验证所有页。⚠️ 风险说明全擦除会把你的程序也擦掉如果你在程序运行过程中误触发了全擦除那芯片就变砖了只能重新用ST-Link烧程序。所以写代码时MER位一定要谨慎操作。五、选项字节那些隐藏配置5.1 选项字节的组织结构​信息块选项字节的组织结构选项字节一共16个字节但STM32用了一种冗余设计每个配置都存了原值和反值比如RDP和nRDP。这样芯片上电时可以互相校验防止配置因干扰出错。各字段含义字段作用RDP读保护级别。写入0xA5解除读保护其他值会开启不同级别的保护USER配置硬件看门狗IWDG_SW、停机/待机模式是否产生复位Data0/1用户可自定义一般存一些设备标识或校准参数WRP0~3写保护位每一位对应保护4个存储页中容量产品我的理解选项字节就像是FLASH的保险箱密码和权限设置。RDP读保护一旦开启别人用J-Link就读不出你的程序了对知识产权保护很重要。但注意开启读保护后如果要解除FLASH会被全部擦除这是ST设计的防破解机制。5.2 选项字节的编程与擦除选项字节和主存储器的操作类似但多了几道安检编程流程检查FLASH_SR的BSY位确认FPEC空闲。解锁FLASH_CR的OPTWRE位选项字节写使能。置FLASH_CR的OPTPG位选项字节编程位为1。写入半字到指定地址。等待BSY0。读出验证。擦除流程检查BSY位。解锁OPTWRE位。置FLASH_CR的OPTER位选项字节擦除位为1。置STRT位为1。等待BSY0。读出验证。我的理解选项字节操作比主存储器多一个OPTWRE解锁这相当于双重认证。毕竟改选项字节可能影响整个芯片的访问权限ST当然得谨慎点。六、器件电子签名芯片的身份证每颗STM32芯片出厂时ST都在系统存储区域烧写了一组不可更改的电子签名包含两个信息寄存器基地址大小用途闪存容量寄存器0x1FFF F7E016位表示芯片的FLASH容量单位KB。比如C8T6读出来就是64产品唯一身份标识寄存器0x1FFF F7E896位全球唯一的芯片ID每颗芯片都不一样这有啥用闪存容量寄存器程序可以自动识别自己跑在什么容量的芯片上做自适应配置。唯一身份标识可以做设备的硬件指纹。比如你想做一机一码的加密或者给每个设备分配独立序列号读这个寄存器就行了。因为它是出厂固化、不可更改的比存在FLASH里的数据靠谱多了。我的理解这就像是芯片的身份证号和户口本。96位的唯一ID全世界没有两颗一样的芯片做产品追溯、防复制、加密绑定都特别好使。七、我的理解 / 心得学FLASH之前我一直以为它只能存程序。现在明白了只要规划好地址完全可以把用户数据存在程序后面的空白页里。比如C8T6的64KB程序只占用了前20KB后面44KB就是自由空间。关于擦除寿命FLASH的擦写次数是有限的手册标称1万次。所以做数据存储时不能频繁擦同一页。如果要做EEPROM效果可以考虑磨损均衡算法或者直接用STM32的备份寄存器、外接EEPROM。八、踩坑记录踩坑场景现象原因解决办法未解锁直接写FLASH程序卡死或数据没写入FLASH_CR处于锁定状态严格按KEY1→KEY2顺序解锁写入前未擦除读出来的数据和写入值不一致FLASH只能1变0不能0变1写入前必须执行页擦除擦除/编程时掉电芯片变砖无法下载程序操作过程中断导致FLASH损坏确保电源稳定或加掉电检测选项字节误操作无法通过SWD下载程序开启了读保护或写保护按住复位键在Keil点击下载瞬间松开复位指针未加volatile开启优化后代码失效编译器优化掉了寄存器访问所有硬件寄存器指针前加__IO或volatile九、总结表格知识点核心内容注意事项FLASH组成程序存储器 系统存储器 选项字节C8T6程序存储器为64KB64页主存储器页大小每页1KB擦除最小单位是页写入最小单位是半字16位解锁键值KEY10x45670123KEY20xCDEF89AB顺序不能错错则锁死编程前提必须先擦除擦除后全为1写入只能1变0编程流程解锁→置PG→写半字→等BSY→校验地址必须半字对齐页擦除流程解锁→置PER→写地址→置STRT→等BSY会擦除整页1KB数据全擦除流程解锁→置MER→置STRT→等BSY会擦掉程序本身慎用选项字节RDP/USER/Data/WRP每项存原值反值操作前需额外解锁OPTWRE电子签名容量寄存器96位唯一ID出厂固化不可改可用于设备加密和序列号写这篇文章的时候我把江科大的视频又回顾了一遍结合《STM32F10xxx参考手册》把FLASH的寄存器位一个个核对过去才发现之前很多想当然的理解都是错的。比如我以为FLASH可以像RAM一样随便写实际上必须先擦除我以为解锁就是走个形式实际上写错真的会锁死。STM32的FLASH模块虽然看起来就是擦了写、写了读但里面的门道真不少——解锁机制、选项字节、读写保护每一步都是ST为了可靠性设计的保险丝。搞懂这些不只是为了应付考试更是为了以后做产品时少踩坑。开发环境Keil5 STM32F103C8T6最小系统板 ST-Link参考资料江科大STM32入门教程、《STM32F10xxx参考手册》如果本文对你有帮助欢迎点赞 收藏 ⭐ 有任何问题欢迎在评论区交流一起学习进步

相关新闻

从Prompt工程到LLM应用开发:快速构建NLP推理系统的实战指南

从Prompt工程到LLM应用开发:快速构建NLP推理系统的实战指南

1. 从“炼丹”到“搭积木”:Prompt工程如何重塑NLP任务开发 如果你在几年前告诉我,开发一个文本分类或者情感分析系统,可以不用再费劲地标注几千条数据、训练一个模型、然后花几天时间调参,我大概率会觉得你在开玩笑。传统的NLP开…

2026/10/10 3:30:35 阅读更多 →
异音检测系统产线部署全流程:从方案设计到验收的六个阶段

异音检测系统产线部署全流程:从方案设计到验收的六个阶段

一套异音检测系统在实验室跑得再完美,搬到产线上第一天照样可能翻车。问题通常不在检测算法上——而在部署过程中的无数细节。这篇文章梳理了一条产线从"想上检测设备"到"稳定运行"的完整路径。一、为什么部署比开发更难?一个做了十…

2026/10/14 22:23:41 阅读更多 →
华为OD机试真题 新系统 2026-08-09 Java、Go、C【查找最佳充电策略】

华为OD机试真题 新系统 2026-08-09 Java、Go、C【查找最佳充电策略】

目录 题目 思路 Code 题目 题目内容: 给定一个电费组 priceArray,表示未来 priceRecords 小时内每小时的电价,单位为分/kWh。 找出充电成本最低的连续 hours 个小时的时间段开始时刻点。 若存在多种成本最低方案,优先返回成本最低方案中最早的时间点。 输入描述:…

2026/10/15 21:30:13 阅读更多 →

最新新闻

前缀和与差分:从Sn到an,一篇文章讲透区间操作核心算法

前缀和与差分:从Sn到an,一篇文章讲透区间操作核心算法

刷算法题的时候,我经常看到有人一遇到“前缀和”“差分”就开始头皮发麻。原因倒也好理解:这两个词听起来像两座大山,好像没学过高等数学就翻不过去。但我想说,你真的被名字唬住了。这俩东西,本质就是你高中数列里天天…

2026/10/15 21:42:56 阅读更多 →
RESTful接口设计工程实践:从资源命名到落地规范

RESTful接口设计工程实践:从资源命名到落地规范

我到现在都记得刚带第一个中型项目的时候,前后端一起联调,光接口文档就维护了三个版本:后端自己写的接口说明、前端总结的字段字典、客户端团队小群里私下补的备注。每次产品提需求,大家第一反应不是讨论功能,而是问“…

2026/10/15 21:42:56 阅读更多 →
C#数据库增删改查实战:Access与SQL Server双路径落地

C#数据库增删改查实战:Access与SQL Server双路径落地

简介:本资源是一份面向C#初学者与ASP.NET入门开发者的数据库基础操作教学代码包,聚焦增删改查(CRUD)核心能力训练。内容以完整可运行的C#源码为主,涵盖OleDbConnection连接Access数据库、OleDbCommand执行参数化SQL语句…

2026/10/15 21:42:56 阅读更多 →
TensorFlow 2多算法对比:文本分类实战与选型指南

TensorFlow 2多算法对比:文本分类实战与选型指南

1. 文本分类这件事,为什么值得把多个算法放在一起跑文本分类算是自然语言处理里最接地气的一类任务了。情感分析、垃圾内容识别、工单自动路由、新闻频道归类,本质上都是把一段文本映射到一个预定义的类别标签上。很多刚入门的朋友跑通一个模型、看到准确…

2026/10/15 21:42:56 阅读更多 →
WOA-VMD鲸鱼算法优化变分模态分解:参数自动搜索与Python实现

WOA-VMD鲸鱼算法优化变分模态分解:参数自动搜索与Python实现

简介:本资源面向计算机、电子信息工程、数学等专业的学生与研究人员,提供一套Matlab实现的WOA-VMD鲸鱼算法优化变分模态分解完整方案,可用于课程设计、期末大作业与毕业设计,也适合作为信号处理方向的创新点。资源利用鲸鱼优化算法…

2026/10/15 21:42:56 阅读更多 →
YOLO-World开放词汇检测实战:架构拆解、训练策略与部署避坑指南

YOLO-World开放词汇检测实战:架构拆解、训练策略与部署避坑指南

简介:这份PDF资料聚焦YOLO-World开放词汇对象检测器的实现方式,面向已具备YOLO基础、希望深入理解视觉语言建模与跨模态检测的算法工程师和研究者。内容围绕架构组成、训练与预训练、推理过程及性能表现展开,重点讲解YOLO检测器、CLIP文本编码…

2026/10/15 21:41:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →