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

📄 ecrcard.c

📁 写IC卡的参考代码,应用于读写IC卡的数据,电表,水表开发场合适用
💻 C
📖 第 1 页 / 共 3 页
字号:
				FLASH_CARD_CLK=0;
			#endif	//HIGH
			_nop_ ( );
			_nop_ ( );
			FLASH_CARD_CS=1;
			sector++;
			if(sector>=MAXPAGE) {card_vcc(0);return 1;}    
			card_addr=0;
			array_page_read(PAGE_READ_COM,sector,card_addr);
		}
	}while(--leng);
	#ifdef	HIGH
		FLASH_CARD_CLK=1;
	#else
		FLASH_CARD_CLK=0;
	#endif
	_nop_ ( );
	_nop_ ( );
	FLASH_CARD_CS=1;
	card_vcc(0);
	return 0;
}
#endif //FLASH_PAGE

#ifdef FLASH_ARRAY	//阵列模式
/**************************************************************/
/*PAGE READ*/
uchar  read_flash_card1(ulong addr,uint leng,uchar xdata *str)
{
	uint sector,card_addr;

	initial_flash_card1();
	
	sector=(addr/0x108)&0xfff;
	if(sector>=MAXPAGE) {card_vcc(0);return 1;}    

	card_addr=(addr%0x108)&0x1ff;
//发送直接阵列方式读FLASH卡主存储区命令及地址
	array_page_read(ARRAY_READ_COM,sector,card_addr);
	do
	{
		*str=r_flash_card();	//读1字节FLASH卡主存储区数据
		str++;
	}while(--leng);
	#ifdef	HIGH
		FLASH_CARD_CLK=1;
	#else
		FLASH_CARD_CLK=0;
	#endif	//HIGH
	_nop_ ( );
	_nop_ ( );
	FLASH_CARD_CS=1;
	card_vcc(0);
	return 0;
}
#endif //FLASH_ARRAY

uchar  read_flash_card(ulong addr,uint leng,uchar xdata *str)
{
	uchar	i;
	uint crcnum;
	for(i=0;i<3;i++)
	{
		if(read_flash_card1(addr,leng,str))
		{
			delayms(250,10);	//卡放电时间
			continue;
		}
		crcnum=crcxdata(leng,1,str);
		if(read_flash_card1(addr,leng,str))
		{
			delayms(250,10);	//卡放电时间
			continue;
		}
		if(crcnum==crcxdata(leng,1,str))	return 0;
	}
	return 1;
}

/*******************************************************************/
uchar write_flash_card1(ulong addr,uint leng,uchar xdata *str)
{
	uchar card_data;
	uint sector,card_addr;

	initial_flash_card1();

	sector=(addr/0x108)&0xfff;
	if(sector>=(MAXPAGE-1)) {card_vcc(0);return 1;}    

	card_addr=(addr%0x108)&0x1ff;
//FLASH卡主存储区数据读到缓冲区
	if(write_card_com(BUFFER_SECTOR_COM,sector)) {card_vcc(0);return 1;}
//发送写缓冲区命令及地址
	write_flash_buffer(sector,card_addr);
	do{
		card_data=*str;
		str++;
		w_flash_card(card_data);	//写1字节到缓冲区
		card_addr++;
		if((card_addr>=MAXBYTE)&&(leng!=1))                    
		{
			#ifdef	HIGH
				FLASH_CARD_CLK=1;
			#else
				FLASH_CARD_CLK=0;
			#endif
			_nop_ ( );
			_nop_ ( );
			FLASH_CARD_CS=1;
			if(read_card_status()) {card_vcc(0);return 1;}
		//缓冲区数据写到FLASH卡主存储区
			if(write_card_com(BUFFER_RWRITE_COM,sector)) {card_vcc(0);return 1;}
			
			sector++;
			if(sector>=(MAXPAGE-1)) {card_vcc(0);return 1;}    
			card_addr=0;
		//FLASH卡主存储区数据读到缓冲区
			if(write_card_com(BUFFER_SECTOR_COM,sector)) {card_vcc(0);return 1;}
		//发送写缓冲区命令及地址
			write_flash_buffer(sector,card_addr);
		}
	}while(--leng);
	#ifdef	HIGH
		FLASH_CARD_CLK=1;
	#else
		FLASH_CARD_CLK=0;
	#endif
	_nop_ ( );
	_nop_ ( );
	FLASH_CARD_CS=1;
	if(read_card_status()) {card_vcc(0);return 1;}
	if(write_card_com(BUFFER_RWRITE_COM,sector)) {card_vcc(0);return 1;}
	
	card_vcc(0);
	return 0;
}

/*******************************************************************/
uchar write_flash_card(ulong addr,uint leng,uchar xdata *str)
{
	uchar	i;
	uchar	xdata buf[1030];
	uchar	xdata *pointer;
	uint 	length,crcnum;
	
	pointer=str;
	while(1)
	{
		if(leng>1024)	length=1024;
		else	length=leng;
		crcnum=crcxdata(length,1,pointer);
		for(i=0;i<3;i++)
		{
			if(write_flash_card1(addr,length,pointer))
			{
				delayms(250,10);	//卡放电时间
				continue;
			}
			if(read_flash_card(addr,length,buf))	return 1;
			if(crcnum==crcxdata(length,1,buf))	break;
		}
		if(i==3)	return 1;
		pointer+=length;
		addr+=length;
		leng-=length;
		if(!leng)	return 0;
	}
}

/**************************************************************/
uchar initial_flash_card(void)       /* FLASH CARD卡的上电及卡确认*/
{
	uchar	i,error;

	for(i=0;i<3;i++)
	{
		initial_flash_card1();
//		read_flash_card(540408,32,buf);
		error=read_card_status();
		card_vcc(0);
		if(error)
		{
			delayms(250,10);
			continue;
		}
		if((r_w_byte&0x38)==0x18)	return 0;
		delayms(250,10);
		continue;
	}
	return 1;
}
#endif	//RW_FLASH_CARD

/*CPU CARD*/
uchar rece_cpu_byte(void)
{
	uchar	i,j=4,m;
	uint	k;
	do
	{
		m=cpu_d;	//等待起始位960 X CPU_D X CPU_TC2
		do
		{
			i=cpu_tc2;
			do
			{
				k=9600;
				IC_CARD_IO=1;
				do	//10us
				{
					if(!IC_CARD_IO)	break;
				}while(--k);
				if(!IC_CARD_IO)	break;
			}while(--i);
			if(!IC_CARD_IO)	break;
		}while(--m);
		if(!m)	return TIMEO;	//超时出错
		delay_half_etu();
		i=8;
		do	//读出8数据位
		{
			delay_etu();
			if(cpu_t)
			{
				r_w_byte=r_w_byte>>1;
				HBIT=IC_CARD_IO;
				_nop_();
			}
			else
			{
				r_w_byte=r_w_byte<<1;
				LBIT=IC_CARD_IO;
				_nop_();
				_nop_();
				_nop_();
			}
		}while(--i);
	
		delay_etu();	//接收奇偶校验码
		if(!cpu_t)	r_w_byte=~r_w_byte;
		ACC=r_w_byte;
		PSW1=P;
		F0=IC_CARD_IO;
		delay_half_etu();
		if(PSW1)
		{
			if(F0)	return 0;
		}
		else
		{
			if(!F0)	return 0;
		}

		delay_half_etu();
		IC_CARD_IO=0;	//10.5 * etu发送错误信号
		delay_etu();
		delay_etu();
		IC_CARD_IO=1;
	}while(--j);
	return PARERR;
}

uchar send_cpu_byte(uchar send_data)
{
	uchar i,j=4;
	do
	{
		IC_CARD_IO=1;
		delay_etu();	//字符间隔时间
		delay_etu();
		delay_etu();
		delay_etu();
		IC_CARD_IO=1;
		if(!IC_CARD_IO)	return PARERR;
		if(cpu_tc1&&(cpu_tc1!=0xff))
		{
			i=cpu_tc1;
			do
			{
				delay_half_etu();
				delay_half_etu();
			}while(--i);
		}
	
		IC_CARD_IO=0;		//发送起始位
		r_w_byte=send_data;
		if(!cpu_t)	r_w_byte=~r_w_byte;
		i=8;
		do
		{
			delay_etu();
			if(cpu_t)
			{
				IC_CARD_IO=LBIT;
				r_w_byte=r_w_byte>>1;
				_nop_();
			}
			else
			{
				IC_CARD_IO=HBIT;
				r_w_byte=r_w_byte<<1;
				_nop_();
				_nop_();
				_nop_();
				_nop_();
			}
		}while(--i);

		delay_etu();
		ACC=send_data;
		_nop_();
		_nop_();
		IC_CARD_IO=P;	//发送奇偶校验位
		delay_etu();
		r_w_byte=5;
		while(--r_w_byte);
	
		IC_CARD_IO=1;		//检测错误信号
		delay_etu();
		r_w_byte=5;
		while(--r_w_byte);
		if(IC_CARD_IO)	return 0;	//11 * etu
		delay_half_etu();
	}while(--j);
	return PARERR;
}

uint atr_cpucard(uchar *buf)
{
	uchar	xdata i,temp,atr_len,error,cpu_tck=0,ti=0;
	uchar xdata *p;
	uint	j=10000;
	UNST	bw;
	atr_len=0;
	p=buf;
	bw.word=0;

	cpu_ta1=0x11,cpu_d=1,cpu_tc1=0,cpu_tc2=10;
	EA=0;
	select_card_type(CPUCARD);
	card_vcc(1);
	IC_CARD_RST=0;
	do	//等待起始位
	{
		if(!IC_CARD_IO)	break;
	}while(--j);
	IC_CARD_RST=1;
	cpu_t=1;	//以正向协议传输
	if(rece_cpu_byte())	//TS
	{
		EA=1;
		bw.byte.Lo=CPUCARDER;	//非CPU卡
		return bw.word;
	}
	if(r_w_byte==0x03)	//反向传输
	{
		cpu_t=0;
		r_w_byte=0x3f;
	}
	else if(r_w_byte!=0x3b)	//正向传输
	{
		EA=1;
		bw.byte.Lo=CPUCARDER;	//非CPU卡
		return bw.word;
	}
	*p=r_w_byte;
	p++;
	atr_len++;
	
	error=rece_cpu_byte();	//接收T0
	if(error)
	{
		bw.byte.Lo=error;
		EA=1;
		return bw.word;
	}
	*p=r_w_byte;
	p++;
	atr_len++;
	bw.byte.Hi=r_w_byte&0x0f;	//保存历史字节数据长度
	if((r_w_byte&0x0f)>32)	//历史字节数据超长出错
	{
		EA=1;
		bw.byte.Lo=RECEOV;
		return bw.word;
	}
	
atr_cpu1:
	temp=r_w_byte>>4;
	i=4;
	do	//Td1...Tdi
	{
		if(temp&0x01)
		{
			error=rece_cpu_byte();
			if(error)
			{
				bw.byte.Lo=error;
				EA=1;
				return bw.word;
			}
			*p=r_w_byte;
			p++;
			atr_len++;
			if(atr_len==32)	//数据超长出错
			{
				EA=1;
				bw.byte.Lo=RECEOV;
				return bw.word;
			}
			if(i==4)	//TAi
			{
				if(!ti)	cpu_ta1=r_w_byte;	//TA1决定接收字符间最大时间
				else if(ti==1)	cpu_tck=1;	//TA2...N表示有TCK校验
			}
			else if(i==2)	//TCi
			{
				if(!ti)	cpu_tc1=r_w_byte;	//TC1决定发送字符间最小时间
				else if(ti==1)	cpu_tc2=r_w_byte;	//TC2决定接收字符间最大时间
			}
			else if(i==1)	//TDi---是否有TCK
			{
				if(r_w_byte&0x0f)	cpu_tck=1;	//TDi表示有TCK校验
				ti++;
				goto atr_cpu1;
			}
		}
		temp=temp>>1;
	}while(--i);
	
	if(bw.byte.Hi)	//有历史数据
	{
		i=bw.byte.Hi;
		bw.byte.Hi+=atr_len;
		do		//读出历史字节:T1...Tk
		{
			error=rece_cpu_byte();
			if(error)
			{
				bw.byte.Lo=error;
				EA=1;
				return bw.word;
			}
			*p=r_w_byte;
			p++;
			atr_len++;
			if(atr_len==32)	//数据超长出错
			{
				EA=1;
				bw.byte.Lo=RECEOV;
				return bw.word;
			}
		}while(--i);
	}
	else	bw.byte.Hi=atr_len;
	
	if(cpu_tck)	//有TCK校验
	{
		error=rece_cpu_byte();	//读出TCK校验值
		if(error)
		{
			bw.byte.Lo=error;
			EA=1;
			return bw.word;
		}
		*p=r_w_byte;
		p++;
		atr_len++;
		
		temp=0;	//TCK校验
		for(i=1;i<atr_len;i++)	temp^=buf[i];
		if(temp)	//异或校验出错
		{
			EA=1;
			bw.byte.Lo=XORERR;
			return bw.word;
		}
	}
		
	if(!cpu_tc2)	cpu_tc2=10;
	switch(cpu_ta1&0x0f)
	{
		case	1:
			cpu_d=1;
			break;
		case	2:
			cpu_d=2;
			break;
		case	3:
			cpu_d=4;
			break;
		case	4:
			cpu_d=8;
			break;
		case	5:
			cpu_d=16;
			break;
		case	6:
			cpu_d=32;
			break;
		case	8:
			cpu_d=12;
			break;
		case	9:
			cpu_d=20;
			break;
		default:
			break;
	}
	EA=1;
	return bw.word;
}

uchar  Cpu_Apdu(uchar xdata *out_buf,uchar xdata *in_buf)
{
	uchar	data ins;
	uchar	i,lc,le,lout,error,send_flag=0;
	uchar	xdata buf[10];
	uchar   xdata *out,*in;
	uchar   xdata **pp;
	UNST	bw;
	EA=0;
	le=0;
	lc=out_buf[4];
	for(i=0;i<5;i++)	buf[i]=out_buf[i];
	if(!lc)	//只读数据
	{
		le=out_buf[7];
		buf[4]=le;
	}
	lout=le;
	ins=buf[1];
	
	pp=(uchar *)&out_buf[5];
	out=*pp;
	pp=(uchar *)&in_buf[1];
	in=*pp;

	bw.word=0;
	while(1)
	{
		if(!send_flag)	//发送命令
		{
			send_flag=1;
			for(i=0;i<5;i++)
			{
				error=send_cpu_byte(buf[i]);
				if(error)	//奇偶错
				{
					EA=1;
					return error;
				}
			}
		}
		
		error=rece_cpu_byte();	//读ACK1
		if(error)
		{
			EA=1;
			return error;
		}
		bw.byte.Hi=r_w_byte;
		if(r_w_byte==0x60)	continue;	//CPU卡忙
		
		if(((r_w_byte&0xf0)==0x60)||((r_w_byte&0xf0)==0x90))	//此时SW1=ACK1
		{
			error=rece_cpu_byte();	//读SW2
			if(error)
			{
				EA=1;
				return error;
			}
			bw.byte.Lo=r_w_byte;
			send_flag=0;
			if(bw.byte.Hi==0x61)	//lc,le同时有效
			{//读取数据长度与文件实际长度不匹配,重发
				buf[0]=0;
				buf[1]=0xc0;
				buf[2]=0;
				buf[3]=0;
				buf[4]=r_w_byte;
				le=r_w_byte;
				lout=le;
				ins=buf[1];
				continue;
			}
			else if(bw.byte.Hi==0x6c)	//没有lc时有效
			{//读取剩余数据
				buf[4]=r_w_byte;
				le=r_w_byte;
				lout=le;

⌨️ 快捷键说明

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