使用说明:读写芯片内部flash–stm32cubemx-hal库
1、使用stm32cubemx配置和建立自己的工程文件
2、添加user_flash.h和user_flash.c文件到工程中
3、在需要使用的地方include "user_flash.h"头文件
4、直接调用user_flash.c文件内函数
user_flash.h文件代码如下:
#ifndef __USER_FLASH_H
#define __USER_FLASH_H
#include "main.h"
#define BOARD_NUM_ADDR 0x0800C000
#define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址
#define FLASH_WAITETIME 50000 //FLASH等待超时时间
//FLASH 扇区的起始地址
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) //扇区0起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) //扇区1起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) //扇区2起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) //扇区3起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) //扇区4起始地址, 64 Kbytes
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) //扇区5起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) //扇区6起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) //扇区7起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) //扇区8起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) //扇区9起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) //扇区10起始地址,128 Kbytes
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) //扇区11起始地址,128 Kbytes
uint32_t STMFLASH_ReadWord(uint32_t faddr); //读出字
void STMFLASH_Write(uint32_t WriteAddr, uint32_t *pBuffer, uint32_t NumToWrite); //从指定地址开始写入指定长度的数据
void STMFLASH_Read(uint32_t ReadAddr, uint32_t *pBuffer, uint32_t NumToRead); //从指定地址开始读出指定长度的数据
#endif /*__USER_FLASH_H*/
user_flash.c文件代码如下:
#include "user_flash.h"
/**------------------------------------------
* @brief Gets the sector of a given address
* @param Address: Flash address
* @retval The sector of a given address
--------------------------------------------*/
uint8_t STMFLASH_GetFlashSector(uint32_t addr)
{
if (addr < ADDR_FLASH_SECTOR_1)
return FLASH_SECTOR_0;
else if (addr < ADDR_FLASH_SECTOR_2)
return FLASH_SECTOR_1;
else if (addr < ADDR_FLASH_SECTOR_3)
return FLASH_SECTOR_2;
else if (addr < ADDR_FLASH_SECTOR_4)
return FLASH_SECTOR_3;
else if (addr < ADDR_FLASH_SECTOR_5)
return FLASH_SECTOR_4;
else if (addr < ADDR_FLASH_SECTOR_6)
return FLASH_SECTOR_5;
else if (addr < ADDR_FLASH_SECTOR_7)
return FLASH_SECTOR_6;
else if (addr < ADDR_FLASH_SECTOR_8)
return FLASH_SECTOR_7;
else if (addr < ADDR_FLASH_SECTOR_9)
return FLASH_SECTOR_8;
else if (addr < ADDR_FLASH_SECTOR_10)
return FLASH_SECTOR_9;
else if (addr < ADDR_FLASH_SECTOR_11)
return FLASH_SECTOR_10;
return FLASH_SECTOR_11;
}
uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
return *(__IO uint32_t *)faddr;
}
void STMFLASH_Write(uint32_t WriteAddr, uint32_t *pBuffer, uint32_t Num)
{
FLASH_EraseInitTypeDef FlashEraseInit;
HAL_StatusTypeDef FlashStatus = HAL_OK;
uint32_t SectorError = 0;
uint32_t addrx = 0;
uint32_t endaddr = 0;
if (WriteAddr < STM32_FLASH_BASE || WriteAddr % 4)
return; //非法地址
HAL_FLASH_Unlock(); //解锁
addrx = WriteAddr; //写入的起始地址
endaddr = WriteAddr + Num * 4; //写入的结束地址
if (addrx < 0X080C1000)
{
while (addrx < endaddr)
{
if (STMFLASH_ReadWord(addrx) != 0XFFFFFFFF)
{
FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS; //擦除类型,扇区擦除
FlashEraseInit.Sector = STMFLASH_GetFlashSector(addrx); //要擦除的扇区
FlashEraseInit.NbSectors = 1; //一次只擦除一个扇区
FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; //电压范围,VCC=2.7~3.6V之间!!
if (HAL_FLASHEx_Erase(&FlashEraseInit, &SectorError) != HAL_OK)
{
break; //发生错误了
}
}
else
addrx += 4;
FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
}
}
FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
if (FlashStatus == HAL_OK)
{
while (WriteAddr < endaddr) //写数据
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr, *pBuffer) != HAL_OK) //写入数据
{
break; //写入异常
}
WriteAddr += 4;
pBuffer++;
}
}
HAL_FLASH_Lock(); //上锁
}
void STMFLASH_Read(uint32_t ReadAddr, uint32_t *pBuffer, uint32_t size)
{
uint32_t i;
for (i = 0; i < size; i++)
{
pBuffer[i] = STMFLASH_ReadWord(ReadAddr); //读取4个字节.
ReadAddr += 4; //偏移4个字节.
}
}
参考:https://my.oschina.net/u/4416479/blog/4645445
时间:2021.03.10
学习记录使用