📄 sim.c
字号:
/*
* 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 + -