1. STM32F103内部FLASH基础认知
大家好,我是张工,一个在嵌入式行业摸爬滚打十多年的老工程师。今天我想和大家聊聊STM32F103内部FLASH数据存储的那些事儿。很多初学者第一次接触内部FLASH存储时都会有点懵,其实只要掌握几个关键概念,你会发现它比外挂EEPROM简单多了。
STM32F103的内部FLASH就像是我们手机的内部存储空间,掉电后数据不会丢失,非常适合存储设备参数、校准数据、运行配置等信息。我做过不少项目,比如智能电表、工业控制器,都是直接用内部FLASH来存储关键参数的,省去了外置存储芯片的成本和布线麻烦。
这里有个重要概念需要理解:STM32F103的FLASH地址从0x08000000开始,这个地址是固定的。不同容量的芯片结束地址不同,比如64KB的C8T6结束于0x0800FFFF,而512KB的VET6结束于0x0807FFFF。你可以把这片FLASH空间想象成一栋大楼,每个地址对应一个房间,我们要做的就是往合适的房间里存放数据。
在实际项目中,我通常会把FLASH空间分成两个区域:程序区和数据区。程序区存放固件代码,数据区存放需要掉电保存的参数。为了避免误操作覆盖代码,一定要确保数据区位于程序区之后的安全位置。怎么确定程序用了多少空间呢?编译后查看生成的map文件就能找到答案。
2. 深入理解FLASH地址映射与扇区划分
2.1 地址映射原理
STM32F103的FLASH地址映射是个很有意思的设计。物理上FLASH是从0x08000000开始,但这个地址区域同时被映射到0x00000000。这种设计主要是为了支持不同的启动模式,当芯片设置为从主闪存启动时,0x00000000地址实际上访问的就是0x08000000开始的FLASH空间。
我在第一次接触这个特性时也迷糊过,后来想通了就好理解了。你可以把0x00000000想象成一个快捷方式,它指向的是0x08000000的实际内容。这种映射关系是由芯片的BOOT引脚配置决定的,一般情况下我们不需要特别关注,只需要记住操作FLASH时使用0x08000000开始的地址就对了。
2.2 扇区划分的奥秘
STM32F103的FLASH不是一整块均匀的空间,而是被划分成多个扇区。这里有个很重要的知识点:不同容量的芯片,扇区大小是不一样的!小容量产品(小于256KB)的扇区大小是1KB,而大容量产品(大于等于256KB)的扇区大小是2KB。
这个差异在实际开发中很容易踩坑。我曾经有个项目先用了STM32F103C8T6(64KB),后来升级到STM32F103VET6(512KB),就因为扇区大小不同导致数据存储出了问题。所以一定要根据芯片容量来定义扇区大小:
#define FLASH_SIZE 512 // 单位KB
#if FLASH_SIZE < 256
#define SECTOR_SIZE 1024 // 1KB
#else
#define SECTOR_SIZE 2048 // 2KB
#endif
扇区是擦除操作的最小单位,这意味着即使你只想修改一个字节,也必须把整个扇区擦除。这就像写字板,你想修改其中一个字,得先把整页擦干净再重新写。理解这一点对设计存储方案至关重要。
2.3 跨容量型号的兼容性设计
在实际产品开发中,我们经常需要为不同型号的芯片设计兼容的代码。比如同一个产品线,基础版用64KB的C8T6,高级版用512KB的VET6。这时候就需要做好FLASH存储的兼容性设计。
我的经验是采用抽象层设计,把FLASH操作封装成统一的接口,底层根据芯片容量自动适配。比如这样定义存储地址:
// 根据芯片容量确定数据存储起始地址
#if FLASH_SIZE == 64
#define DATA_START_ADDR 0x0800F000 // 64KB芯片的最后4KB
#elif FLASH_SIZE == 512
#define DATA_START_ADDR 0x0807F000 // 512KB芯片的最后4KB
#endif
这样设计的好处是上层应用不需要关心具体芯片型号,只需要调用统一的读写接口。我在多个项目中都采用这种方案,大大提高了代码的可移植性和可维护性。
3. FLASH读写操作实战详解
3.1 读操作:简单如读取变量
FLASH的读操作非常简单,因为
1662



被折叠的 条评论
为什么被折叠?



