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

📄 ecrcard.c

📁 写IC卡的参考代码,应用于读写IC卡的数据,电表,水表开发场合适用
💻 C
📖 第 1 页 / 共 3 页
字号:
				continue;
			}
			else
			{
				if(lout==le)	lout=0;	//没有读取到数据
				in_buf[0]=lout;
				in_buf[3]=bw.byte.Hi;
				in_buf[4]=bw.byte.Lo;
				EA=1;
				return 0;
			}
		}//SW1,SW2--0x60-0x9f
		if(r_w_byte==ins)	//命令完成,可以传输数据块
		{
			if(lc)	//写数据
			{
				do
				{
					error=send_cpu_byte(*out);
					if(error)	//奇偶错
					{
						EA=1;
						return error;
					}
					out++;
				}while(--lc);
				continue;
			}
			else if(le)	//读本记录的有效存储数据
			{
				do
				{
					error=rece_cpu_byte();	//读数据
					if(error)
					{
						EA=1;
						return error;
					}
					delay_half_etu();
					*in=r_w_byte;
					in++;
				}while(--le);
				continue;
			}
			continue;
		}//SW1==ins
		r_w_byte=~r_w_byte;
		if(r_w_byte==ins)	//命令完成,只可以传输单字节数据
		{
			if(lc)	//写数据
			{
				error=send_cpu_byte(*out);
				if(error)	//奇偶错
				{
					EA=1;
					return error;
				}
				out++;
				--lc;
				continue;
			}
			else if(le)	//读1字节本记录的有效存储数据
			{
				error=rece_cpu_byte();	//读数据
				if(error)
				{
					EA=1;
					return error;
				}
				delay_half_etu();
				*in=r_w_byte;
				in++;
				--le;
				continue;
			}
			continue;
		}//SW1==/ins
		ins++;
		if(r_w_byte==ins)	//卡类型错
		{
			EA=1;
			return CARDER;
		}//SW1==/(ins+1)
		r_w_byte=~r_w_byte;
		if(r_w_byte==ins)	//卡类型错
		{
			EA=1;
			return CARDER;
		}//SW1==ins+1;
		else	//通信出错
		{
			EA=1;
			return TRANER;
		}
	}//while(1)
}

/*SAM CARD*/
uchar rece_sam_byte(void)
{
	uchar	i,j=4,m;
	uint	k;
	do
	{
		m=sam_d;	//等待起始位960 X SAM_D X SAM_TC2
		do
		{
			i=sam_tc2;
			do
			{
				k=9600;
				SAM_CARD_IO=1;
				do	//10us
				{
					if(!SAM_CARD_IO)	break;
				}while(--k);
				if(!SAM_CARD_IO)	break;
			}while(--i);
			if(!SAM_CARD_IO)	break;
		}while(--m);
		if(!m)	return TIMEO;	//超时出错
		delay_half_etu();
		i=8;
		do	//读出8数据位
		{
			delay_etu();
			if(sam_t)
			{
				r_w_byte=r_w_byte>>1;
				HBIT=SAM_CARD_IO;
				_nop_();
			}
			else
			{
				r_w_byte=r_w_byte<<1;
				LBIT=SAM_CARD_IO;
				_nop_();
				_nop_();
				_nop_();
			}
		}while(--i);
	
		delay_etu();	//接收奇偶校验码
		if(!sam_t)	r_w_byte=~r_w_byte;
		ACC=r_w_byte;
		PSW1=P;
		F0=SAM_CARD_IO;
		delay_half_etu();
		if(PSW1)
		{
			if(F0)	return 0;
		}
		else
		{
			if(!F0)	return 0;
		}
		
		delay_half_etu();
		SAM_CARD_IO=0;	//10.5 * etu发送错误信号
		delay_etu();
		delay_etu();
		SAM_CARD_IO=1;
	}while(--j);
	return PARERR;
}

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

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

uint atr_samcard(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;

	sam_ta1=0x11,sam_d=1,sam_tc1=0,sam_tc2=10;
	EA=0;
	samcard_vcc(1);
	SAM_CARD_RST=0;
	do	//等待起始位
	{
		if(!SAM_CARD_IO)	break;
	}while(--j);
	SAM_CARD_RST=1;
	sam_t=1;	//以正向协议传输
	if(rece_sam_byte())	//TS
	{
		EA=1;
		bw.byte.Lo=CPUCARDER;	//非CPU卡
		return bw.word;
	}
	if(r_w_byte==0x03)	//反向传输
	{
		sam_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_sam_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_sam1:
	temp=r_w_byte>>4;
	i=4;
	do	//Td1...Tdi
	{
		if(temp&0x01)
		{
			error=rece_sam_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)	sam_ta1=r_w_byte;	//TA1决定接收字符间最大时间
				else if(ti==1)	cpu_tck=1;	//TA2...N表示有TCK校验
			}
			else if(i==2)	//TCi
			{
				if(!ti)	sam_tc1=r_w_byte;	//TC1决定发送字符间最小时间
				else if(ti==1)	sam_tc2=r_w_byte;	//TC2决定接收字符间最大时间
			}
			else if(i==1)	//TDi---是否有TCK
			{
				if(r_w_byte&0x0f)	cpu_tck=1;	//TDi表示有TCK校验
				ti++;
				goto atr_sam1;
			}
		}
		temp=temp>>1;
	}while(--i);
	
	if(bw.byte.Hi)	//有历史数据
	{
		i=bw.byte.Hi;
		bw.byte.Hi+=atr_len;
		do		//读出历史字节:T1...Tk
		{
			error=rece_sam_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_sam_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(!sam_tc2)	sam_tc2=10;
	switch(sam_ta1&0x0f)
	{
		case	1:
			sam_d=1;
			break;
		case	2:
			sam_d=2;
			break;
		case	3:
			sam_d=4;
			break;
		case	4:
			sam_d=8;
			break;
		case	5:
			sam_d=16;
			break;
		case	6:
			sam_d=32;
			break;
		case	8:
			sam_d=12;
			break;
		case	9:
			sam_d=20;
			break;
		default:
			break;
	}
	EA=1;
	return bw.word;
}

uchar  Sam_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_sam_byte(buf[i]);
				if(error)	//奇偶错
				{
					EA=1;
					return error;
				}
			}
		}
		
		error=rece_sam_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_sam_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;
				continue;
			}
			else
			{
				if(lout==le)	lout=0;	//没有读取到数据
				in_buf[0]=lout;
				in_buf[3]=bw.byte.Hi;
				in_buf[4]=bw.byte.Lo;
				EA=1;
				return 0;
			}
		}//SW1,SW2--0x60-0x9f
		if(r_w_byte==ins)	//命令完成,可以传输数据块
		{
			if(lc)	//写数据
			{
				do
				{
					error=send_sam_byte(*out);
					if(error)	//奇偶错
					{
						EA=1;
						return error;
					}
					out++;
				}while(--lc);
				continue;
			}
			else if(le)	//读本记录的有效存储数据
			{
				do
				{
					error=rece_sam_byte();	//读数据
					if(error)
					{
						EA=1;
						return error;
					}
					delay_half_etu();
					*in=r_w_byte;
					in++;
				}while(--le);
				continue;
			}
			continue;
		}//SW1==ins
		r_w_byte=~r_w_byte;
		if(r_w_byte==ins)	//命令完成,只可以传输单字节数据
		{
			if(lc)	//写数据
			{
				error=send_sam_byte(*out);
				if(error)	//奇偶错
				{
					EA=1;
					return error;
				}
				out++;
				--lc;
				continue;
			}
			else if(le)	//读1字节本记录的有效存储数据
			{
				error=rece_sam_byte();	//读数据
				if(error)
				{
					EA=1;
					return error;
				}
				delay_half_etu();
				*in=r_w_byte;
				in++;
				--le;
				continue;
			}
			continue;
		}//SW1==/ins
		ins++;
		if(r_w_byte==ins)	//卡类型错
		{
			EA=1;
			return CARDER;
		}//SW1==/(ins+1)
		r_w_byte=~r_w_byte;
		if(r_w_byte==ins)	//卡类型错
		{
			EA=1;
			return CARDER;
		}//SW1==ins+1;
		else	//通信出错
		{
			EA=1;
			return TRANER;
		}
	}//while(1)
}

⌨️ 快捷键说明

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