stm32 利用Flash进行储存数据

由于Flash具有擦写速度快,读取方便,掉电不丢失等优点,在工程项目中,常常开辟一块儿数据来存放各个传感器的数据!


在stm32中,无需对于flash进行特别的初始化,但是还是先要去掉写保护,在写这个程序遇到的最大问题是无法进行debug,因为根本就看不到数据,最后只能使用串口发送数据来进行调试抓狂 


需要注意的是

stm32只能一字(u32)或者半字(u16)输入,且利用flash写入时,其实地址必须为偶数,为奇数无法继续执行

擦除只能是全擦除或者单页擦除

用的是stm32F103VE,下面是调试过的代码

bsp_storge.h

#ifndef _BSP_STORAGE_H
#define _BSP_STORAGE_H
 					
#include "stm32f10x_flash.h"
#include"stdint.h"
#include "bsp_usart.h"

#define Sector_DataSize    256


uint32_t  MonthData_TempAddr=(uint32_t)0x0807f700;			  // 地址计数指针

uint32_t  MonthDataStaAddr=(uint32_t)0x08032000;			//当前月扇区起始地址

uint32_t  MonthDataEndAddr=(uint32_t)0x0807f800;			// 当前月扇区终止地址




static FLASH_Status PutDataIntoFlash(uint32_t Address1,uint8_t *buf,uint32_t len);

void ReadFromFlash(uint32_t Addr,uint8_t *buf,uint32_t len);

FLASH_Status  WriteToFlash(uint32_t TempAddr,uint8_t *RomData,uint32_t len,uint32_t DataStaAddr,uint32_t DataEndAddr);


void flashtext(void) ;

#endif /*_BSP_STORAGE_H   */


bsp_storage.c

#include "bsp_storage.h"

#define PageSize  2048

//#define MonthDataStaAddr   ((uint32_t)0x08032000)	  //sector:100
//#define MonthDataEndAddr   ((uint32_t)0x08039FFF)	  //sector:115 end


//#define LastMonthDataStaAddr  	 ((uint32_t)0x0803A000)		//sector:116
//#define LastMonthDataEndAddr	 ((uint32_t)0x08041FFF)		//sector:131	end
//
//#define BeforeLastMonthDataStaAddr	((uint32_t)0x08042000)	 //sector:132
//#define BeforeLastMonthDataStaAddr	((uint32_t)0x0804AFFF)	 //sector:149	end


/***************************************************************************************************
*\Function      PutDataIntoFlash(uint32_t Address1,uint8_t *buf,uint8_t len)
*\Description   将数据放入到flash中
*\Parameter     uint32_t Address1
*\Parameter     uint8_t *buf
*\Parameter		uint8_t len
*\Return        void
*\Note          2014年7月19日  地址只能是偶数
*\Log          	PutDataIntoFlash(0x0807F800,aaa,5);
*              
***************************************************************************************************/
static FLASH_Status PutDataIntoFlash(uint32_t Address1,uint8_t *buf,uint32_t len)
{
	uint32_t i;
	uint16_t TempData16;// 十六位临时数据变量
	FLASH_Status status = FLASH_COMPLETE;
	if(len%2==0)     // 数据长度奇偶判断
	{
		for(i=0;i<len;)					  
		{		  	    

			TempData16=(uint16_t)buf[i];	 // 数据进行高低位置调换,人为的将大端模式转换为小端模式,便于数据的读取
			TempData16= TempData16|0xFF00;
			TempData16= ((((uint16_t)buf[i+1])<<8)|0x00FF)&TempData16; 

			if(status == FLASH_COMPLETE)
			{			 
				status=FLASH_ProgramHalfWord(Address1,TempData16);
				Address1+=2;		 		 
			}
			else 
			{	  		 	 
				break;  		 
			}	
			i=i+2;		
		}  	
	}
	else
	{			
		for(i=0;i<len;)					  
		{
			TempData16=(uint16_t)buf[i];	 // 数据进行高低位置调换,人为的将大端模式转换为小端模式,便于数据的读取


			TempData16&=buf[i];		   // 数据进行高低位置调换,人为的将大端模式转换为小端模式,便于数据的读取
			if(i+2<len)				   // 数据长度为奇数的时候,将最后一位数据置为(00) 
			{
				TempData16= TempData16|0xFF00;
				TempData16= ((((uint16_t)buf[i+1])<<8)|0x00FF)&TempData16;			

			}
			else
				TempData16&=0x00FF;				  

			if(status == FLASH_COMPLETE)
			{			 
				status=FLASH_ProgramHalfWord(Address1,TempData16);
				Address1+=2;		 		 
			}
			else 
			{	  		 	 
				break;  		 
			}	
			i=i+2;		
		}  	
	}
	return 	status;	
}				
/***************************************************************************************************
*\Function      ReadFromFlash(uint32_t Addr,uint8_t *buf,uint32_t len)
*\Description   读flash中特定位置的值
*\Parameter     uint32_t Addr
*\Parameter     uint8_t *buf
*\Parameter     uint32_t len
*\Return        void
*\Note         	2014年7月19日
*\Log          	ReadFromFlash(0x0807F800,buf,5);     
***************************************************************************************************/
void ReadFromFlash(uint32_t Addr,uint8_t *buf,uint32_t len)
{ 

	uint32_t address=Addr;		   	   
	while(len--)
	{
		*buf=*(uint32_t*)address;
		buf++;
		address++;				  		
	}
	return;
}

/***************************************************************************************************
*\Function      FLASH_Status  WriteToFlash(uint32_t TempAddr,uint8_t *RomData,uint32_t len,uint32_t DataStaAddr,uint32_t DataEndAddr)
*\Description   将数据写入到Flash中	 
*\Parameter     uint32_t Addr	   实际存入起始地址   全局变量写入
*\Parameter     uint8_t *RomData   需要写入的数据
*\Parameter     uint32_t len	   数据长度
*\Parameter     uint32_t DataStaAddr	   扇区总数据起始地址
*\Parameter     uint32_t DataEndAddr	   扇区总数据结束地址
*\Return        FLASH_Status 
*\Note         	起始地址必须为偶数,且必须为256的倍数	2014年7月20日
*\Log          	WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);      
***************************************************************************************************/
FLASH_Status  WriteToFlash(uint32_t TempAddr,uint8_t *RomData,uint32_t len,uint32_t DataStaAddr,uint32_t DataEndAddr)
{
	/*///////////////////////////////////////////////////
	数据长度 256字节			  一页共8组数据


	 第一组数据            起始:0   终止 :255		
	 第二组数据      	 	起始:256 终止 :511			
	 第三组数据      		起始:512 终止 :767			
	 第四组数据      		起始:768 终止 :1023	

	 .......                  ..........
	 .......                  ..........

	 第八组数据			起始:1792  终止 :2047

	 每组数据中:
	 起始20字节 : 标志使用码,当前储存数据组,
	 终止20字节 :
	 /////////////////////////////////////////////////
	 */												 
	FLASH_Status  status;
	uint32_t staAddr;	    // 将要写入的扇区起始地址		 
	uint32_t count;        // 对于扇区内的分组进行计数
	uint8_t  buf1[PageSize]={0};  
	uint32_t i,j;			 
	FLASH_Unlock();
	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);


	staAddr=TempAddr-(TempAddr%PageSize);	 

	count=(TempAddr%PageSize)/Sector_DataSize;		

	/* 读出*/
	ReadFromFlash(staAddr,buf1,PageSize);						   // 从flash中读出当前页的值
	/*更改数据*/
	for(i=count*Sector_DataSize,j=0;i<count*Sector_DataSize+Sector_DataSize;i++,j++)
	{						  		
		buf1[i]=RomData[j];	  			
	}

	/* 擦除整页 */

	status=FLASH_ErasePage(staAddr);


	/* 写回 */
	status=PutDataIntoFlash(staAddr,buf1,PageSize);

	MonthData_TempAddr=TempAddr+Sector_DataSize;						  //  为下一次写入更新地址
	if(MonthData_TempAddr>=DataEndAddr)		// DataEndAddr,DataStaAddr即使开始的时候定为全局变量,但仍旧无法传值,估计是因为写flash的原因,对于地址的传入还是用参数传入
	{
		MonthData_TempAddr=DataStaAddr;		 
	}

	 FLASH_Lock();
	return  status;		
}


/***************************************************************************************************
*\Function      flashtext(void)
*\Description   flash测试函数
*\Return        void
*\Note         	2014年7月21日
*\Log               
***************************************************************************************************/
void flashtext(void)
{

//	uint32_t temp3;
//	uint32_t Addr;	
//	uint8_t aaa[5]={0x01,0x02,0x03,0x04,0x05};
	//	uint8_t buf[7]={0};
	uint8_t buf[256]={0x01,0x02,0x03,0x04,0x05};
	//	FlagStatus status=RESET;
	//	status=FLASH_GetReadOutProtectionStatus();
	//	Usart_Sendchar(USART2,0x12);
	//    WriteToFlash(0x08032000,buf,256);
	//	WriteToFlash(0x08032100,buf,256);
	//		WriteToFlash(0x08032200,buf,256);

	WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
	WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
	WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
	// WriteToFlash(MonthData_TempAddr,buf,256);
	//WriteToFlash(MonthData_TempAddr,buf,256);
	//FLASH_ErasePage(0x0807F800); 
	///	PutDataIntoFlash(0x0807F800,aaa,5);
	//	ReadFromFlash(0x0807F800,buf,5);
	//	NumDisplayOnLCD(buf,5);
	//  FLASH_ProgramHalfWord(0x0807F800,0x0123);
	while(1);
	//	   			   

	//	Addr=*(__IO uint16_t *) (((uint32_t)0x0807F801));
	// Usart_Sendchar(USART2,(uint8_t)Addr); 

	//Addr=(uint32_t)0x0801FC00;		
	//	temp3=*(__IO uint32_t*)Addr;
}




你可能感兴趣的:(stm32,ARM,嵌入式开发)