STM32G030C8T6读写flash

        最近选型使用STM32G030这款芯片,由于做的功能需要频繁读写flash,最开始没有注意到芯片的擦写次数是1000次,为了确保功能实现,只能是每次写入flash时判断当前页是否写满,写满才擦除重新开始写;

         每次需要写入flash的数据长度小于128字节,以128字节计算,每一页可以写入16=2048/128 次; STM32G030C8T6最少可以写入16000次;如果对写入次数需求高的,可以减少每次写入数据的长度;

STM32G030C8T6写入特性参考:stm32g030 内部flash存储一些用户数据的方法 - 简书

stm32F103

可编程flash区,以页为单位,每页1K,共128页, 擦写次数>1万次;

写入以16位“半字”为最小单位,擦除以页为单位;

先解锁,清标志,擦除,写,上锁; 

进行flash操作时,必须打开内部HSI;

stm32G030

                                          用时   \/

64-bit        program         85~125us;

32 Double word program        X ms

page(2k)      program              X ms

bank(64k)      program            X s

page(2k)      erase                 40ms

Mass          erase                   X ms

擦写次数  仅>= 1K次!!!  需考虑坏页情况;

写数据时,一般建议关闭所有中断!

stm32g030 双字写时,不仅要求是双字形式, 而且要求8字节对齐。 否则进入硬件错误!

测试部分代码:

//从指定地址开始写入指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:写入数据长度
void STMFLASH_Write_64(u32 WriteAddr,u8*pBuffer,u16 NumToWrite)	
{
	u16 i;
	u64 data_write;
	u16 len =NumToWrite;   
	u8	len_flag=0; 	
	if(NumToWrite>FLASH_PAGE_SIZE)return;
	if( (WriteAddr<FLASH_BASE) ||(WriteAddr>=(FLASH_BASE+FLASH_PAGE_SIZE*FLASH_PAGE_NB)))return;//非法地址
	HAL_FLASH_Unlock();											//解锁	
	len_flag=len%8;
	
	len=len+get_rem_data(len_flag);								//数据长度8字节对齐判断
	
	if(WriteAddr%FLASH_PAGE_SIZE==0)							//写满了从一页开始地址写需要擦除
	{			
		FLASH_EraseInitTypeDef My_Flash={0}; 					//声明 FLASH_EraseInitTypeDef 结构体为 My_Flash
		My_Flash.TypeErase = FLASH_TYPEERASE_PAGES; 			//标明Flash执行页面只做擦除操作
		My_Flash.Page  	=	(WriteAddr - FLASH_BASE) / FLASH_PAGE_SIZE;
        My_Flash.NbPages = 1;                        			//说明要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最大页数-初始页的值)之间的值
            
        uint32_t 	PageError = 0;                    			//设置PageError,如果出现错误这个变量会被设置为出错的FLASH地址
        HAL_FLASHEx_Erase(&My_Flash, &PageError);  				//调用擦除函数擦除	
	}		
	for(i=0;i<len/8;i++)//复制									//8字节数据对齐组包
	{
		u32 data_1=0;
		u64 data_2=0;
		data_1=(pBuffer[8*i+0])|(pBuffer[8*i+1]<<8)|(pBuffer[8*i+2]<<16)|(pBuffer[8*i+3]<<24); 		//
		data_2=(pBuffer[8*i+4])|(pBuffer[8*i+5]<<8)|(pBuffer[8*i+6]<<16)|(pBuffer[8*i+7]<<24); 		
		data_write= data_1| (data_2<<32);	
		if(	HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,WriteAddr,data_write) 	 == HAL_OK)
			WriteAddr+=8;//地址增加2.		
	} 		
	HAL_FLASH_Lock();												//上锁
}

u8 get_rem_data(u8 data)			//长度判断
{
	u8 re_data=0;
	switch (data)
	{
		case 0: re_data=0; break;
		case 1: re_data=7; break;
		case 2: re_data=6; break;
		case 3: re_data=5; break;
		case 4: re_data=4; break;
		case 5: re_data=3; break;
		case 6: re_data=2; break;
		case 7: re_data=1; break;
	}
	return re_data;
}

void stm32_FLASH_ErasePage(u32 WriteAddr)		//擦除
{
	if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+FLASH_PAGE_SIZE*FLASH_PAGE_NB)))return;//非法地址
	HAL_FLASH_Unlock();						//解锁
	if(WriteAddr%FLASH_PAGE_SIZE==0)	
	{
//		FLASH_PageErase(WriteAddr);//擦除这个扇区	
		FLASH_EraseInitTypeDef My_Flash={0}; 			//声明 FLASH_EraseInitTypeDef 结构体为 My_Flash
		My_Flash.TypeErase = FLASH_TYPEERASE_PAGES; 	//标明Flash执行页面只做擦除操作
		My_Flash.Page  	=	(WriteAddr - FLASH_BASE) / FLASH_PAGE_SIZE;
        My_Flash.NbPages = 1;                        	//说明要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最大页数-初始页的值)之间的值
            
        uint32_t 	PageError = 0;                    	//设置PageError,如果出现错误这个变量会被设置为出错的FLASH地址
        HAL_FLASHEx_Erase(&My_Flash, &PageError);  		//调用擦除函数擦除	
	}			
	HAL_FLASH_Lock();//上锁
}

u8 STMFLASH_ReadByte(u32 faddr)
{
	return *(__IO uint8_t*) (faddr);
	
//	return *(u8*) faddr; 
}

//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
void STMFLASH_Read_Byte(u32 ReadAddr,u8 *pBuffer,u16 NumToRead)   	
{
	u16 i;
	for(i=0;i<NumToRead;i++)
	{
		pBuffer[i]=STMFLASH_ReadByte(ReadAddr);//读1个字节.
		ReadAddr+=1;//偏移1个字节.	
	}
}
#define	FLASH_SAVE_ADDR_MAX_31		0X0800f800	
u8 data_flash[64];
static u16 count_delay=0;
u8 flag_v_a=0;
int main(void)
{
	HAL_Init();
	SystemClock_Config();
//	led_gpio_config();
//	d_out_gpio_config();
//	d_in_gpio_config();
//	rs485_en_gpio_config();	
	UART1_init(115200);
	UART2_init(115200);		
	printf("******************sys begain **************\r\n");
	
	data_flash[0]=0x55;
	fauil_delay_work=30;
	IWDG_Init(4,625*6);				// 频率:32K/64/1   Tout=  ((prer分频)* rlr /32)  7
	while (1)
	{	
		printf("\r\n\r\nwrite falsh data \r\n");
		for(u8 i=0;i<sizeof(data_flash);i++)
		{
			if(i==0)	data_flash[0]=0x55;
			else		data_flash[i]=i+data_coun;					
			printf("%02x ",data_flash[i] );
		}
		data_coun++;
		HAL_Delay(1000);
		stm32_save_flash(FLASH_SAVE_ADDR_MAX_31,data_flash,sizeof(data_flash));
		IWDG_Feed();
		
		HAL_Delay(1000);
		if(stm32_read_flash(FLASH_SAVE_ADDR_MAX_31,data_flash,sizeof(data_flash)))	
		{
			printf("\r\n\r\nread falsh data \r\n");
			for(u8 i=0;i<sizeof(data_flash);i++)
			{
				printf("%02x ",data_flash[i] );
			}
		
		}
		
	}
}

运行效果:测试代码单次写入数据长度使用的是64字节

完整demo下载路径:STM32G030C8T6读写flash-单片机文档类资源-CSDN下载

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
STM32G030C8T6是一款高性能的ARM Cortex-M0+微控制器。为了实现对其Flash读写操作,我们可以按照以下步骤进行操作: 1. 首先,我们需要在程序中引入相关的头文件,以便使用相关的库函数。例如,可以引入"stm32g0xx_hal.h"头文件,其中包含了对STM32G0系列微控制器的HAL库函数定义。 2. 然后,我们需要进行Flash的解锁操作。由于对Flash读写操作需要进入特权模式,所以需要使用相关的函数进行解锁。可以使用"HAL_FLASH_Unlock()"函数进行解锁操作。 3. 接下来,我们可以使用"HAL_FLASH_Program()"函数进行Flash的写入操作。该函数需要传入一个Flash地址以及要写入的数据。例如,可以将数据写入到Flash的某个页中。 4. 如果需要读取Flash中的数据,可以使用"HAL_FLASH_Program()"函数进行读取。该函数需要传入一个Flash地址以及一个指向接收数据的指针。例如,可以读取Flash某个地址中的数据。 5. 写入或读取操作完成后,我们需要对Flash进行锁定操作,以保护Flash的数据不被误操作。可以使用"HAL_FLASH_Lock()"函数进行锁定操作。 需要注意的是,进行Flash操作时需要小心,避免不当的操作导致数据丢失或Flash损坏。同时,由于Flash有限的写入次数,应尽量避免频繁的写入操作,以延长Flash的使用寿命。 以上是使用STM32G030C8T6进行Flash读写操作的基本步骤,可以根据具体的需求进行适当的调整和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44071950

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值