当前位置:文档之家› STM32内部FLASH读写操作详解

STM32内部FLASH读写操作详解

STM32 芯片内部的 FLASH 存储器,主要用于存储我们代码。

如果内部FLASH存储完我们的代码还有剩余的空间,那么这些剩余的空间我们就可以利用起来,存储一些需要掉电保存的数据。

本文以STM32103ZET6为例。

STM32103ZET6属于大容量产品,其闪存模块组织如下:其主存储器大小为512KB,分为256页,每页大小都为2KB。

我们的程序一般默认烧写到第0页的起始地址(0x08000000)处。

当BOOT0引脚和BOOT1引脚都接GND时,就是从这个地址开始运行代码的。

这个地址在keil中可以看到:假如我们要下载的程序大小为4.05KB,则第0、1、2页用于保存我们的程序,我们需要掉电保存的数据只能保存在第3~第255页这一部分空间内。

我们最终要下载的程序大小可在工程对应的.map文件中看到。

.map文件可以双击工程的Target的名字快速打开,如:下面对STM32内部FLASH进行简单的读写测试:内部FLASH读写测试流程图如下:本流程图省略异常情况,只考虑成功的情况:示例代码:本例的关键代码如下(以读写第255页为例):/******************************************************************** ************************************------------------------------------------STM32 Demo---------------------------------------------------** 工程说明:STM32内部FLASH实验* 作者:ZhengNian* 博客:zhengnianli.github.io* 公众号:嵌入式大杂烩********************************************************************** ***********************************/#define MAIN_CONFIG#include "config.h"/* STM32F103ZET6有256页,每一页的大小都为2KB */#define ADDR_FLASH_PAGE_255 ((uint32_t)0x0807F800) /* Page255 2KB *//* FLASH读写测试结果 */#define TEST_ERROR -1 /* 错误(擦除、写入错误) */#define TEST_SUCCESS 0 /* 成功 */#define TEST_FAILED 1 /* 失败 *//* Flash读写测试buf */#define BufferSize 6uint16_t usFlashWriteBuf[BufferSize] ={0x0101,0x0202,0x0303,0x0404,0x0505,0x0606};uint16_t usFlashReadBuf[BufferSize] = {0};/* 供本文件调用的函数声明 */static int FlashReadWriteTest(void);/******************************************************************** ************************************* 函数: main**------------------------------------------------------------------------------------------------------** 参数: void** 返回: 无** 说明: 主函数********************************************************************* ***********************************/int main(void){/* 上电初始化 */SysInit();/* 内部Flash读写测试 */if (TEST_SUCCESS == FlashReadWriteTest()){printf("Flash test success!\n");}else{printf("Flash test failed!\n");}while (1){}}/******************************************************************** ************************************* 函数: FlashReadWriteTest, 内部Flash读写测试函数**------------------------------------------------------------------------------------------------------** 参数: void** 返回: TEST_ERROR:错误(擦除、写入错误) TEST_SUCCESS:成功TEST_FAILED:失败** 说明: 无********************************************************************* ***********************************/static int FlashReadWriteTest(void){uint32_t ucStartAddr;/* 解锁 */FLASH_Unlock();/* 擦除操作 */ucStartAddr = ADDR_FLASH_PAGE_255;if (FLASH_COMPLETE != FLASH_ErasePage(ucStartAddr)){printf("Erase Error!\n");return TEST_ERROR;}else{ucStartAddr = ADDR_FLASH_PAGE_255;printf("擦除成功,此时FLASH中值为:\n");for (int i = 0; i < BufferSize; i++){usFlashReadBuf[i] = *(uint32_t*)ucStartAddr;printf("ucFlashReadBuf[%d] = 0x%.4x\n", i, usFlashReadBuf[i]);ucStartAddr += 2;}}/* 写入操作 */ucStartAddr = ADDR_FLASH_PAGE_255;printf("\n往FLASH中写入的数据为:\n");for (int i = 0; i < BufferSize; i++){if (FLASH_COMPLETE != FLASH_ProgramHalfWord(ucStartAddr, usFlashWriteBuf[i])){printf("Write Error!\n");return TEST_ERROR;}printf("ucFlashWriteBuf[%d] = 0x%.4x\n", i, usFlashWriteBuf[i]);ucStartAddr += 2;}/* 上锁 */FLASH_Lock();/* 读取操作 */ucStartAddr = ADDR_FLASH_PAGE_255;printf("\n从FLASH中读出的数据为:\n");for (int i = 0; i < BufferSize; i++){usFlashReadBuf[i] = *(__IO uint16_t*)ucStartAddr;printf("ucFlashReadBuf[%d] = 0x%.4x\n", i, usFlashReadBuf[i]);ucStartAddr += 2;}/* 读出的数据与写入的数据做比较 */for (int i = 0; i < BufferSize; i++){if (usFlashReadBuf[i] != usFlashWriteBuf[i]){return TEST_FAILED;}}return TEST_SUCCESS;}/******************************************************************** *************************************** End Of File********************************************************************* ***********************************/(1)进行解锁操作STM32 的闪存编程是由内嵌的闪存编程/擦除控制器(FPEC)管理,这个模块包含的寄存器如下:STM32 复位后, FPEC 模块是被保护的,不能写入 FLASH_CR 寄存器;通过写入特定的序列到 FLASH_KEYR 寄存器可以打开 FPEC 模块(即写入 KEY1和KEY2),只有在写保护被解除后,我们才能操作相关寄存器。

固件库中的函数为:/* 解锁 */void FLASH_Unlock(void);(2)擦除将要写的页STM32 的 FLASH 在编程的时候,也必须要求其写入地址的 FLASH 是被擦除了的(也就是其值必须是 0XFFFF),否则无法写入,在 FLASH_SR 寄存器的PGERR 位将得到一个警告。

STM32 的闪存擦除分为两种:页擦除和整片擦除。

也就是其最小擦除单位为1页,尽管你只需往某页里写10个字节数据或者更少的数据,你也必须先擦除该页(2*1024个字节)。

我们这里使用按页擦除,固件库中按页擦除的函数为:/* 按页擦除 */FLASH_Status FLASH_ErasePage(uint32_t Page_Address);其返回值为枚举:typedef enum{FLASH_BUSY = 1, /* 忙 */FLASH_ERROR_PG, /* 编程错误 */FLASH_ERROR_WRP, /* 写保护错误 */FLASH_COMPLETE, /* 操作完成 */FLASH_TIMEOUT /* 操作超时 */}FLASH_Status;(3)往上一步擦写成功的页写入数据STM32 闪存的编程每次必须写入16 位。

相关主题