1. Flash区间介绍
在 stm32f413 中,flash_ex.h 对 flash 页信息的文件描述中,共有
FLASH_SECTOR_0 - FLASH_SECTOR_15,这里面的flash大小为1.5M,容量较大一些,
其中:
FLASH_SECTOR_0 至 FLASH_SECTOR_3 为16K;
FLASH_SECTOR_4 为 64K;
FLASH_SECTOR_0 至 FLASH_SECTOR_4 共计128K;
FLASH_SECTOR_5 至 FLASH_SECTOR_15 每页大小为128K;
这里所用Flash为1M空间,FLASH_SECTOR范围:
FLASH_SECTOR_0 - FLASH_SECTOR_11 共11页,每页大小与1.5M的相同;
页起始对应地址如下:
2. 写操作
2.1 按字节写入
头文件:
#include “main.h”
#include “stm32flash.h”
#include “stm32f4xx_hal.h”
#include “stdio.h”
获取页地址代码
uint8_t STMFLASH_GetFlashSector(uint32_t flash_addr)
{
if(flash_addr < ADDR_FLASH_SERTOR_1)
{
return FLASH_SECTOR_0;
}
else if(flash_addr < ADDR_FLASH_SERTOR_2)
{
return FLASH_SECTOR_1;
}
else if(flash_addr < ADDR_FLASH_SERTOR_3)
{
return FLASH_SECTOR_2;
}
else if(flash_addr < ADDR_FLASH_SERTOR_4)
{
return FLASH_SECTOR_3;
}
else if(flash_addr < ADDR_FLASH_SERTOR_5)
{
return FLASH_SECTOR_4;
}
else if(flash_addr < ADDR_FLASH_SERTOR_6)
{
return FLASH_SECTOR_5;
}
else if(flash_addr < ADDR_FLASH_SERTOR_7)
{
return FLASH_SECTOR_6;
}
else if(flash_addr < ADDR_FLASH_SERTOR_8)
{
return FLASH_SECTOR_7;
}
else if(flash_addr < ADDR_FLASH_SERTOR_9)
{
return FLASH_SECTOR_8;
}
else if(flash_addr < ADDR_FLASH_SERTOR_10)
{
return FLASH_SECTOR_9;
}
else if(flash_addr < ADDR_FLASH_SERTOR_11)
{
return FLASH_SECTOR_10;
}
else
{
return FLASH_SECTOR_11;
}
}
单字节写入代码
void STMFLASH_Write_Byte(uint32_t WriteAddr, uint8_t *pBuffer) //写入1个字节
{
//定义各种变量
FLASH_EraseInitTypeDef FlashEraseInit;
HAL_StatusTypeDef FlashStatus=HAL_OK;
u32 SectorError=0;
//解锁FLASH
HAL_FLASH_Unlock();
//判断地址合法
if(WriteAddr<0X1FFF0000)
{
//初始化擦除变量
FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS; //
FlashEraseInit.Sector=FLASH_SECTOR_5; //
FlashEraseInit.NbSectors=1; //
FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3; //
if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK)
{
printf("Erase failed! \r\n");
}
//FLASH操作是否完成
FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME); //
if(FlashStatus==HAL_OK)
{
//写操作,按字节写入
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, WriteAddr, *pBuffer)!=HAL_OK)//
{
printf("write failed! \r\n");
}
else
{
printf("write successed! \r\n");
}
}
else
{
printf("FlashStatus failed! \r\n");
}
//FLASH上锁
HAL_FLASH_Lock(); //
}
}
写入时发现的问题:写入速度较慢,用了几乎1S,太慢了,不过只写一个标志位的话还是可以接受的。
写入结果:循环写入到该地址,正常。
2.2 多字节写入
头文件:
#include “main.h”
#include “stm32flash.h”
#include “stm32f4xx_hal.h”
#include “stdio.h”
/*多字节写入*/
void STMFLASH_Write_Byte_Long(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t wt_len)
{
FLASH_EraseInitTypeDef FlashEraseInit;
HAL_StatusTypeDef FlashStatus=HAL_OK;
uint32_t SectorError=0;
uint32_t flash_addr = WriteAddr; //要写入的地址
uint32_t flash_end_addr = WriteAddr + wt_len; //结束地址
uint32_t flash_len = wt_len; //要写入的长度
uint8_t flash_page_num; //
flash_page_num = STMFLASH_GetFlashSector(WriteAddr); //首页地址
HAL_FLASH_Unlock(); //
/*判断当前地址是否超出范围*/
while(flash_addr < flash_end_addr)
{
FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS; //
FlashEraseInit.Sector=STMFLASH_GetFlashSector(flash_addr); //
FlashEraseInit.NbSectors=1; //
FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3; //
if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK)
{
printf("Erase failed! \r\n");
}
FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME); //
if(FlashStatus==HAL_OK)
{
/*只要长度存在,循环写入*/
while(flash_len--)
{
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, flash_addr, *pBuffer)!=HAL_OK)
{
printf("write failed!\r\n");
}
pBuffer++;
flash_addr++;
/*判断当前写入地址是否超出当前页*/
if(flash_page_num < STMFLASH_GetFlashSector(flash_addr)) //超出
{
flash_page_num = STMFLASH_GetFlashSector(flash_addr);
break;
}
}
}
}
printf("write successed!\r\n");
HAL_FLASH_Lock(); //
}
测试
写入结果
测试在页边缘写入
写入结果,写入时间不到1.5S
3. 读取代码
按字节读取
/*
* 读取字节 8位
* faddr - 地址
* */
uint8_t STMFLASH_ReadByte(uint32_t faddr)
{
return *(__IO uint8_t*)faddr;
}
按半字16位读取
/*
* 读取 16位
* faddr - 地址
* */
uint16_t STMFLASH_ReadByte(uint32_t faddr)
{
return *(__IO uint16_t*)faddr;
}