STM32 FLASH 简单读写操作【有代码】

【举报再看养成习惯,噢 不对,点赞再看 养成习惯。感谢支持】

STM32的Flash操作分为读写:读写。

一、读操作

读取比较简单,直接指针解引用地址就可以读取。注意一下读取的单位即可

/*************************************************************
** Function name:       STMFLASH_ReadWord
** Descriptions:        读操作
** Input parameters:    要读取的地址
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
	return *(uint32_t*)faddr; 
}


/*************************************************************
** Function name:       STMFLASH_Read
** Descriptions:        连续读取操作
** Input parameters:    NumToRead 要读取的数据个数,单位为uint32
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
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个字节.	
	}
}

二、写操作

注意事项:写操作之前需要先对扇区进行擦除,以STM32G030F6举例,打开JFlash可以看到芯片的具体分区,2K为一个扇区,一共16个扇区。

 所以之后我们擦除的时候每次就要擦除2K数据。接下来看代码

// G030F6P6 Flash共计32K  16个扇区  计划使用后后两个扇区,即4K存储数据 ,单次最小擦除2K数据?有待确定

#define FLASH_SECTOR14_START                      0x08007000
#define FLASH_SECTOR14_END                        0x080077FF
#define FLASH_SECTOR15_START                      0x08007800
#define FLASH_SECTOR15_END                        0x08007FFF

#define FLASH_DATA_ADDR_MIN                         FLASH_SECTOR14_START
#define FLASH_DATA_ADDR_MAX                         FLASH_SECTOR15_END

#define FLASH_DATA_ADDR_BASE                        FLASH_DATA_ADDR_MIN
#define CALIBRATION_L_LR_VALUE_ADDR                 FLASH_DATA_ADDR_BASE+0
#define CALIBRATION_L_UD_VALUE_ADDR                 FLASH_DATA_ADDR_BASE+12
#define CALIBRATION_R_LR_VALUE_ADDR                 FLASH_DATA_ADDR_BASE+24
#define CALIBRATION_R_UD_VALUE_ADDR                 FLASH_DATA_ADDR_BASE+36
#define FLASH_WAITETIME                             1000

// bind addr长度为5字节  实际占用2个uint32
#define BIND_MSG_BASE                       FLASH_SECTOR15_START     
#define BIND_ADDR                           BIND_MSG_BASE+0




/*************************************************************
** Function name:       STM32G0_GetFlashSector
** Descriptions:        获取G030芯片中addr所在的扇区
** Input parameters:    None
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
uint8_t STM32G0_GetFlashSector(uint32_t addr){
	if (addr >= FLASH_SECTOR14_START && addr <= FLASH_SECTOR14_END){
		return 14;
	}else if (addr >= FLASH_SECTOR15_START && addr <= FLASH_SECTOR15_END){
		return 15;
	}
	return 16;
}

/*************************************************************
** Function name:       STMFLASH_Write
** Descriptions:        STM32写操作
** Input parameters:    pBuffer 传入需要存储的指针、 NumToWrite 需要写入的字节数量/8(单次最少写入双字大小 8字节)
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
void STMFLASH_Write(uint32_t WriteAddr, uint32_t *pBuffer, uint32_t NumToWrite)	
{ 
	FLASH_EraseInitTypeDef FlashEraseInit;
	HAL_StatusTypeDef FlashStatus = HAL_OK;
	uint32_t PageError = 0;
	uint32_t addrx = 0;
	uint32_t endaddr = 0;	
	if(WriteAddr < FLASH_DATA_ADDR_MIN || WriteAddr % 4)  return;	//非法地址 禁止写入的范围
	HAL_FLASH_Unlock();                         //解锁	
	addrx = WriteAddr;				            //写入的起始地址
	endaddr = WriteAddr + NumToWrite * 8;	    //写入的结束地址
	if(addrx < FLASH_DATA_ADDR_MAX)
	{
		while(addrx < endaddr)		        //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
		{   
			if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)	//有非0XFFFFFFFF的地方,要擦除这个扇区
			{   
				FlashEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;    //擦除类型,页擦除 
				FlashEraseInit.Page = STM32G0_GetFlashSector(addrx);      //从哪页开始擦除
				FlashEraseInit.NbPages = 1;                          //一次只擦除一页
				SEGGER_RTT_printf(0,"Flash Erase page is %d\r\n",FlashEraseInit.Page);
				if(HAL_FLASHEx_Erase(&FlashEraseInit, &PageError) != HAL_OK) 
				{
					SEGGER_RTT_printf(0,"Flash Erase err\r\n");
					break;      //发生错误了	
				}
				FLASH_WaitForLastOperation(FLASH_WAITETIME);            //等待上次操作完成
			}else {
				addrx += 4;
			}
		}
	}
	FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME);        //等待上次操作完成
	if(FlashStatus == HAL_OK)
	{
		while(WriteAddr < endaddr)									//写数据
		{
			if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, WriteAddr, *(uint64_t*)pBuffer) != HAL_OK)//写入数据
			{
				break;												//写入异常
			}
			WriteAddr += 8;     //地址加8
			pBuffer += 2;       //buff传进来的是32位的,所以这里+2 便是8个字节
		}  
		SEGGER_RTT_printf(0,"Flash write ok\r\n");
	}
	FLASH_WaitForLastOperation(FLASH_WAITETIME);        //等待上次操作完成
	HAL_FLASH_Lock();           									//上锁
} 

STM32G0_GetFlashSector函数可以获取输入地址在芯片的那个扇区,需要根据具体的芯片信息来更改。

STMFLASH_Write函数主要注意存储数据大小,函数注释中写了。要根据不同的芯片的Program函数来更改。

注意这里贴出的函数只能进行一些简单的存储操作,如果往同一个扇区的不同地方写入数据,第一次会写入成功,第二次会失败。函数中下图圈起来的地方应该检测要写入的扇区所有的地址才对,这里只检测了起始地址到结束地址的数据。如果写入数据在同一个扇区,但是不在同一个位置就会出现BUG。写入失败

 

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值