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

📄 sim.c

📁 用keil开发的.单片机税控器程序.单片机用的是AT公司的.upsd3245
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
* Copyright (c) 2004,成都港顺科技发展有限公司
* All rights reserved.
*
* 编 译 器:Keil:C Compiler:7.20;Assembler:7.10
* 工程名称:POS-Test.UV2
* 文件名称:Sim.C
* 摘    要:与税控IC卡通讯的所有底层函数
*
* 单 片 机:uPSD3254
* 当前版本:0.4
* 作    者:李凯
* 完成日期:2004-12-7 14:45
*/

#include "Main.h"

#define SIM0RXD 	PDO=0		//select Sim0 RXD Mode
#define SIM0TXD 	PDO=0x02	//select Sim0 TXD Mode
#define SIM1RXD 	PDO=0x04	//select Sim1 RXD Mode
#define SIM1TXD 	PDO=0x06	//select Sim1 TXD Mode

#define Ctr0Set		P15=1
#define Ctr0Clr		P15=0
#define Ctr1Set		P17=1
#define Ctr1Clr		P17=0

#define Rst0Set		P14=1
#define Rst0Clr 	P14=0
#define Rst1Set		P16=1
#define Rst1Clr 	P16=0

#define SimWoQi		0		//渥奇的卡
#define SimTianYu	1		//天喻的卡
#define SimWoQi100K	2		//渥奇的100K卡

sbit CardDetect=P3^4;

//uchar xdata SimTimeOut,SimType,SimEtu;
xdata uchar SimTimeOut,SimType,SimGuardTime,SimWaitTime,SimIns;

uchar SimDetect(uchar x)
{//x=0x11:插入用户卡;=0x12:插入管理卡;=0x01:取出用户卡;=0x02:取出管理卡
	uint i=1000,k=1000;

	if((x&0x10)!=0)
	{
		if(x==0x11)
		{
			LcdDisplay(0,0,"请插入用户卡!",3);
		}
		else
		{
			LcdDisplay(0,0,"请插入管理卡!",3);
		}
		SimDeactive(1);
		while(CardDetect==0){if(GetKey()==K_TC)return 0;}
		while(--i);
		while(CardDetect==0){if(GetKey()==K_TC)return 0;}
		SimDeactive(1);
		while(--k);
	}
	else
	{
		if(x==0x01)
			LcdDisplay(48,0,"请取出用户卡!",1);
		else
			LcdDisplay(48,0,"请取出管理卡!",1);
		SimDeactive(1);
		while(CardDetect==1){if(GetKey()==K_TC)return 0;}
		while(--i);
		while(CardDetect==1){if(GetKey()==K_TC)return 0;}
	}
	return 1;
}

void SimActive(uchar ch)
{
	uchar k=185,m=75;

	TXD=1;
	RXD=1;
	RI=0;TI=0;
	if(ch==0)
	{
		Rst0Set;
		Ctr0Clr;
		while(--k);
		Rst0Clr;
		while(--m);
		Rst0Set;
		SIM0RXD;
	}
	else
	{
		Rst1Set;
		Ctr1Clr;
		while(--k);
		Rst1Clr;
		while(--m);
		Rst1Set;
		SIM1RXD;
	}
}

void SimDeactive(uchar ch)
{
	uchar x=250;

	if(ch==0)
	{
		Rst0Clr;			//RSTIN=0
		Ctr0Set;			//CMDVcc=1
		SIM0TXD;
	}
	else
	{
		Rst1Clr;			//RSTIN=0
		Ctr1Set;			//CMDVcc=1
		SIM1TXD;
	}
	while(--x);		//至少需要125us
}

void SimTxdByte(uchar dat)
{
	uchar i,j;

	i=SimGuardTime+1;		//对ISO7816-3来说,发送一个字节+奇偶位需要12个ETU
	while(i>0)				//但是对51单片机来说,发送一个字节+奇偶位只有10个ETU
	{
		j=104;
		while(--j);
		i--;
	}	
	ACC=dat;
	TB8=P;
	while(1)
	{
		SBUF = dat;
		while(!TI);
		TI=0;
		j=100;
		while(--j);
		if(TXD==1)break;//发送方在起始上升沿之后的(11±0.2)基本时间单元(etu)时刻检测I/O
		else
		{//检测到差错信号,至少两个etu延时之后才重发
			j=208;		//Bps9600: Etu=104 us
			while(--j);
		}
	}
}

uchar SimRxdByte()
{
	uchar dat,j;
	ulong m,n;
	bit x;
	
	SimTimeOut=0;
	n=SimWaitTime*9600;
	while(1)
	{
		m=n;
		while(!RI)
		{
			m--;
			if(m==0)
			{
				SimTimeOut=1;
				return 0;
			}
		}
		RI=0;
		dat=SBUF;
		ACC=dat;
		x=P;
		if(x==RB8)
			return dat;
		else
		{//奇偶效验错误时,从(10.5±0.2)基本时间单元(etu)开始,
			REN=0;
			j=50;		//从(10.5±0.2)基本时间单元(etu)开始
			while(--j);
			RXD=0;		//传送一个状态为A(低电平),最少为1etu,最大为2etu的差错信号
			j=120;		//Bps9600: Etu=104 us ;
			while(--j);
			RXD=1;
			j=104;		//卡在至少2etu后重发数据
			while(--j);
			REN=1;
		}
	}
}

//TS T0 TA1 TB1 TC1 TD1 TA2 TB2 TC2 TD2 TA3 TB3 TC3 TD3 TA(i) TB(i) TC(i) TD(i) T1 T2 ... TK TCK
uchar SimATR()
{
	uchar i,m,n,len,k,f,x,y,v,TX[24];
	uchar dat;

	memset(TX,0,sizeof(TX));
	len=2;
	SimGuardTime=0;
	SimWaitTime=10;
	i=0;v=0;
	f=0;k=0;
	x=0;y=0;
	m=0;n=0;
	while(1)
	{
//		RxdLen=len;			//TEST
		dat=SimRxdByte();
		if(SimTimeOut==1)
			return 0;
		RxdBuf[i]=dat;
		if(i==1)
		{	
			m=2;n=2;		
			len+=(dat&0x0F);	//历史字节数目
			if(dat&0x10){TX[0]=1;len++;m++;n++;}		//判断TA1-TD1是否存在
			if(dat&0x20){TX[1]=1;len++;m++;n++;}
			if(dat&0x40){TX[2]=1;len++;n++;}
			if(dat&0x80){TX[3]=1;len++;}
		}
		if(i==m && TX[2]==1)
		{//额外保护时间N=TC1			
			if(dat==255)SimGuardTime=0;
			else	SimGuardTime=dat;
		}
		if(i==n && TX[3]==1)	//TD1存在并且已经收到
		{
			if((dat&0x0F)!=0)
			{//TCK存在
				f=1;
				len++;
			}
			x=n+1;
			y=x;
			if(dat&0x10){TX[4]=1;len++;x++;y++;}		//判断TA2-TD2是否存在
			if(dat&0x20){TX[5]=1;len++;x++;y++;}
			if(dat&0x40){TX[6]=1;len++;y++;}
			if(dat&0x80){TX[7]=1;len++;}
		}
		if(i==x && TX[6]==1)	//TC2存在并且已经收到
		{//最大工作等待时间
			k=dat;			
		}
		if(i==y && TX[7]==1)	//TD2存在并且已经收到
		{
			if(f==0 && ((dat&0x0F)!=0))
			{//TCK存在
				f=1;
				len++;
			}
			v=y+1;			
			if(dat&0x10){TX[8]=1;len++;v++;}		//判断TA3-TD3是否存在
			if(dat&0x20){TX[9]=1;len++;v++;}
			if(dat&0x40){TX[10]=1;len++;v++;}
			if(dat&0x80){TX[11]=1;len++;}
		}
		if(i==v && TX[11]==1)	//TD3存在并且已经收到
		{
			if(f==0 && ((dat&0x0F)!=0))
			{//TCK存在
				len++;
				f=1;
			}
			if(dat&0x10){TX[12]=1;len++;}		//判断TA4-TD4是否存在
			if(dat&0x20){TX[13]=1;len++;}
			if(dat&0x40){TX[14]=1;len++;}
			if(dat&0x80){TX[15]=1;len++;}
		}
		i++;
		if(i>=len)break;
	}
	if(k!=0)SimWaitTime=k;

	switch(RxdBuf[1])
	{
		case 0x7A:	SimType=SimTianYu;		break;
		case 0x7D:	SimType=SimWoQi;		break;
		case 0x7F:	SimType=SimWoQi100K;	break;
		default	:	SimType= 0;				break;
	}
//	RxdLen=len;		//test
	if(f!=0)
	{//TCK存在
		k=0;
		len-=1;
		for(i=1;i<len;i++)
			k^=RxdBuf[i];
		if(k!=RxdBuf[len])
		{
			ErrorHint("复位应答TCK错误!",0x9100);
		}
	}
	k=12;
	while(--k)
	{//The answer to reset is complete 12 etu after the leading edge of the last character.
		i=104;
		while(--i);
	}
//	UartTxd(1,&SimGuardTime);
	return 1;
}

uchar SimRstCold(uchar ch)
{
	uint i;

	SimDeactive(ch);
	UART0_Mod3_Timer1_9600;		//禁止多机通信,8位数据+奇偶效验位
	SimActive(ch);
	i=SimATR();
	if(i==0)
	{
		if(ch==0)ErrorHint("复位失败,请检查税控卡!",0x110);
		if(ch==1)ErrorHint("复位失败,请检查用户卡!",0x111);
		else	 ErrorHint("复位失败,请检查管理卡!",0x112);
	}
//	return SimBpsSet(19200,ch);
	return 1;
}

uint ProcedureByte(uchar ins,uchar ch)
{
	uchar k,ack;
//	uchar x;
	gyt2 mp;

	if(ch == 0)SIM0RXD;
	else	SIM1RXD;
	while(1)
	{
		ack=SimRxdByte();
		if(SimTimeOut==1)return 0xFFFC;
		if(ack!=0x60)break;
	}
	k=ack&0xF0;
	if(k==0x60 || k==0x90)
	{
		mp.str[0]=ack;
		mp.str[1]=SimRxdByte();
		if(SimTimeOut==1)return 0xFFFD;
		SimTimeOut=0xFF;
		return mp.dat;
	}
	else
	{
		k=ack^ins;
		if(k==0xFF || k==0xFE)	//仅传输下一个字节,编程电压不处理
			return 2;
		if(k==0 || k==1)		//传输所有余下数据,编程电压不处理
			return 1;
		ErrorHint("过程字节不正确",k);			//过程字节不正确必须报错
	}
}

uint SimCmd(uchar tlen,uchar ch)
{
	gyt2 *state;
	uint k;
	uchar x,dat,rnum,tnum,ins;
	uchar lc,le,rlen;

	if(tlen>5)
	{//lc 存在
		lc=TxdBuf[4];
		if(tlen>(lc+5))
		{//le存在,但是不发送le
			le=TxdBuf[lc+5];
			tlen-=1;
		}
		else
		{//le不存在
			le=0;
		}
	}
	else //tlen==5,tlen不可能小于5
	{//le、lc都不存在,或者le=0需要返回最大数据,或者仅le存在,都只需要接受SW1、SW2
		lc=0;
		le=TxdBuf[4];		
	}
	rlen=le+2;		//SW1+SW2
	UART0_Mod3_Timer1_9600;
//	UART0_Mod3_Timer2_19200;
	tnum=0;
	SimIns=0;
	ins=TxdBuf[1];
//	SIMCS;						//cs6	
	TI=0;RI=0;
	while(1)
	{
		if(ch == 0)SIM0TXD;
		else	SIM1TXD;
		SimTxdByte(TxdBuf[tnum++]);
		if(tnum==5 && lc!=0)
		{
			k=ProcedureByte(ins,ch);		//获得过程字节
			if(SimTimeOut==0xFF || SimTimeOut==1)return k;
			if(k!=2 && k!=1)return k;
			if(k==2)
			{
				while(1)
				{
					if(ch == 0)SIM0TXD;
					else	SIM1TXD;
					SimTxdByte(TxdBuf[tnum++]);
					if(tnum>=tlen)break;
					k=ProcedureByte(ins,ch);
					if(SimTimeOut==0xFF || SimTimeOut==1)return k;					
					if(k!=2 && k!=1)return k;
					if(k==1)break;			//传输所有余下数据					
				}
			}
		}	
		if(tnum>=tlen)break;
	}
	if(ch == 0)SIM0RXD;
	else	SIM1RXD;
	rnum=0;tnum=0;
	x=rlen-2;
//	if(le!=0)
	{
		k=ProcedureByte(ins,ch);
		if(SimTimeOut==0xFF || SimTimeOut==1)return k;
		if(k!=2 && k!=1)return k;
		if(k==2)SimIns=1;		//仅传输下一个字节
//		if(k==1)				//传输所有余下数据
	}	
	while(1)
	{		
		dat=SimRxdByte();
		if(SimTimeOut==1)
		{
			return 0xFFFF;
		}
		if(SimIns && rnum<x)
		{
			tnum++;
			if((tnum%2)==0)continue;
		}
		if(dat==0x60 && rnum==x)continue;
		RxdBuf[rnum++]=dat;
		if(rnum>=rlen)break;
	}
	state = &RxdBuf[rlen-2];
	return state->dat;
}

//|---------------------------------------------------------------------------------|
//|税控卡和用户卡所支持的波特率:													|
//|9600           3571200/9600=372            FI=DI=1        FF1011FE          11FE	|
//|19200          3579000/19200=186=372/2     FI=1 DI=2      FF1012FD          12FD	|
//|38400          3579000/38400=94=372/4      FI=1 DI=3      FF1013FC          13FC	|
//|56000          3579000/56000=64=512/8      FI=9 DI=4      FF10947B          947B	|
//|首先检测卡片的复位信息,根据复位信息确定,以9600速率发送激活指令ff 10 94+这三	|
//|个字节的单字节异或值。卡片应该以9600返回确认值,确认值字节应该为后两个字节如	|
//|947B等表明速率已经修改成功,必须以修改后的速率进行通讯。若返回值不是后两个字 |
//|节,说明速率修改不成功。														|
//|1/Baud=etu=F/(D*fs)																|
//|---------------------------------------------------------------------------------|
/*
uint SimBpsSet(uint bps,uchar card)
{
	uint statecode,m;
	gyt2 *xp;
	TxdBuf[0]=0xFF;
	TxdBuf[1]=0x10;
	switch(bps)
	{
		case 9600:
					TxdBuf[2]=0x11;
					TxdBuf[3]=0xFE;
					break;
		case 19200:
					TxdBuf[2]=0x12;
					TxdBuf[3]=0xFD;
					break;

		case 38400:
					TxdBuf[2]=0x13;
					TxdBuf[3]=0xFC;
					break;

		case 56000:
					TxdBuf[2]=0x94;
					TxdBuf[3]=0x7B;
					break;

		default:
					TxdBuf[2]=0x11;
					TxdBuf[3]=0xFE;
					break;
	}
	xp = &TxdBuf[0];
	m = xp->dat;
	TxdLen=0xFF;
	statecode=SimCmd(4,card);
	xp = &RxdBuf[0];
	if(xp->dat==m)
	{
		SimEtu=52;
		return 1;
	}
	else
		ErrorHint("Bps Set Error!",statecode);
}
*/
//----------------------------------------------------------------------------------
uint GetResponse(uchar le,uchar card)
{
	uint statecode;

	TxdBuf[0]=0x00;
	TxdBuf[1]=0xC0;
	TxdBuf[2]=0x00;
	TxdBuf[3]=0x00;
	TxdBuf[4]=le;
	statecode=SimCmd(5,card);
	return statecode;
}

void SelectFile(uchar xp1,uchar xp2,uchar lc,uchar *dat,uchar card)
{//lc=0x02 or 0x10;		*dat:文件标识符或名称
	uchar i;
	uint statecode;

	TxdBuf[0]=0x00;
	TxdBuf[1]=0xA4;
	TxdBuf[2]=xp1;
	TxdBuf[3]=xp2;
	TxdBuf[4]=lc;
	for(i=0;i<lc;i++)
		TxdBuf[5+i]=dat[i];
	statecode=SimCmd(lc+5,card);
	if(statecode == 0x9000)return;
	if((statecode & 0xFF00)!=0x6100)
	{
		if(card==0)ErrorHint("选择税控卡文件出错!",statecode);
		if(card==1)ErrorHint("选择用户卡文件出错!",statecode);
		else		ErrorHint("选择管理卡文件出错!",statecode);
	}
	i= statecode&0x00FF;
	statecode=GetResponse(i,card);
	if(statecode != 0x9000)
	{
		if(card==0)ErrorHint("读税控卡文件数据出错!",statecode);

⌨️ 快捷键说明

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