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

📄 flash.c

📁 税控收款机源码:拼音输入法,LCD,VFD驱动,IC卡驱动,税控国标
💻 C
字号:
#include  "include.h"

uint  data flash_r_addr;
uint  data flash_w_addr;
uchar data flash_r_data;
uchar data flash_w_data;
bit A15;
sbit   A20=P3^5;
sbit   AB15=P4^3;
//注意:对于XBYTE[]的操作的偏移地址是仿真器的需要,实际CUP不需要
//	检查指定扇区是否空,扇区空返回0
//=======================================================================
//===========SRAM读写驱动====================================//
/*************************************************************
*函数名称: select_sector(uchar sector)
*输入参数: uchar sector --- 24位地址线的高8位
*输出参数: void
*函数功能: 根据输入地址线的数据对相应地址线置位,本函数对
*           SRAM、FLASH的地址操作有效
*************************************************************/
void select_sector(uchar sector)
{
	uchar x;
	
	if(sector >15)
	{
		if(sector>31)		//置位 A21
			SetupPortA(A21,1);
		else
			SetupPortA(A21,0);
		A20=1;				//置位 A20
	}
	else
	{
		SetupPortA(A21,0);
		A20=0;
	}
	x=sector&0x0f;			//x 低四位对应 a16 a17 a18 a19

	P4&=0x07;				//保留P4的低三位
	x<<=4;
	x&=0xf0;
	P4|=x;
	if(A15)P4|=0x08;
}


/*************************************************************
*函数名称: read_sramb(ulong addr,uint leng,void *buf)
*输入参数: ulong addr --- 24位地址
*           uint leng  --- 读数据的长度
*           void *buf  --- 指针,把读出的数据存放在此空间
*返回值  : uchar  1   --- 读SRAM失败(地址有误)
                   0   --- 读SRAM成功
*函数功能: 读出leng长度的,以addr为首地址的,存放在SRAM的数据,
*           并存放在 *buf 指向的空间
*************************************************************/
uchar read_sramb(ulong addr,uint leng,void *buf)
{
	uchar  sector;                  			
	uint  rd_addr;//addr0;
	uchar EAStatus;

	sector=*((uchar *)(&addr)+1);    // 取页面地址 

	rd_addr=(uint)addr;					// 取地址指针 
 
	if(sector >8)    return(1); 
	if((addr + leng -1) > 0x80000) return(1);
	
	EAStatus = EA;
	EA = 0;
	
	if(rd_addr & 0x8000)  A15 = 1;
	else A15 = 0;
	rd_addr = rd_addr & 0x7fff;

	select_sector(sector); 
	flash_r_addr =  rd_addr;

	do
	{
		if(flash_r_addr & 0x8000)
		{
			flash_r_addr=0;
			A15=~A15;
			if(!A15) sector++;
			select_sector(sector); 
		}
		PSD8xx_reg.PAGE&=0x7f;
		flash_r_data = XBYTE[flash_r_addr];
		_nop_ ( );
		_nop_ ( );

		*((uchar*)buf) = flash_r_data;
		((uchar*)buf)++;
		flash_r_addr++;

	}while(--leng);
	PSD8xx_reg.PAGE|=0x80;
	
	EA = EAStatus;
	return(0);
}
/*************************************************************
*函数名称: write_sramb(ulong addr,uint leng,void *buf)
*输入参数: ulong addr --- 24位地址
*           uint leng  --- 读数据的长度
*           void *buf  --- 指针,要写入的数据存放在此空间
*返回值  : uchar    0   --- 写SRAM成功
*                    1   --- 写SRAM失败(地址有误)
*                    2   --- 写SRAM失败(校验有误)
*函数功能: 把存放在指向 *buf 的空间的、leng长度的数据,
*           写入以addr为首地址的SRAM中
*************************************************************/
uchar write_sramb(ulong addr,uint leng,void *buf)
{
	uchar  sector;
	uint  rd_addr;
	uchar EAStatus;
	sector=*((uchar *)(&addr)+1);	// 取页面地址 

	rd_addr=(uint)addr;				// 取地址指针 
	//send_char(sector);
	if(sector >7)                  return(1);
	if((addr + leng -1) > 0x80000) return(1);
	
	EAStatus = EA;
	EA = 0;
	if(rd_addr & 0x8000)  A15 = 1;
	else A15 = 0;
	rd_addr = rd_addr & 0x7fff;

	select_sector(sector); 
	
	flash_r_addr =  rd_addr;
	do
	{
		if(flash_r_addr & 0x8000)
		{
			flash_r_addr=0;
			A15=~A15;
			if(!A15) sector++;
			select_sector(sector); 
		}
		PSD8xx_reg.PAGE&=0x7f;
		XBYTE[flash_r_addr]=*((uchar*)buf);
		delayms(1) ;
		PSD8xx_reg.PAGE&=0x7f;
		flash_r_data = XBYTE[flash_r_addr];
		if(flash_r_data != *((uchar*)buf)) {PSD8xx_reg.PAGE&=0x7f; return(2); }// Write_FAU_data(6,WRITE_SRAM_FAIL);
	
		((uchar*)buf)++;
		flash_r_addr++;
    
	}while(--leng);
	PSD8xx_reg.PAGE|=0x80;

	EA = EAStatus;
	return(0);
}


//===================FLASH驱动程序===================================//
//        本部分为HY29LV320驱动
//        此芯片为4M BYTE 并行 FLASH

uchar sector_blank_check(ulong _sector_addr)
{
	uchar sector;
	uint  addr;
	uchar EAStatus;

	sector=*((uchar *)(&_sector_addr)+1);       // 取页面地址 
	addr=(uint)_sector_addr;					// 取地址指针 

	EAStatus = EA;
	EA = 0;	
	if(addr & 0x8000)  A15 = 1;
	else A15 = 0;

	addr = addr & 0x7fff;

	if(_sector_addr<0x010000)	//第 0---7 个扇区,每扇区8K BYTE
	{
		select_sector(sector);
		addr = addr&0xe000;
		for(flash_r_addr=0;flash_r_addr<0x2000;flash_r_addr++)
		{
			_nop_ ( );
			PSD8xx_reg.PAGE|=0x80;
			flash_r_data = XBYTE[flash_r_addr+addr];
			PSD8xx_reg.PAGE&=0x7f;
			_nop_ ( );
			_nop_ ( );
			if(flash_r_data!=0xff)
			{
				EA = EAStatus;
				return (1);
			}
		}
	}
	else						//其他扇区,每扇区64K BYTE
	{
		A15=0;
		do
		{
			select_sector(sector);

			for(flash_r_addr=0;flash_r_addr<0x8000;flash_r_addr++)
			{
				_nop_ ( );
				PSD8xx_reg.PAGE|=0x80;
	            flash_r_data = XBYTE[flash_r_addr];
				PSD8xx_reg.PAGE&=0x7f;
	            _nop_ ( );
	            _nop_ ( );

				if(flash_r_data!=0xff)
				{
					EA = EAStatus;
					return (1);
				}
			}
			A15=~A15;
		}while(A15);
	}
	
	EA = EAStatus;
	return(0);
}

/************************************************************************/
/* PROCEDURE:   Erase_One_Block                                         */
/*                                                                      */
/* This procedure can be used to erase a total of 64K words.            */
/*                                                                      */
/* Input:                                                               */
/*      Dst     DESTINATION address where the erase operation starts    */
/*                                                                      */
/* Output:                                                              */
/*      NONE                                                            */
/************************************************************************/

uchar flash_sector_erase(uchar erase_sector_num)
{
	
	ulong erase_addr;
	uchar  sector;
	uint  addr;
	uchar EAStatus;
	
	if(erase_sector_num<23) //字库及预留区,不允许操作,前28个扇区
		return(1);
	
	erase_addr = 0x100000 + (ulong)(erase_sector_num - 23)*0x10000;
	
	sector=*((uchar *)(&erase_addr)+1);       // 取页面地址 
	addr=(uint)erase_addr;					// 取地址指针 

	EAStatus = EA;
	EA = 0;
	
	if(addr & 0x8000)  A15 = 1;
	else A15 = 0;

	addr = addr&0x7fff;

	select_sector(sector);

	_nop_ ( );
	_nop_ ( );

	PSD8xx_reg.PAGE|=0x80;

	XBYTE[0xaaa] = 0xaa;

	XBYTE[0x555] = 0x55;

	XBYTE[0xaaa] = 0x80;

	XBYTE[0xaaa] = 0xaa;

	XBYTE[0x555] = 0x55;

	XBYTE[addr] = 0x30;
  
	PSD8xx_reg.PAGE&=0x7f;

	delay_ms(50) ;

	if( sector_blank_check(erase_addr) ){ return (1);}//Write_FAU_data(6,ERASE_FLASH_FAIL);
	
	EA = EAStatus;
	return(0);
}

/************************************************************************/
/* PROCEDURE:   Erase_Entire_Chip                                       */
/*                                                                      */
/* This procedure can be used to erase the entire chip.                 */
/*                                                                      */
/* Input:                                                               */
/*      NONE                                                            */
/*                                                                      */
/* Output:                                                              */
/*      NONE                                                            */
/************************************************************************/

/*uchar flash_chip_erase(void)
{
	uchar i;
	reset_addr();
	_nop_ ( );
	_nop_ ( );
	P4_1 = 0;
	PSD8xx_reg.PAGE|=0x80;
	XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0xaa;
	XBYTE[0x555+PSD_REG_ADDR+0x100] = 0x55;
	XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0x80;
	XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0xaa;
	XBYTE[0x555+PSD_REG_ADDR+0x100] = 0x55;
	XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0x10;
	P4_1 = 1;
	PSD8xx_reg.PAGE&=0x7f;
	_nop_ ( );
	_nop_ ( );
	for(i=0; i<10; i++)
	{
		delay_ms(4) ;
	}              

	//if( check_toggle_bit(0x8000) ) return (1);

	for(i=0x00;i<0x20;i++)
	if( sector_blank_check(i) ) return (1);

	return(0);
}

*/

//================================================================================
uchar write_flash_abyte(uint addr,uchar abyte)
{
	uchar k,i,j,cnt;

	k=2;
	while(k)    //不成功写几遍
	{
		flash_w_data = abyte;
		flash_w_addr = addr;
  
		PSD8xx_reg.PAGE|=0x80;
  		XBYTE[0xaaa] = 0xaa;
		XBYTE[0x555] = 0x55;
		XBYTE[0xaaa] = 0xa0;
		XBYTE[flash_w_addr] =flash_w_data;
		PSD8xx_reg.PAGE&=0x7f;
//=============================================
		PSD8xx_reg.PAGE|=0x80;
		cnt = 50;
		while(cnt)
		{
			cnt--;
			i = XBYTE[flash_w_addr];
			j = XBYTE[flash_w_addr];
			
			if((i&0x40) != (j&0x40))		//D6 == D6
				continue;
				
			i = XBYTE[flash_w_addr];
			if((i&0x80)==(flash_w_data&0x80))
				break;					//D7 == D7
		}
		PSD8xx_reg.PAGE&=0x7f;
//=============================================
		PSD8xx_reg.PAGE|=0x80;
		flash_r_data =XBYTE[flash_w_addr];
		PSD8xx_reg.PAGE&=0x7f;

		if(flash_r_data == flash_w_data){  return (0);}// check_write_flash
		else {k--;}
	}
	return (1);
}

//========================================================================

//将SRAM中leng长度的数据写到FLASH指定单元,写入正确返回0,否则返回1
//注意:如果被写的地址的数据不是0XFF可能会造成FLASH一直忙,会造成读出错
uchar write_flash(ulong wr_addr,uint wr_length,void *wr_buf)
{
	uchar  sector;
	uint  addr;
	uchar EAStatus;

	sector=*((uchar *)(&wr_addr)+1);       // 取页面地址 
	addr=(uint)wr_addr;					// 取地址指针 
  
//	if((sector >34)||(sector<4))    return(1);//0-3 为字库需要保护4-7 为安全审计记录
//	if((wr_addr + wr_length - 1) > 0x1fffff) return(1);

	if(wr_addr<0x100000)			//字库及预留区,不允许操作,前23个扇区
		return(1);
		
	EAStatus = EA;
	EA = 0;
	if(addr & 0x8000)  A15 = 1;
	else A15 = 0;
	//write_data_flg=1;   //掉电时给出的标志 掉电有用   	
	addr = addr & 0x7fff;

	select_sector(sector);

	do
	{
		if(addr&0x8000)
		{
			addr=0X00;
			A15=~A15;
			if(!A15) sector++;
			select_sector(sector);
		}
		if( write_flash_abyte(addr,*((uchar*)wr_buf)))
		{
			EA = EAStatus;
			return (2);
		}
		else
		{
			if(low_pwr==1) {shut_bat(0);}//low_pwr=2;
			((uchar*)wr_buf)++;
			addr++;
		}
	}while(--wr_length);
	
	EA = EAStatus;
	return(0);
}
//==========================================================================
//	将FLASH中leng长度的数据写到SRAM指定单元,写入正确返回0,否则返回1

uchar read_flash(ulong rd_addr, uint rd_length, void *rd_buf)
{
	uchar  sector;
	uint  addr;
	uchar EAStatus;
	
	sector=*((uchar *)(&rd_addr)+1);    // 取页面地址
 
	addr=(uint)rd_addr;					// 取地址指针 

//	if(sector > 34)
//		return(1);
		
	if((rd_addr + rd_length -1) > 0x3fffff)
		return(1);
		
	EAStatus = EA;
	EA = 0;
	
	if(addr & 0x8000)
		A15 = 1;
	else
		A15 = 0;
	addr = addr & 0x7fff;
 
	select_sector(sector); 
	flash_r_addr =  addr;
	

	do
	{
		if(flash_r_addr & 0x8000)
		{
			flash_r_addr=0;
			A15=~A15;
			if(!A15) sector++;
			select_sector(sector); 
		}
		
		_nop_ ( );
		_nop_ ( );
		_nop_ ( );

		PSD8xx_reg.PAGE|=0x80;
 
		flash_r_data = XBYTE[flash_r_addr];

		PSD8xx_reg.PAGE&=0x7f;
		_nop_ ( );  _nop_ ( );

		*((uchar*)rd_buf) =flash_r_data;

		((uchar*)rd_buf)++;
		flash_r_addr++;
  
	}while(--rd_length);
	
	EA = EAStatus;
	return(0);
}

⌨️ 快捷键说明

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