赞
踩
1.FLASH介绍
FLASH存储器写入数据时,每一位只能由“1”变成“0”,不能由“0”变成“1“,因此,当我们有数据要保存到FLASH存储器时,要先对目标段进行整段擦除操作,擦除操作使对应段FLASH存储器变成全“1”,再对需要的位写为“0”,即完成写入操作。
FLASH读写操作流程如下:
(1)对FLASH写入数据
解锁FLASH
擦除FLASH
写入数据到FLASH
锁住FLASH
FLASH读取数据
(2)直接读取相应的FLASH地址
2.代码编写
FLASH读写不需要对STM32CubeMX进行配置,直接调用HAL相关函数进行开发。
在这里插入代码片
//FLASH起始地址
#define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址
#define FLASH_WAITETIME 50000 //FLASH等待超时时间
/* Base address of the Flash sectors /
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) / Base @ of Sector 0, 16 Kbytes /
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) / Base @ of Sector 1, 16 Kbytes /
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) / Base @ of Sector 2, 16 Kbytes /
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) / Base @ of Sector 3, 16 Kbytes /
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) / Base @ of Sector 4, 64 Kbytes /
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) / Base @ of Sector 5, 128 Kbytes /
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) / Base @ of Sector 6, 128 Kbytes /
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) / Base @ of Sector 7, 128 Kbytes /
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) / Base @ of Sector 8, 128 Kbytes /
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) / Base @ of Sector 9, 128 Kbytes /
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) / Base @ of Sector 10, 128 Kbytes /
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) / Base @ of Sector 11, 128 Kbytes */
/**************************************************************** *函数名:STMFLASH_ReadWord *描 述:读取指定地址的字 *参 数:faddr 读地址 *返 回:数据 *****************************************************************/ uint32_t STMFLASH_ReadWord(uint32_t faddr) { return *(__IO uint32_t*)faddr; } /**************************************************************** *函数名:STMFLASH_GetFlashSector *描 述:获取某个地址所在的flash扇区 *参 数:addr:flash地址 *返 回:0~11,即addr所在的扇区 *****************************************************************/ 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; } /**************************************************************** *函数名:STM32FLASH_EraseSector *描 述:擦除地址所在的扇区 *参 数:addrx 地址 *返 回:None *****************************************************************/ void STM32FLASH_EraseSector(uint32_t addrx) { uint32_t SectorError=0; FLASH_EraseInitTypeDef FlashEraseInit; HAL_FLASH_Unlock(); //解锁 FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS; //擦除类型,扇区擦除 FlashEraseInit.Sector = STMFLASH_GetFlashSector(addrx);//要擦除的扇区 FlashEraseInit.NbSectors = 1; //一次只擦除一个扇区 FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; //电压范围,VCC=2.7~3.6V之间!! printf("\r\n************erase************\r\n"); if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError) != HAL_OK) { printf("erase flash error!\r\n"); } HAL_FLASH_Lock(); //上锁 } /**************************************************************** *函数名:STMFLASH_Write *描 述:在指定地址写入固定长度数据 *参 数:WriteAddr 起始地址,pBuffer 数据指针, NumToWrite 要写入的数据的个数 *返 回:-1 失败 *****************************************************************/ void STMFLASH_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite) { FLASH_EraseInitTypeDef FlashEraseInit; HAL_StatusTypeDef FlashStatus=HAL_OK; uint32_t SectorError=0; static uint32_t addrx=0; uint32_t endaddr=0; uint32_t len=0;//,size=0; len = NumToWrite; //size = len/4 + ((len%4)?1:0); if(WriteAddr < STM32_FLASH_BASE || WriteAddr % 4) //非法地址 return; HAL_FLASH_Unlock(); //解锁 addrx = WriteAddr; //写入的起始地址 endaddr = WriteAddr + len; //写入的结束地址 if(addrx<0X1FFF0000) { while(addrx < endaddr) //对非FFFFFFFF的地方,先擦除 { if(STMFLASH_ReadWord(addrx) != 0XFFFFFFFF)//有非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之间!! printf("\r\n************erase************\r\n"); if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError) != HAL_OK) { printf("erase flash error!\r\n"); 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(); //上锁 } /**************************************************************** *函数名:readdata_from_flash *描 述:从指定地址读出固定长度数据 *参 数:readaddr 读地址 pbuffer 读出数据 numtoread 读长度 *返 回:-1 失败 *****************************************************************/ void STMFLASH_Read(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t NumToRead) { uint32_t i; for(i=0;i<NumToRead;i++) { pBuffer[i] = STMFLASH_ReadWord(ReadAddr);//读取4个字节. ReadAddr += 4;//偏移4个字节. } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。