零基础STM32单片机编程入门(二十四) 内部FLASH详解及读写实战含源码

一.概要

STM32F103C8T6是一款强大而灵活的微控制器,它的片内Flash存储器可以用来存储有关代码和数据,在实际应用中,我们也需要对这个存储器进行读写操作。

STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。页面典型的用途就是用于按页擦除FLASH。从这点来看,页面有点像通用FLASH的扇区。
本文介绍了STM32F103C8T6的FLASH存储空间,FLASH数据的读写,以及读写保护等。

二.内部FLASH地址空间排布

根据用途,STM32片内的FLASH分成两部分:主存储块、信息块。
主存储块用于存储程序,我们写的程序一般存储在这里,用户还可以存储数据。
信息块又分成两部分:系统存储器、选项字节。 系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。这个区域由芯片厂写入BootLoader,然后锁死,用户是无法改变这个区域的。 选项字节存储芯片的配置信息及对主存储块的保护信息,主要有写保护字节,读保护字节等。

STM32F103C8T6是中容量产品主存储块64-128KB, 每页1KB,系统存储器2KB(启动代码),存储空间如下图:
在这里插入图片描述

三.内部FLASH主要特色

在这里插入图片描述

四.内部FLASH读写操作

1.FLASH数据读取

内置闪存模块可以在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相应的数据。
以下是一个示例代码,展示了如何在C语言中读取STM32F103的内部Flash数据
// 假设我们要读取的数据在Flash地址0x8000000的位置
#define FLASH_ADDRESS 0x8000000
uint32_t data = (uint32_t)FLASH_ADDRESS;

2.FLASH数据擦除

STM32F103的FLASH在写入数据前确实需要先进行擦除操作。‌这是因为FLASH存储器的特性决定的,‌与其它FLASH存储器一样,‌STM32F103的FLASH也是按页(‌扇区)‌进行管理的,FLASH可以按页擦除,也可以整片擦除。

按页擦除操作流程:
在这里插入图片描述

3.FLASH数据写入

对主存储器数据写入每次可以写入16位。当FLASH_CR寄存器的PG位为’1’时,在一个闪存地址写入一个半字将启动一次编程;写入任何非半字的数据,都会产生总线错误。

FLASH数据写入操作流程:
在这里插入图片描述

五.内部FLASH的各种保护

1.写保护

STM32F103的FLASH写保护可以通过编程特定的选项字节来启用或禁用,以便保护特定的内存区域免受未经授权的写入,用于避免误写/误擦除操作。

对于STM32F103C8T6写保护是以WRPx选项字节每1比特位代表4页为单位实现的。
在这里插入图片描述

2.读保护

将Flash设置为读保护的目的,是为了防止其他人通过STLINK等仿真器,将Flash中的程序读取出来(设想一下,你辛辛苦苦研发的产品,别人通过仿真器将程序读取出来,再copy一下产品的硬件,就可以生产),所以可以通过将Flash设置为读保护来保护自己的程序。

读保护是通过设置RDP选择字节进行对FLASH的读保护。
在这里插入图片描述

六.FLASH读写例程

硬件准备:

STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口。

在这里插入图片描述

打开STM32CubeMX软件,新建工程
在这里插入图片描述
Part Number处输入STM32F103C8,再双击就创建新的工程
在这里插入图片描述
配置下载口引脚
在这里插入图片描述
配置外部晶振引脚
在这里插入图片描述

配置系统主频
在这里插入图片描述
配置工程文件名,保存路径,KEIL5工程输出方式
在这里插入图片描述
生成工程
在这里插入图片描述
用Keil5打开工程
在这里插入图片描述
添加代码,FLASH解锁,FLASH写入,FLASH数据读取
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#define FLASH_USER_START_ADDR   (FLASH_BASE + (16 * FLASH_PAGE_SIZE)) //FLASH写入的起始地址,0x08004000
#define FLASH_USER_END_ADDR     (FLASH_USER_START_ADDR + FLASH_PAGE_SIZE)//FLASH写入的结束地址

#define DATA_32                 ((uint32_t)0x12345678)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t Address = 0, PAGEError = 0;//页管理变量
__IO uint32_t data32 = 0 , MemoryProgramStatus = 0;

/*Variable used for Erase procedure*/
static FLASH_EraseInitTypeDef EraseInitStruct;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();//初始化1毫秒 Tick

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();//外部8M晶振,系统72M主频

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	HAL_FLASH_Unlock();//FLASH解锁

  /* Erase the user Flash area
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/

  /* Fill EraseInit structure*/
  EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
  EraseInitStruct.PageAddress = FLASH_USER_START_ADDR;
  EraseInitStruct.NbPages     = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / 	FLASH_PAGE_SIZE;

  if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)//擦除FLASH
  {
  }

  /* Program the user Flash area word by word
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
  Address = FLASH_USER_START_ADDR;
  while (Address < FLASH_USER_END_ADDR)
  {
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32) == HAL_OK)//把0x12345678写入0x08008000开始的地址
    {
      Address = Address + 4;
    }
    else
    {
      /* Error occurred while writing data in Flash memory.
         User can add here some code to deal with this error */
    }
  }

  /* Lock the Flash to disable the flash control register access (recommended
     to protect the FLASH memory against possible unwanted operation) *********/
  HAL_FLASH_Lock();//FLASH锁

  /* Check if the programmed data is OK
      MemoryProgramStatus = 0: data programmed correctly
      MemoryProgramStatus != 0: number of words not programmed correctly ******/
  Address = FLASH_USER_START_ADDR;
  MemoryProgramStatus = 0x0;

  while (Address < FLASH_USER_END_ADDR)//取出来比对
  {
    data32 = *(__IO uint32_t *)Address;

    if (data32 != DATA_32)
    {
      MemoryProgramStatus++;
    }
    Address = Address + 4;
  }


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
}

七.CubeMX工程源代码下载

通过百度网盘分享的文件:24.片上FLASH读写实验.rar
链接:https://pan.baidu.com/s/1-pvP7qU-0mCBnu-_EbZucw
提取码:gixg
如果链接失效,可以联系博主给最新链接

程序下载下来之后解压就行

八.小结

在STM32的开发过程中,保存用户数据、‌实现程序的自我更新等应用场景都离不开对FLASH读写操作。

  • 33
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值