本系列文章汇总: 本篇文章主要介绍如何使用STM32中的片内FLash。 如果使用的是STM32F1系列,请先看这篇文章!!!(STM32CubeMX生成F1的工程中造成 下载器无法下载 问题的解决方案) 打开STM32CubeMX,打开MCU选择器: 搜索并选中芯片 这里我都使用外部时钟: 小熊派开发板板载ST-Link并且虚拟了一个串口,原理图如下: 这里我将开关拨到 接下来开始配置 STM32L4的最高主频到80M,所以配置PLL,最后使 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uC8VFP4r-1591787333797)(https://mculover666.cn/blog/20200610/zENXSh7HqWOq.png?imageslim)] 最后设置生成独立的初始化文件: 点击 查看所使用芯片的信息,Flash起始地址为0x08000000,大小为0x00040000(256KB): STM32L4x1芯片内部的Flash存储器内存分布如下: STM32L431RCT6的Flash容量是256KB,所以只有Bank1,有128页,每页2KB。 擦除或者写入内部Flash的时候,需要先解锁再操作,操作完毕之后上锁: HAL库中定义了一个Flash初始化结构体,如下: 第一个参数TypeErase是参数类型,分为页擦除和块擦除: 第二个参数Banks是选择需要擦除哪一块: 由参数中可以看到,STM32L431RCT6中只有Bank1可选。 第三个参数Page是初始化擦除页,在STM32L431RCT6中,该值范围是0-127。 第四个参数NbPages是要擦除的页数,在STM32L431RCT6中,在1-(127-初始化参数页的编号)。 擦除的时候,调用的API如下: 第一个参数是写入类型: 这个就不用API啦~CPU可以直接访问到地址的,读取就好。 首先包含进来头文件: 然后定义一个测试数据长度: 编写测试函数: 最后在main.c 调用: 编译、下载、实验现象如下: 更多精彩文章及资源,请关注我的微信公众号:『mculover666』。
1. 准备工作
硬件准备
首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi):软件准备
2.生成MDK工程
选择芯片型号
STM32L431RCT6
:配置时钟源
配置串口
AT-MCU
模式,使PC的串口与USART1之间连接。USART1
:配置时钟树
HCLK = 80Mhz
即可:生成工程设置
代码生成设置
生成代码
GENERATE CODE
即可生成MDK-V5工程:3. 在MDK中编写、编译、下载用户代码
重定向printf
STM32内部Flash及HAL库API
解锁/上锁Flash操作
HAL_StatusTypeDef HAL_FLASH_Unlock(void); HAL_StatusTypeDef HAL_FLASH_Lock(void);
擦除操作
/** * @brief FLASH Erase structure definition */ typedef struct { uint32_t TypeErase; /*!< Mass erase or page erase. This parameter can be a value of @ref FLASH_Type_Erase */ uint32_t Banks; /*!< Select bank to erase. This parameter must be a value of @ref FLASH_Banks (FLASH_BANK_BOTH should be used only for mass erase) */ uint32_t Page; /*!< Initial Flash page to erase when page erase is disabled This parameter must be a value between 0 and (max number of pages in the bank - 1) (eg : 255 for 1MB dual bank) */ uint32_t NbPages; /*!< Number of pages to be erased. This parameter must be a value between 1 and (max number of pages in the bank - value of initial page)*/ } FLASH_EraseInitTypeDef;
/** @defgroup FLASH_Type_Erase FLASH Erase Type * @{ */ #define FLASH_TYPEERASE_PAGES ((uint32_t)0x00) /*!<Pages erase only*/ #define FLASH_TYPEERASE_MASSERASE ((uint32_t)0x01) /*!<Flash mass erase activation*/ /** * @} */
/** @defgroup FLASH_Banks FLASH Banks * @{ */ #define FLASH_BANK_1 ((uint32_t)0x01) /*!< Bank 1 */ #if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) #define FLASH_BANK_2 ((uint32_t)0x02) /*!< Bank 2 */ #define FLASH_BANK_BOTH ((uint32_t)(FLASH_BANK_1 | FLASH_BANK_2)) /*!< Bank1 and Bank2 */ #else #define FLASH_BANK_BOTH ((uint32_t)(FLASH_BANK_1)) /*!< Bank 1 */ #endif /** * @} */
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError);
写入操作
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
/** @defgroup FLASH_Type_Program FLASH Program Type * @{ */ #define FLASH_TYPEPROGRAM_DOUBLEWORD ((uint32_t)0x00) /*!<Program a double-word (64-bit) at a specified address.*/ #define FLASH_TYPEPROGRAM_FAST ((uint32_t)0x01) /*!<Fast program a 32 row double-word (64-bit) at a specified address. And another 32 row double-word (64-bit) will be programmed */ #define FLASH_TYPEPROGRAM_FAST_AND_LAST ((uint32_t)0x02) /*!<Fast program a 32 row double-word (64-bit) at a specified address. And this is the last 32 row double-word (64-bit) programmed */ /** * @} */
读取操作
实验内容
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdio.h> #include <string.h> //使用到了memcpy /* USER CODE END Includes */
/* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define LEN 10 /* USER CODE END PD */
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void Onchip_Flash_Test(void) { int i; uint32_t PageError = 0; FLASH_EraseInitTypeDef FlashSet; HAL_StatusTypeDef status; uint32_t addr = 0x0803F800; uint32_t data_buf[LEN]; /* 读取Flash内容 */ memcpy(data_buf, (uint32_t*)addr, sizeof(uint32_t)*LEN); printf("read before erase:rnt"); for(i = 0;i < LEN;i++) { printf("0x%08x ", data_buf[i]); } printf("rn"); /* 写入新的数据 */ //擦除最后一页 FlashSet.TypeErase = FLASH_TYPEERASE_PAGES; FlashSet.Banks = FLASH_BANK_1; FlashSet.Page = 127; FlashSet.NbPages = 1; //解锁Flash操作 HAL_FLASH_Unlock(); status = HAL_FLASHEx_Erase(&FlashSet, &PageError); HAL_FLASH_Lock(); if(status != HAL_OK) { printf("erase fail, PageError = %drn", PageError); } printf("erase successrn"); /* 读取Flash内容 */ memcpy(data_buf, (uint32_t*)addr, sizeof(uint32_t)*LEN); printf("read after erase:rnt"); for(i = 0;i < LEN;i++) { printf("0x%08x ", data_buf[i]); } printf("rn"); //写入Flash内容 HAL_FLASH_Unlock(); for (i = 0; i < LEN * sizeof(uint32_t); i+=8) { //一个字是32位,一次写入两个字,64位,8个字节 status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr + i, (uint64_t)i); if(status != HAL_OK) { break; } } HAL_FLASH_Lock(); if(i < LEN) { printf("write failrn"); } else { printf("write successrn"); } /* 读取Flash内容 */ addr = 0x0803F800; memcpy(data_buf, (uint32_t*)addr, sizeof(uint32_t)*LEN); printf("read after write:rnt"); for(i = 0;i < LEN;i++) { printf("0x%08x ", data_buf[i]); } printf("rn"); } /* USER CODE END 0 */
/* USER CODE BEGIN 2 */ printf("stm32l4 onchip flash test...rn"); Onchip_Flash_Test(); /* USER CODE END 2 */
实验现象