软件:STM32-F1系列-读取Flash(2026/7/14)

目录

Flash介绍

[1:Flash 是什么?](#1:Flash 是什么?)

[2:Flash 的结构](#2:Flash 的结构)

[3:CPU 怎么执行程序?](#3:CPU 怎么执行程序?)

[4:为什么还需要 SRAM?](#4:为什么还需要 SRAM?)

5:flash的两个操作

6:擦除单位Page

[7:flash 存储内容](#7:flash 存储内容)

[8:flash 的几大应用](#8:flash 的几大应用)

[① Bootloader](#① Bootloader)

[② IAP(In-Application Programming)(在应用编程)](#② IAP(In-Application Programming)(在应用编程))

[③ EEPROM 模拟 (Emulated EEPROM)](#③ EEPROM 模拟 (Emulated EEPROM))

STM32f103flash资源

1:基本参数

[2:Flash 的三大操作](#2:Flash 的三大操作)

[①. 读操作(无门槛)](#①. 读操作(无门槛))

②.写操作(需解锁)

③.擦除操作(2种方式)

3:编程/擦除流程(标准库)

4:几大应用

5:与BKP寄存器的区别

读取flash程序实例

1:字节寻址

2:大端和小端

3:写入半字地址处理

4:创建自己的SRAM

5:从SRAM写入到flash

6:清空SRAM数组


Flash介绍

1:Flash 是什么?

Flash 可以说是 STM32 最重要的存储器之一。

今天的 Flash,就是 STM32 芯片里面那块掉电不会丢失数据的存储器。

它负责保存:

  • 用户程序(main()、各种函数)
  • 常量数据
  • 字库
  • 参数
  • BootLoader
  • 固件

CPU 上电后第一件事情就是:去 Flash 读取程序,然后开始执行。

2:Flash 的结构

STM32 的 Flash 没有 Page、Sector 混着用。

对于 F1 系列:只有 Page(页)

整个 Flash:64KB Flash→64 页→每页 1KB

地址变化:起始地址为0x08000000,1KB为1024 Byte转为16进制0x400

Page0为08000000→Page1为08000400直到0800FC00为最后一页

3:CPU 怎么执行程序?

很多人都会误解:Flash 是不是把程序复制到 SRAM 再运行?

对于 STM32F103:不是,CPU 可以直接读取 Flash。

4:为什么还需要 SRAM?

因为:Flash,适合保存,不适合频繁修改。SRAM:适合频繁读写

因此CPU是从 Flash 读取代码,去 SRAM 修改变量。

所以:

代码在 Flash。

数据在 SRAM。

这是最经典的结构。

5:flash的两个操作

(1)读取

CPU可以直接读取flash,0x08000000→取指令→执行 。程序运行就是这样。

(2)写入

Flash不能像RAM一样随便修改,写入前需要擦除以后才可以写入

擦除指的是把该页内容全部写入1

6:擦除单位Page

STM32F103最小擦除单位:Page

7:flash 存储内容

情况1:程序代码

情况2:用户参数

比如,

系统配置类:背光亮度等级

用户偏好类:语言选择:中文/英文。

运行统计类:设备通电次数

8:flash 的几大应用

① Bootloader

本质:一段上电后最先运行的代码,负责"交接工作"。

STM32 上电后,根据 Boot 引脚(BOOT0/BOOT1)的状态决定从哪里启动。如果是从 Flash 启动,它固定从 0x08000000开始执行,Bootloader 就放在0x08000000这里。

Bootloader的任务:

<1>初始化最基本的硬件(时钟、串口/USB/CAN)。

<2>判断是否需要升级程序(比如检测按键、检测APP完整性、接收升级指令)。

<3>跳转到用户应用程序(APP)去执行。

② IAP(In-Application Programming)(在应用编程)

本质:利用 Flash 的可擦写特性,在运行代码的同时改写 Flash 里的其他代码。

它与 Bootloader 的关系

很多人混淆这两个概念。其实:

  • Bootloader​ 是载体(那段代码)。

  • IAP​ 是功能(通过串口/USB/无线等方式更新固件的功能)。

通常,我们在 Bootloader 中实现 IAP 功能。

流程如下:

  1. 设备上电,进入 Bootloader。

  2. 收到主机发来的新固件数据包(Bin 文件)。

  3. Bootloader 擦除 APP 所在扇区。

  4. Bootloader 将收到的数据写入 Flash 的 APP 区域。

  5. 校验 CRC,成功后跳转。

为什么叫"在应用编程"?

因为你可以设计成:即使进入了 APP,APP 也能接收到升级指令,然后强制跳回 Bootloader,让 Bootloader 重新覆盖 APP 区域。这就实现了"一边跑一边修"。

防变砖机制(双保险)

为了防止升级中途断电导致变砖,高级一点的设计是:

  • 预留两份 APP 空间(A/B 区)。

  • 当前跑 A 区,收到升级包后写到 B 区。

  • B 区校验通过后,修改标志位,下次重启跳转到 B 区。

  • 这样即使 B 区写坏了,还能回到 A 区。

③ EEPROM 模拟 (Emulated EEPROM)

本质:利用 Flash 的非易失性,假装自己是 EEPROM。

Flash 比 EEPROM 难用在于:

  1. 擦除单位大:Flash 擦 1KB,EEPROM 擦 1Byte。

  2. 寿命短:Flash 1万次,EEPROM 100万次。

STM32F103C8T6 没有​ EEPROM。但我们需要存参数(如校准系数、配置),这些参数不能存在 RAM(掉电丢),也不能每次都烧录(太麻烦)。

ST 官方提供了 AN2594 应用笔记和对应的 EEPROM Emulation 库,强烈建议直接用官方的,不要自己造轮子,里面的状态机很复杂。

STM32f103flash资源

1:基本参数

2:Flash 的三大操作

①. 读操作(无门槛)
  • 直接通过地址指针读取,和读 SRAM 一样
  • 内建预取缓冲区,可以加速指令读取
②.写操作(需解锁)
  • Flash 默认是锁住的,防止误操作
  • 必须按顺序写入密钥才能解锁:先写 0x45670123,再写 0xCDEF89ABFLASH_KEYR 寄存器
  • 写操作必须按**半字(16 bit)**写入,不能按字节写
  • 写入前目标地址必须是 0xFFFF(擦除后的状态)
③.擦除操作(2种方式)
  • Flash 的物理特性:只能把 1 变成 0,不能把 0 变成 1
  • 要把 0 变回 1,只能靠擦除,擦除会将整页或整片变为全 0xFFFF
  • 两种擦除模式:
    • 页擦除:擦除某一页(1 KB),对其他页无影响
    • 整片擦除:擦除全部 64 KB,包括你正在运行的程序!慎用

3:编程/擦除流程(标准库)

复制代码
// 1. 解锁 Flash
FLASH_Unlock();

// 2. 等待 Flash 空闲(可选,大多数函数内部已处理)
// while(FLASH_GetFlagStatus(FLASH_FLAG_BSY) == SET);

// 3a. 页擦除
FLASH_ErasePage(0x0800_FC00);  // 擦除最后一页(第63页)

// 3b. 或 整片擦除(慎用!会擦掉程序本身)
// FLASH_EraseAllPages();

// 4. 编程写入(半字单位)
FLASH_ProgramHalfWord(0x0800_FC00, 0x1234);
FLASH_ProgramHalfWord(0x0800_FC02, 0x5678);

// 5. 上锁保护
FLASH_Lock();

// 6. 读取验证(直接读地址就行)
uint16_t data = *(volatile uint16_t *)0x0800_FC00;

4:几大应用

1.模拟 EEPROM --- STM32F103C8T6 没有真正的 EEPROM,但可以用最后几页 Flash 来存配置参数(你的备份寄存器项目就是这个思路的入口)

2.IAP(在线升级) --- 通过串口/CAN 接收新固件,写入 Flash 的高地址区域,然后跳转执行

3.写保护 --- 通过 FLASH_WRPR 可以把某些页设为写保护,防止误擦

4.选项字节(Option Bytes) --- 位于 0x1FFFF800 区域,控制读保护、看门狗、复位等,操作时需要额外解锁 FLASH_OPTKEYR

5:与BKP寄存器的区别

读取flash程序实例

1:字节寻址

在包括 STM32(ARM Cortex-M)在内的几乎所有现代计算机架构 中,内存是按字节编址 的------每个地址指向一个字节(8 bits)。

所以 0x08000000 存的是 1 字节,这是对的。但这不是 flash 的特殊限制,你的 RAM(比如 0x20000000)也是这样的。

2:大端和小端

小端和大端------就是"多字节数据怎么排队"

当你存一个多字节的值(比如 uint32_t 是 4 字节),这 4 个字节在内存里是按什么顺序放的,这就是端序(endianness)。

3:写入半字地址处理

一个地址存一个字节,此处写入的是半字,是两个字节,所以是两个地址存刚好两个字节也就是一个半字,所以循环中,需要给数据的i索引乘上2

MyFLASH_ProgramHalfWord(STORE_START_ADDRESS +i * 2, 0x0000); 让地址索引一次+2

4:创建自己的SRAM

objectivec 复制代码
void Store_Init(void)
{
	/*判断是不是第一次使用*/
	if (MyFLASH_ReadHalfWord(STORE_START_ADDRESS) != 0xA5A5)	//读取第一个半字的标志位,if成立,则执行第一次使用的初始化
	{
		MyFLASH_ErasePage(STORE_START_ADDRESS);					//擦除指定页
		MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5);	//在第一个半字写入自己规定的标志位,用于判断是不是第一次使用
		for (uint16_t i = 1; i < STORE_COUNT; i ++)				//循环STORE_COUNT次,除了第一个标志位
		{
			MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, 0x0000);		//除了标志位的有效数据全部清0
		}
	}
	
	/*上电时,将闪存数据加载回SRAM数组,实现SRAM数组的掉电不丢失*/
	for (uint16_t i = 0; i < STORE_COUNT; i ++)					//循环STORE_COUNT次,包括第一个标志位
	{
		Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i * 2);		//将闪存的数据加载回SRAM数组
	}
}

作用:系统上电时,检查 Flash 里有没有存档;如果没有,就创建初始存档;如果有,就把存档读到 SRAM,实现我们手写的sram数值掉电不丢失,

5:从SRAM写入到flash

objectivec 复制代码
void Store_Save(void)
{
	MyFLASH_ErasePage(STORE_START_ADDRESS);				//擦除指定页
	for (uint16_t i = 0; i < STORE_COUNT; i ++)			//循环STORE_COUNT次,包括第一个标志位
	{
		MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, Store_Data[i]);	//将SRAM数组的数据备份保存到闪存
	}
}

先擦除后写入,包括标志位,也索性从写一下,不想麻烦就i从1起始也可以

6:清空SRAM数组

objectivec 复制代码
void Store_Clear(void)
{
	for (uint16_t i = 1; i < STORE_COUNT; i ++)			//循环STORE_COUNT次,除了第一个标志位
	{
		Store_Data[i] = 0x0000;							//SRAM数组有效数据清0
	}
	Store_Save();										//保存数据到闪存
}
相关推荐
weixin_4640780719 小时前
Altium Designer自定义变压器
嵌入式硬件
QQ52862112420 小时前
芯片程序提取的具体流程和方法
stm32·单片机·嵌入式硬件·程序·pcb抄板
LingzhiPi21 小时前
零知派ESP32-S3-智能小车控制系统(4.2)-红外双目跟随模块使用
单片机·嵌入式硬件
智者知已应修善业1 天前
【proteus交通灯故障检测的完善方案】2025-4-29
经验分享·笔记·单片机·嵌入式硬件·proteus
LingzhiPi1 天前
零知ESP32--RC522NFC考勤打卡系统
c++·单片机·嵌入式硬件
炸膛坦客1 天前
常见代码问题与解答:(二)因外部晶振频率改变导致 MCU 锁死的原因及处理方法
单片机·嵌入式硬件
ShiMetaPi1 天前
ShiMetaPi Pico-G1:百元级黑光全彩AI ISP开发板
人工智能·嵌入式硬件·pico·isp
Lzh编程小栈1 天前
嵌入式深度精讲|STM32引脚全方位底层原理、配置逻辑、硬件规范、高频面试题
c语言·stm32·单片机·嵌入式硬件
AI的探索之旅1 天前
我把立创EDA接进了本地大模型:数据不出门的AI设计检查实测
人工智能·stm32·硬件工程