stm32片上flash存储数据以及读取数据

片上flash在一些低成本产品上使用居多,不过唯一要注意的的是,在存储瞬间,芯片不能掉电,否则单片机就会崩溃,需要重新格式化芯片,再次进行重刷代码。当然该问题不仅是单片机flash上面有,小可不才,在w25qxxflash以及AT45DBXX芯片上都出现过该问题,只是外部flash只是读取不到数据,解决方式还是格式化flash。

本次使用的芯片是stmxxxxxCBT6,工程是stm32cubemx生成的工程。.c代码如下:

#include "flash.h"
#define FLASH_FLAG_ALL_ERRORS           (FLASH_FLAG_OPERR   | FLASH_FLAG_PROGERR | FLASH_FLAG_WRPERR | \
                                         FLASH_FLAG_PGAERR  | FLASH_FLAG_SIZERR  | FLASH_FLAG_PGSERR | \
                                         FLASH_FLAG_MISERR  | FLASH_FLAG_FASTERR | \
                                         FLASH_FLAG_OPTVERR | FLASH_FLAG_ECCC    | FLASH_FLAG_ECCD)

uint16_t t; 	 
u64 WriteData;

		
//ADD:0-200  存储200个系统关键数据
static u8	Flash_ReadBuffer[32];
static u8	Flash_WriteBuffer[32];
u16 SumFan;//校验和


//读取FLASH内内容到数组
void Flash_Read(uint32_t Addr,uint8_t *Buffer,uint16_t Length)  
{  
    uint8_t *wAddr;
    wAddr=(uint8_t *)(Addr);  
    while(Length--)
		{  
       *Buffer++=*wAddr++;  
    }     
}
		
//写入4个字节的数据到FLASH
HAL_StatusTypeDef flash_write_4Byte(uint32_t address, uint64_t data)
{
    HAL_StatusTypeDef ret = HAL_OK;
    HAL_FLASH_Unlock();
    ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address , data);
    HAL_FLASH_Lock();
    return ret;
}

//写数组到FLASH
//数组必须为4个倍数
void flash_write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)  
{  
    //uint16_t t; 	
    HAL_FLASH_Unlock();  
  //  u64 WriteData;	
    for(t = 0;t < (NumToWrite/8);t++)  
    {  
			WriteData = 0;
			for(int8_t i = 7; i >= 0; i--)
			{
				WriteData <<= 8;
				WriteData |= pBuffer[t*8+i];
			}
			//	WriteData = *(__IO uint64_t *)(&WriteData);//4byte  0x1FFF7590UL
			//WriteData = 0x123445789abcedf;
			// + (uint64_t)pBuffer[t*8+7]<<56)   ) ;
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,WriteAddr + t*8,WriteData);  
    }  
    HAL_FLASH_Lock(); 	 
}  

///**
//  * @brief  Gets the page of a given address
//  * @param  Addr: Address of the FLASH Memory
//  * @retval The page of a given address
//  */
//static uint32_t GetPage(uint32_t Addr)
//{
//  return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;;
//}



void flash_page_erase(uint32_t page)
{
	 if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY) != 0x00U)
    {
        *(uint32_t *)(Flash_Page63_StartAddr+240) = 12323;//flash随意写入一个值,使flash触发错误
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS) ;
    }

    HAL_StatusTypeDef test = HAL_FLASH_Unlock();

    test = FLASH_WaitForLastOperation(1000); //1s timeout
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
    FLASH_PageErase(FLASH_BANK_1,page);
    test = FLASH_WaitForLastOperation(1000);
    CLEAR_BIT(FLASH->CR, FLASH_CR_PER);

    HAL_FLASH_Lock();
}


//写参数
void Writedatatoeeprom(void)
{
		 u8 i,j,error;
     u16  Keepdata[11];                                     

	
			Keepdata[0] = xxxxxxxxxx; //  在开辟的空间存数据 先定义11个u16数组
			Keepdata[1] = 2;          //  依次在这里存入1 、2、3....11,最大到31
			Keepdata[2]  =3;                     
			                     
			Keepdata[3] = 4;           
			Keepdata[5] = 6;            
			Keepdata[6] =7;            
			
			Keepdata[7] = 8;                   
           
			Keepdata[8] =9;
			Keepdata[9] =10;		
	        Keepdata[10] =11;
			
			//发送数据缓冲区清零
			for(i=0; i<32; i++)
			{
				 Flash_WriteBuffer[i] =0; 
			}
			//分解数据,因为数据存储类型是u8,所以需要将u16数组转化为u8,高八位低八位依次存储
			for(i=0; i<11; i++)
			{
				Flash_WriteBuffer[i*2+0] =(u8)(Keepdata[i]/256); 
				Flash_WriteBuffer[i*2+1] =(u8)(Keepdata[i]%256); 
			}
			//计算校验和
			SumFan = 0;
			for(i=0; i<30; i++)
			{
				 SumFan = SumFan + Flash_WriteBuffer[i]; 
			}
			SumFan = 65535 - SumFan;
			Flash_WriteBuffer[30] =(u8)(SumFan/256); 
			Flash_WriteBuffer[31] =(u8)(SumFan%256);
			
	
	//存3次数据
	for(i=0; i<3; i++)
	{
		 error = 0;
     flash_page_erase(63);
	   flash_write(Flash_Page63_StartAddr,Flash_WriteBuffer,32);
		 Flash_Read(Flash_Page63_StartAddr,Flash_ReadBuffer,32);
		 for(j=0; j<32; j++)
		 {
			 if(Flash_WriteBuffer[i] != Flash_ReadBuffer[i]) error =  error + 1;
		 }
		 if(error==0)break;
	}
	//说明写入失败
	if(i>=3)
	{
     i=0;
	}
}



//读参数
void Readdatatoeeprom(void)
{
	u8 i;
	//u16 Restdata[200];
	//读取数据
	Flash_Read(Flash_Page63_StartAddr,Flash_ReadBuffer,32);
	//计算校验和
	SumFan = 0;
	for(i=0; i<30; i++)
	{
		 SumFan = SumFan + Flash_ReadBuffer[i]; 
	}
	SumFan = 65535 - SumFan;
	//判断校验和是否正确
	if((Flash_ReadBuffer[30] == (u8)(SumFan/256))&&(Flash_ReadBuffer[31] == (u8)(SumFan%256)))
	{
   		 xxxxxxxxxxxxx = Flash_ReadBuffer[0]*256 + Ex_Flash_ReadBuffer[1];
         //这里为读取到的数组,读取到的数组为u8,依次转化为刚存入的
	}
	//校验和错误,给出默认数据并写入
	else
	{
       xxxxxxx= 0;  
     Writedatatoeeprom();
	}
}

上述代码为片上内存存储和读取源代码。c文件。与之对应的还有H文件。h文件代码如下:

#ifndef __FLASH_H
#define __FLASH_H

#include "core_cm0plus.h"

//总共128K
//FLASH_BANK_1: 前64K
//FLASH_BANK_2: 后64K
	
#define Flash_Page60_StartAddr  0x0801e000
#define Flash_Page61_StartAddr  0x0801e800
#define Flash_Page62_StartAddr  0x0801f000
#define Flash_Page63_StartAddr  0x0801f800

extern void Readdatatoeeprom(void);
extern void Writedatatoeeprom(void);
#endif

依据.h文件,不难看出,使用片上存储空间存储数据时,不需要进行硬件资源上的初始化,也没有软件上的外设资源初始化。只需要直接调用写,和读两个指令。

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值