⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 flash 读写 flash 读写 flash 读写 flash 读写 flash 读写 flash 读写 flash 读写 flash 读写 flas
💻 C
字号:
/******************************************************************************

	 						FLASH  操作	

/******************************************************************************
名称:flash.c
功能:对FLASH进行操作
硬件:AT45DB021
作者:Albert
日期:2004-08-29
修改日期:
修改内容:
/*****************************************************************************/

#include <mega128.h> 
#include <spi.h>
#include "flash.h"
#include "type.h"


BYTE gFlashBuff[0x1000];		//FLASH缓冲区 = 2 BLOCK  = 4kB

/******************************/   
int CalculateAddrOffsetSize ( DWORD addr1 , DWORD addr2);   //计算地址偏移大小
DWORD AddrToPageAndOffset(DWORD addr,DWORD addr_offset);    //根据地址和偏移大小计算新地址    
BOOL ReadFlashStatus(void);
BOOL ReadFlashMem(BYTE *buf, WORD size, DWORD addr);		//读FLASH   
void ReadFlashPage(BYTE *pBuf,WORD size, DWORD addr);
BOOL WriteFlashMem(BYTE *buf, WORD size, DWORD addr);       //写FLASH
void WriteFlashPage(BYTE *pBuf,WORD size, DWORD addr);      //写一页
void CopyFlashPage(WORD despage,WORD srcpage);              //复制页
void CopyFlashBlock(WORD desblock,WORD srcblock);			//复制Block
void EraseFlashPage(WORD pager);
void EraseFlashBlock(BYTE block);
void EraseFlashChip(void);
void EraseSector(BYTE Sector);
void InitSpi(void);
/******************************/		  

//计算两个flash地址之间的大小
int CalculateAddrOffsetSize ( DWORD addr1 , DWORD addr2)
{
	WORD page1,page2,page;
	WORD offset1,offset2,offset;
	int size;
		
	if( addr1 == addr2 )
		return 0;
	else if( addr1 > addr2 )
	{
		page1 = (WORD)(addr1 >> 9);
		offset1 = (WORD)addr1 & 0x1ff;
		page2 = (WORD)(addr2 >> 9);
		offset2 = (WORD)addr2 & 0x1ff;

		if( offset1 >= offset2 )
		{
			page = page1 - page2;
			offset = offset1 - offset2;
			size = page*FLASH_PAGE_SIZE + offset;
		}
		else
		{
			page = page1 - page2 - 1;
			offset = ( offset1 + FLASH_PAGE_SIZE ) - offset2;
			size = page*FLASH_PAGE_SIZE + offset;
		}
	}
	return size;
}

//给出地址和地址偏移量,计算页地址和页内地址,返回新地址
DWORD AddrToPageAndOffset(DWORD addr,DWORD addr_offset)
{                                             
	WORD page;
	WORD offset;

	WORD srcpage,pagetemp;
	WORD srcoffset,offsettemp;
	WORD offsetsum;
	WORD pagerem;
	DWORD address;
	
	srcpage = (WORD)(addr >> 9);
	srcoffset = (WORD)(addr	& 0x001ff );     
	if(srcoffset > 255)
		return FALSE;
	
	pagetemp = (WORD)(addr_offset / FLASH_PAGE_SIZE);
	offsettemp = (WORD)(addr_offset % FLASH_PAGE_SIZE);
	
	offsetsum = srcoffset + offsettemp;
	pagerem = offsetsum / FLASH_PAGE_SIZE;
	if(pagerem > 1)
		return FALSE;
	offset = offsetsum % FLASH_PAGE_SIZE;
	page = srcpage + pagetemp + pagerem;
	address = (DWORD)page << 9;
	address += (DWORD)offset;
	return address;
} 


BOOL ReadFlashStatus(void)
{
	BYTE status;

	FLASH_CS_H;
	delay_ms(1);
	FLASH_CS_L;   

	spi(0xD7);	 
	status = spi(0xff);
	
	FLASH_CS_L;
	delay_ms(1);
	FLASH_CS_H;  
	
	if(status & 0x80)	
		return TRUE;
	else
		return FALSE;
}

//不连续写FLASH(主存读数据),一页一页读
void ReadFlashBuf(DWORD address)
{         
	while(ReadFlashStatus() == FALSE);

	FLASH_CS_H;
	delay_ms(1);    
	FLASH_CS_L;   
	
	spi(0x53);           
	spi((char)((address >> 16)&0x0f));
	spi((char)((address >> 8)&0xfe));                
	spi(0x00);

	FLASH_CS_L;
	delay_ms(1);
	FLASH_CS_H;  
} 

//不连续写FLASH(主存读数据),一页一页读
void ReadFlashPage(BYTE *pBuf,WORD size, DWORD addr)
{         
	WORD i;
	
	while(ReadFlashStatus() == FALSE);

	FLASH_CS_H;
	delay_ms(1);    
	FLASH_CS_L;   
	
	spi(0xD2);    

	spi((char)(addr >> 16));
	spi((char)(addr >> 8));
	spi((char)addr);                
	spi(0x00);
	spi(0x00);
	spi(0x00);
	spi(0x00);

	for(i=0;i<size;i++)
		*pBuf++ = spi(0xff);

	FLASH_CS_L;
	delay_ms(1);
	FLASH_CS_H;  
}   

BOOL ReadFlashMem(BYTE *buf, WORD size, DWORD addr)
{
	WORD i;          
	WORD pagenum = 0;
	WORD pageres = 0;                                                   
	WORD remain = 0;
	WORD pager_offset;    
	                  
	pager_offset = (WORD)(addr & 0x001ff);
	if(pager_offset > 255)	         
		return FALSE;
	              
                  
	if(size <= (FLASH_PAGE_SIZE - pager_offset))
		ReadFlashPage(buf,size,addr);
	else
	{   
		ReadFlashPage(buf,FLASH_PAGE_SIZE-pager_offset,addr);	
		remain = size - (FLASH_PAGE_SIZE - pager_offset);    
		pagenum = remain / FLASH_PAGE_SIZE; 			
		pageres = remain % FLASH_PAGE_SIZE; 			
		if((pagenum == 0)&&(pageres == 0))
			return FALSE;
		for(i=1;i<pagenum+1;i++)
		{       
			ReadFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset),FLASH_PAGE_SIZE,(addr+i*0x00200)&0xffe00);//页地址加1	 
		}
		ReadFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset), size-(FLASH_PAGE_SIZE*i-pager_offset), (addr+i*0x00200)&0xffe00);
	}
	return TRUE;
} 

//给定FLASH地址,连续写数据
BOOL WriteFlashMem(BYTE *buf, WORD size, DWORD addr)
{           
	WORD i;          
	WORD pagenum = 0;
	WORD pageres = 0;                                                   
	WORD remain = 0;
	WORD pager_offset;   
 
	pager_offset = (WORD)(addr & 0x001ff);
	if(pager_offset > 255)	         
		return FALSE;
	              
                  
	if(size <= (FLASH_PAGE_SIZE - pager_offset))
		WriteFlashPage(buf,size,addr);
	else
	{   
		WriteFlashPage(buf,FLASH_PAGE_SIZE-pager_offset,addr);	
		remain = size - (FLASH_PAGE_SIZE - pager_offset);    
		pagenum = remain / FLASH_PAGE_SIZE; 			
		pageres = remain % FLASH_PAGE_SIZE; 
		if((pagenum == 0)&&(pageres==0))
			return FALSE;		
		for(i=1;i<pagenum+1;i++)
		{       
			WriteFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset),FLASH_PAGE_SIZE,(addr+i*0x00200)&0xffe00);//页地址加1	 
		} 
		WriteFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset), size-(FLASH_PAGE_SIZE*i-pager_offset), (addr+i*0x00200)&0xffe00);
	}
	return TRUE;
}	

//不连续写FLASH(主存写数据),一页一页写
void WriteFlashPage(BYTE *pBuf,WORD size, DWORD addr)
{         
	WORD i;
	
	while(ReadFlashStatus() == FALSE); 
	
	ReadFlashBuf(addr);	//读到buff
	
	FLASH_CS_H;
	delay_ms(1);    
	FLASH_CS_L;   

	spi(0x82);    

	spi((char)(addr >> 16));
	spi((char)(addr >> 8));
	spi((char)addr);

	for(i=0;i<size;i++)
		spi(*pBuf++);                              
	                        
	FLASH_CS_L;
	delay_ms(1);
	FLASH_CS_H;    
}

//拷贝一个sector (起始页后4K字节)
void CopyFlashPage(WORD despage,WORD srcpage)
{
	DWORD addr;
	addr = (DWORD)(srcpage*2) << 12;
	ReadFlashMem(gFlashBuff,0x1000L,addr);
	addr = (DWORD)(despage*2) << 12;
	WriteFlashMem(gFlashBuff,0x1000L,addr);
} 


//拷贝BLOCK (起始页后2048个字节为1个BLOCK = 2048B)
void CopyFlashBlock(WORD desblock,WORD srcblock)
{       
	DWORD addr;
	addr = (DWORD)(srcblock << 9);                                    
	ReadFlashMem(gFlashBuff,2048,addr);
	addr = (DWORD)(desblock << 9);                                    	
	WriteFlashMem(gFlashBuff,2048,addr);
}	

//页擦除
void EraseFlashPage(WORD pager)
{    
	while(ReadFlashStatus() == FALSE);
	
	FLASH_CS_H;
	delay_ms(1);    
	FLASH_CS_L;   
	
	spi(0x81);                  
	spi((char)(pager>>7));
	spi((char)((pager<<1)&0xfe));
	spi(0x00);    
	
	FLASH_CS_L;
	delay_ms(1);
	FLASH_CS_H;  
	delay_ms(1);
}	                  
                      
//块擦除
void EraseFlashBlock(BYTE block)
{   
	while(ReadFlashStatus() == FALSE);
 
	FLASH_CS_H;
	delay_ms(1);    
	FLASH_CS_L;   
	
	spi(0x50);
	spi((char)(block>>4));
	spi((char)((block<<4)&0xf0));
	spi(0x00);   
	
	FLASH_CS_L;
	delay_ms(1);
	FLASH_CS_H;  
	delay_ms(1);
}

//芯片擦除
void EraseFlashChip(void)
{    
	BYTE i;
	for(i=0;i<128;i++)//256个BLOCK
		EraseSector(i);
}

//擦除1个扇区
void EraseSector(BYTE Sector)
{   //4KB
	EraseFlashBlock(Sector*2);
	EraseFlashBlock(Sector*2+1);  
}      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -