STM32+HAL+ FLASH

STM32+HAL+ FLASH

1、什么是FLASH

能够理解为一种存储空间,和EEPROM差很少,能使数据掉电不丢失web

下图为大容量的编程

在这里插入图片描述

  • 主存储器svg

  • 信息块函数

  • FPEC测试

  • 主存储器ui

该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每页 2K 字节。注意,小容量和中容量产品则每页只有 1K 字节。从上图能够看出主存储器的起始地址就是0X08000000, BOOT0、BOOT1 都接 GND 的时候,就是从 0X08000000 开始运行代码的。spa

  • 信息块

该部分分为 2 个小部分,其中启动程序代码,是用来存储 ST 自带的启动程序,用于串口下载代码,当 BOOT0 接 V3.3, BOOT1 接 GND 的时候,运行的就是这部分代码。用户选择字节,则通常用于配置写保护、读保护等功能,这里咱们不作介绍,你们能够百度了解。code

  • 闪存存储器接口寄存器(FPEC)

该部分用于控制闪存读写等,是整个闪存模块的控制机构。对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。xml

闪存的编程与擦除

FPEC的7个寄存器

  • FPEC 键寄存器(FLASH_ KEYR)
  • 选择字节键寄存器(FLASH OPTKEYR)
  • 闪存控制寄存器(FLASH CR)
  • 闪存状态寄存器(FLASH SR)
  • 闪存地址寄存器(FLASH_ AR)
  • 选择字节寄存器(FLASH OBR)
  • 写保护寄存器(FLASH_ _WRPR)
FLASH_KEYR 写入键值解锁
FLASH_OPTKEYR 写入键值解锁选项字节操做
FLASH_CR 选择并启动闪存操做
FLASH_SR 查询闪存操做状态
FLASH_AR 存储闪存操做地址
FLASH_OBR 选项字节中主要数据的映象
FLASH_WRPR 选项字节中写保护字节的映象

FPEC键寄存器 (FLASH_KEYR)

RDPRT键 KEY 1 KEY 2
0X000000A5 0X45670123 0XCDEF89AB

用途:写入KEY1和KEY2后解锁FPECblog

HAL库函数

锁定与解锁

HAL_StatusTypeDef HAL_FLASH_Unlock(void);//解锁函数
HAL_StatusTypeDef HAL_FLASH_Lock(void);//锁定函数

写操做

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);//FLASH写操做函数 

TypeProgram用来区别要写入的类型:

  • FLASH_TYPEPROGRAM_BYTE-----------------------8位
  • FLASH_TYPEPROGRAM_HALFWORD------------16位
  • FLASH_TYPEPROGRAM_WORD-------------------32位
  • FLASH_TYPEPROGRAM_DOUBLEWORD-------64位

擦除函数

HAL_StatusTypeDef
 HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError);

pEraseInit结构体定义

typedef struct
{
  uint32_t TypeErase;   /*!< TypeErase: Mass erase or page erase. 擦除类型 This parameter can be a value of @ref FLASHEx_Type_Erase */
  
  uint32_t Banks;       /*!< Select banks to erase when Mass erase is enabled.Bank编号 This parameter must be a value of @ref FLASHEx_Banks */    
  
  uint32_t PageAddress; /*!< PageAdress: Initial FLASH page address to erase when mass erase is disabled 擦除页面地址 This parameter must be a number between Min_Data = 0x08000000 and Max_Data = FLASH_BANKx_END (x = 1 or 2 depending on devices)*/
  
  uint32_t NbPages;     /*!< NbPages: Number of pagess to be erased. 页数 This parameter must be a value between Min_Data = 1 and Max_Data = (max number of pages - value of initial page)*/
                                                          
} FLASH_EraseInitTypeDef;

等待函数

HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
  /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. Even if the FLASH operation fails, the BUSY flag will be reset and an error flag will be set */

读 FLASH特定地址数据函数(正点原子)

u16 STMFLASH_ReadHalfWord(u32 faddr){
    return *(vu16*)faddr;
}

编程流程

解锁 HAL_FLASH_Unlock();
擦除 **HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef pEraseInit, uint32_t PageError);
写入 HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
上锁 HAL_FLASH_Lock();

参考代码

uint32_t writeFlashData = 0x00000009;
uint32_t addr = 0x08007000;

//FLASH写入数据测试
void FLASH_WRITE(void)
{
    FLASH_EraseInitTypeDef f;
	f.TypeErase = FLASH_TYPEERASE_PAGES;
	f.PageAddress = addr;
	f.NbPages = 1;
	uint32_t PageError = 0;
    //解锁
  HAL_FLASH_Unlock();
	//擦除
	HAL_FLASHEx_Erase(&f, &PageError);

	//写入
	HAL_FLASH_Program(TYPEPROGRAM_WORD, addr, writeFlashData);
	
	//上锁
  HAL_FLASH_Lock();
}

//FLASH读取数据测试
void Prinf_FLASH(void)
{
  uint32_t temp = *(__IO uint32_t*)(addr);

	printf("addr:0x%x, data:0x%x\r\n", addr, temp);
}

主函数

void main(void)
{
	writeFlashData = 0x00000009;
	FLASH_WRITE();
	Prinf_FLASH();
	while(1);
}