(超详细)STM32芯片Flash读写操作讲解和代码(寄存器版本)

关于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读操作

因为嵌入式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写操作

写入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的写入,当然为了方便大家理解,我代码写的很简单,到了真实项目中,我的代码只能作为你们的思路。

注意事项:

  1. Flash擦除/写入千万、千万、千万不要放到主程序while循环中,因为每一块芯片由于硬件的限制对于Flash的擦除/写入都是次数限制的,一旦用完这些擦除/写入次数,芯片就报废了,当然也不用太小心,一般这个限制次数都是10万次。

  1. Flash擦除/写入是一个比较严谨的过程,一旦出错将会导致整个程序的崩溃,所以希望大家多看看手册。

手册资料:

STM32F103XXFlash编辑手册:链接:https://pan.baidu.com/s/1IdWxsnysqhs6iWfW5oIhaQ

提取码:udbs

  • 18
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是一个简单的示例代码,用于在STM32F031微控制器上进行Flash读写操作: ```c #include "stm32f0xx.h" #define ADDR_FLASH_PAGE_127 ((uint32_t)0x0803F800) /* Flash 127 Page Address */ void flash_erase_page(uint32_t page_address) { FLASH_Unlock(); /* Unlock the Flash to enable the flash control register access */ /* Clear pending flags (if any) */ FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR); /* Erase the Flash page */ FLASH_ErasePage(page_address); FLASH_Lock(); /* Lock the Flash to disable the flash control register access */ } void flash_write_word(uint32_t address, uint32_t data) { FLASH_Unlock(); /* Unlock the Flash to enable the flash control register access */ /* Clear pending flags (if any) */ FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR); /* Write the word data into the specified address */ FLASH_ProgramWord(address, data); FLASH_Lock(); /* Lock the Flash to disable the flash control register access */ } uint32_t flash_read_word(uint32_t address) { return (*(__IO uint32_t*) address); } int main(void) { uint32_t data = 0x12345678; uint32_t read_data; flash_erase_page(ADDR_FLASH_PAGE_127); /* Erase the flash page */ flash_write_word(ADDR_FLASH_PAGE_127, data); /* Write data to flash */ read_data = flash_read_word(ADDR_FLASH_PAGE_127); /* Read data from flash */ return 0; } ``` 需要注意的是,Flash写入操作会擦除整个Flash页面,因此在写入之前需要先擦除页面。Flash读取操作可以直接从指定地址读取数据。同时,需要在进行Flash操作之前解锁Flash,操作完成之后再锁定Flash以保护Flash数据的完整性。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值