STM32CUBEMX | STM32L431RCT6的内部Flash操作

一、STM32CUBEMX配置

1、选择芯片型号:

在这里插入图片描述
在这里插入图片描述

2、配置时钟源

1、 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
2、 如果使用默认内部时钟(HSI),这一步可以略过;

在这里插入图片描述

3、配置时钟树

STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:

在这里插入图片描述

4、代码生成设置

在这里插入图片描述
点击GENERATE CODE即可生成MDK-V5工程:

在这里插入图片描述

二、在MDK中编写、编译、下载用户代码

1、STM32内部Flash及HAL库API

查看所使用芯片的信息,Flash起始地址为0x08000000,大小为0x00040000(256KB):
在这里插入图片描述
STM32L4x1芯片内部的Flash存储器内存分布如下:

在这里插入图片描述
STM32L431RCT6的Flash容量是256KB,所以只有Bank1,有128页,每页2KB。

2、解锁/上锁Flash操作

擦除或者写入内部Flash的时候,需要先解锁再操作,操作完毕之后上锁

HAL_StatusTypeDef  HAL_FLASH_Unlock(void);
HAL_StatusTypeDef  HAL_FLASH_Lock(void);

3、擦除操作

HAL库中定义了一个Flash初始化结构体,如下:

/**
  * @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;

3.1 第一个参数TypeErase是参数类型,分为页擦除和块擦除:

/** @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*/
/**
  * @}
  */

3.2 第二个参数Banks是选择需要擦除哪一块:

由参数中可以看到,STM32L431RCT6中只有Bank1可选:

/** @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
/**
  * @}
  */

3.3 第三个参数Page是初始化擦除页

在STM32L431RCT6中,该值范围是0-127。

3.4 第四个参数NbPages是要擦除的页数

在STM32L431RCT6中,在1-(127-初始化参数页的编号)。

3.5 擦除的时候,调用的API如下:

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);

1、第一个参数是写入类型

/** @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 */
/**
  * @}
  */

五、读取操作

这个就不用API啦~CPU可以直接访问到地址的,读取就好。

六、实验内容

1、首先包含进来头文件:

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h> //使用到了memcpy
/* USER CODE END Includes */

2、然后定义一个测试数据长度:

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LEN						10
/* USER CODE END PD */

3、编写测试函数:

/* 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:\r\n\t");
	for(i = 0;i < LEN;i++)
	{
		printf("0x%08x ", data_buf[i]);
	}
	printf("\r\n");
	
	/* 写入新的数据 */
	//擦除最后一页
	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 = %d\r\n", PageError);
	}
	printf("erase success\r\n");
	
	
	/* 读取Flash内容 */
	memcpy(data_buf, (uint32_t*)addr, sizeof(uint32_t)*LEN);
	printf("read after erase:\r\n\t");
	for(i = 0;i < LEN;i++)
	{
		printf("0x%08x ", data_buf[i]);
	}
	printf("\r\n");

	//写入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 fail\r\n");
	}
	else
	{
		printf("write success\r\n");
	}

	/* 读取Flash内容 */
	addr = 0x0803F800;
	memcpy(data_buf, (uint32_t*)addr, sizeof(uint32_t)*LEN);
	printf("read after write:\r\n\t");
	for(i = 0;i < LEN;i++)
	{
		printf("0x%08x ", data_buf[i]);
	}
	printf("\r\n");
	
}
/* USER CODE END 0 */

4、最后在main.c 调用:

/* USER CODE BEGIN 2 */
printf("stm32l4 onchip flash test...\r\n");
Onchip_Flash_Test();

/* USER CODE END 2 */

七、实验现象

编译、下载、实验现象如下:
在这里插入图片描述

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值