STM32CubMx (八) FLASH读写

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个字节. 
	}
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值