赞
踩
关于Flash,官方的解释为:Flash为32位宽的存储单元,可用于存储代码和数据常量。Flash模块位于微控制器内存映射中的特定基址……。而对于我们来说,只要知道Flash闪存区是一个掉电后也不会清除的数据存储地。(相信大家对于Flash闪存也有着一定 的了解了,我也不多说废话,直接开整)
STM32芯片大致可分为小容量、中容量和大容量三种类型,在小容量和中容量系列芯片中一个扇区为1KB,在大容量系列芯片中一个扇区为2KB,为什么要说这个呢?因为Flash的擦除只能以一个扇区为最小单位擦除。因为代码也是存储在Flash区,所以各位在做项目时,最先就应该将内存分配好,我的建议是将Flash最后一个扇区用来做用户数据存储,我们甚至可以在keil配置好代码地址,这样就每次下载程序时也不会改变最后一个扇区的数据。
例:以STM32F103C6Tx的一款芯片为例(代码部分同),这个芯片拥有32KFlash存储器容量,算是小容量芯片。
如果不设置,IROM1的地址应该为:0x8000000—0x8000,0x8000转换为十进制为32768,除以1024(1KB为1024bit),刚好为32K,减去最后一个扇区1KB,31KB转换为十六进制为0x7C00,设置后就如图所示,IROM1的地址为0x8000000—0x7C00,表示keil写入代码时将不会擦除0x7C00以后的空间,数据也会得以保存。
因为嵌入式Flash模块可以直接寻址,因此读取操作十分简单,只需要找到读取的地址即可。
- uint16_t Flash_Data; //存储数据
- __IO uint16_t * flashPtr; //该指针用来存储Flash读写地址
首先需要定义一个指针,该指针主要用来存储Flash读写的地址,__IO uint16_t数据类型表示flashPtr是一个易变的无符号的大小为16位的指针。
- flashPtr = (__IO uint16_t *) 0x08007C00; //指向数据地址
- Flash_Data = *flashPtr; //读取数据
两行代码就可以完成对Flash的读取,只是指针的简单运用,当然在实际项目中最好加上对提取数据的校验。
写入Flash是一个相对复杂的过程,已经是在对STM芯片底层数据直接编程,废话不多说。Flash写入数据,大致可分为两个步骤,一是擦除数据、二是写入数据。在上代码前,我们先来了解几个会用到的Flash寄存器:
首先是Flash控制寄存器(FLASH_CR),主要了解第0位PG写入控制位、第1位PER擦除控制位、第6位STRT擦除触发控制位和第7位LOCK解锁控制位,再此我不过多介绍,在文章末尾我会提供STM32F103Flash编辑手册,各位自行去阅读(配合手册去理解代码事半功倍)。
其次是Flash状态寄存器(FLASH_SR),主要了解第5位EOP擦除/写入完成标志位,第0位BSYFlash擦除/写入状态位。
FPEC密钥寄存器(FLASH_KEYR),这个寄存器用来写入钥匙,Flash地址寄存器(FLASH_AR)用来写入扇区擦除的首地址。
这个是官方提供写入Flash的具体流程,每次写入前需要先判断FLASH_CR_LOCK位,当为1时可直接进行写入配置,当为0时需要先解锁才能写入配置(为什么要解锁呢?因为每次复位后FPEC(闪存编程和擦除控制器)都是被锁定的,只有解锁后才有权限),写入配置很简单只需要置位FLASH_CR_PG写入位,再把数据(16位)写入指定的地址,再检测是否写好,最后重新上锁。当然写入前需要先擦除,擦除也是同样的操作,接下来请看代码:
- /*Flash解锁函数*/
- void Flash_unlock(void) {
- if ((FLASH->CR & FLASH_CR_LOCK) != RESET) { //判断LOCK位
- FLASH->KEYR = 0x45670123;
- FLASH->KEYR = 0xCDEF89AB;
- /*若LOCK位不为1,则执行解锁程序,向Flash_KEYR寄存器写入解锁密钥,密钥是唯一的,
- 一旦写错,就会锁死,只能复位后才能操作Flash*/
- }
- }
- /*Flash写入函数*/
- void putFlash(void)
-
- Flash_unlock(); //解锁
- SET_BIT(FLASH->CR, FLASH_CR_PER); //置位扇区擦除控制位
- WRITE_REG(FLASH->AR, 0x08007C00); //对应扇区起始地址
- SET_BIT(FLASH->CR, FLASH_CR_STRT); //开始扇区清除
- while ((FLASH->SR & (FLASH_SR_BSY | FLASH_SR_EOP)) != 0x20) //等待擦除完毕
- ;
- FLASH->SR |= FLASH_SR_EOP; //清除标志位
- FLASH->CR = 0x80; //重新上锁,擦除完成
-
- Flash_unlock(); //解锁
- flashPtr = (__IO uint16_t *) 0x08007C00; //选择写入地址,只能是擦除的扇区内
- SET_BIT(FLASH->CR, FLASH_CR_PG); //置位Flash写入控制位
- *flashPtr = Flash_Data; //写入数据到flashPrt地址对应空间中
- while ((FLASH->SR & (FLASH_SR_BSY | FLASH_SR_EOP)) != 0x20) //等待写入完成
- ;
- FLASH->SR |= FLASH_SR_EOP; //清除标志位
- FLASH->CR = 0x80; //重新上锁
- }
通过上面两个函数便可以完成对Flash的写入,当然为了方便大家理解,我代码写的很简单,到了真实项目中,我的代码只能作为你们的思路。
Flash擦除/写入千万、千万、千万不要放到主程序while循环中,因为每一块芯片由于硬件的限制对于Flash的擦除/写入都是次数限制的,一旦用完这些擦除/写入次数,芯片就报废了,当然也不用太小心,一般这个限制次数都是10万次。
Flash擦除/写入是一个比较严谨的过程,一旦出错将会导致整个程序的崩溃,所以希望大家多看看手册。
STM32F103XXFlash编辑手册:链接:https://pan.baidu.com/s/1IdWxsnysqhs6iWfW5oIhaQ
提取码:udbs
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。