原文地址::http://blog.sina.com.cn/s/blog_a20257d80101cju7.html
相关文章
1、
ISO14443-4块传输协议的实现
----http://blog.sina.com.cn/s/blog_a20257d80101cju3.html
贴上自己的代码,目前测试通过,但我感觉结构不是很好,希望和大家交流共同提高。
.H文件
#define ACKN -1
#define ACKY -2
#define RESEND -3
#define ONSENDNEXT -4
#define SENDDEL -5
#define SENDWTX -6
#define DONOTHING -12
#define BLOCK_MASK 0XC0
#define IBLOCK 0X00
#define RBLOCK 0X80
#define SBLOCK 0XC0
#define NACK_MASK 0X10
#define CID_MASK 0X08
#define BNUM_MASK 0X01
#define WTX_DEL_MASK 0X30
#define LINK_MASK 0X10
#define WTX 0X30
#define DELSECT 0X00
.c文件
unsigned char near CCID;
unsigned char near Frame_Data_Len_Card;
unsigned char near currentflag;
unsigned char near lastframe[64];
unsigned char near lastframelen;
unsigned char near PBuffer[270],CardBuffer[270];
unsigned short near PBufferLength,PBufferPoint,CardBufPoint,CardBufferLength;
bit cblock_num,CCid_En;
unsigned char AckN(void)
{
unsigned char near buf[4];
buf[0] = 0XA2|cblock_num;
buf[0] = CCid_En?buf[0]|0x08:buf[0];
buf[1] = CCID;
WriteCardFifo(buf,2);
SetRecvOrSend(START_SEND_AND_RECV);
// PutDatUart(buf, 2);
return OK;
}
unsigned char AckY(void)
{
unsigned char near buf[4];
cblock_num=!cblock_num;
buf[0] = 0XA2|cblock_num;
buf[0] = CCid_En?buf[0]|0x08:buf[0];
buf[1] = CCID;
WriteCardFifo(buf,(unsigned char)((unsigned char)CCid_En+1));
// PutDatUart(buf, 2);
return SetRecvOrSend(START_SEND_AND_RECV);
}
char CardRecvFrameProcess(unsigned char *tempbuf,unsigned char inlen)
{
unsigned short near len;
unsigned char near PCB;
unsigned char near Cid;
unsigned char near lastflag = currentflag;
len = inlen;
if(len==0)
{
return DONOTHING;
}
PCB = tempbuf[0];
Cid = PCB&CID_MASK;
if(((CCid_En==1)&&(CCID!=0)&&(Cid==0)) || ((CCid_En==0)&&(Cid==1))) return DONOTHING;
if((PCB&BLOCK_MASK) ==IBLOCK)//i-block
{
if(PCB&CID_MASK)//带CID时,长度应该不少于2字节
{
if(len<=2) return DONOTHING;
}
else //不带CID时长度不应少于1个字节
{
if(len<2) return DONOTHING;
}
if((PCB&0X02)!=0X02) return DONOTHING;
currentflag = PCB & LINK_MASK;
if(currentflag)
{
if(lastflag)
{
if((PBufferLength + len - 1 - (unsigned char)CCid_En)>BUFFERLENGTH)
{
PBufferLength=0;
PBufferPoint =0;
return DONOTHING;
}
memcpy(&PBuffer[PBufferPoint],&tempbuf[1+(unsigned char)CCid_En],len-1-(unsigned char)CCid_En);
PBufferPoint = PBufferPoint + len - 1 - (unsigned char)CCid_En;
PBufferLength = PBufferLength + len - 1 - (unsigned char)CCid_En;
}
else
{
PBufferPoint = 0;
PBufferLength = 0;
memcpy(&PBuffer[PBufferPoint],&tempbuf[1+(unsigned char)CCid_En],len-1-(unsigned char)CCid_En);
PBufferPoint = PBufferPoint + len - 1 - (unsigned char)CCid_En;
PBufferLength = PBufferLength + len - 1 - (unsigned char)CCid_En;
}
return ACKY;
}
else
{
if(lastflag)
{
if((PBufferLength + len - 1 - (unsigned char)CCid_En)>BUFFERLENGTH)
{
PBufferLength=0;
PBufferPoint =0;
return DONOTHING;
}
memcpy(&PBuffer[PBufferPoint],&tempbuf[1+(unsigned char)CCid_En],len-1-(unsigned char)CCid_En);
PBufferPoint = PBufferPoint + len - 1 - (unsigned char)CCid_En;
PBufferLength = PBufferLength + len - 1 - (unsigned char)CCid_En;
}
else
{
PBufferPoint = 0;
PBufferLength = 0;
memcpy(&PBuffer[PBufferPoint],&tempbuf[1+(unsigned char)CCid_En],len-1-(unsigned char)CCid_En);
PBufferPoint = PBufferPoint + len - 1 - (unsigned char)CCid_En;
PBufferLength = PBufferLength + len - 1 - (unsigned char)CCid_En;
}
return FM_OK;
}
}
else if((PCB&BLOCK_MASK) ==RBLOCK) //rblock
{
if(PCB&CID_MASK)//带CID时,长度应该不少于2字节
{
if(len!=2) return DONOTHING;
}
else //不带CID时长度不应少于1个字节
{
if(len!=1) return DONOTHING;
}
if((PCB&0X40)==0X00) return DONOTHING;
if(PCB&NACK_MASK)
{
if((PCB&BNUM_MASK)!=cblock_num)
{
return ACKN;//表示重发NAK,因帧号不对
}
else
{
return RESEND; //表示重发上一帧
}
}
else //ack
{
if((PCB&BNUM_MASK)!=cblock_num)
{
return SENDNEXT; //表示继续发下一帧
}
else
{
return RESEND; //表示重发上一帧
}
}
}
else if((PCB&BLOCK_MASK) ==SBLOCK) //sblock
{
if((PCB&0X04)!=0X00) return DONOTHING;
if((PCB&WTX_DEL_MASK)==DESELECT)
{
if(PCB&CID_MASK)
{
if(len!=0x02) return DONOTHING;
else return SENDDEL;
}
else
{
if(len!=0x01) return DONOTHING;
else return SENDDEL;
}
}
else if((PCB&WTX_DEL_MASK)==WTX)
{
if(PCB&CID_MASK)
{
if(len!=0x03) return DONOTHING;
else return SENDWTX;
}
else
{
if(len!=0x02) return DONOTHING;
else return SENDWTX;
}
}
else
{
return DONOTHING;
}
}
else
{
return DONOTHING;
}
}
char CardCosInsProcess()
{
Timer0Delay(FIFTY_MINISECOND); //这个时间根据卡返回的ATS中的参数确定,默认为4.8ms,在定时器中断中发WTX,并禁止再次中断,停止定时器
EnableTimer0Int();
StopTimer0();
return OK;
}
char CardSendFrameProcess(char STA)
{
unsigned char near tempbuf[64];
unsigned char near len;
char near Sta=STA;
unsigned char near CardMLen = Frame_Data_Len_Card-2-(unsigned char)CCid_En -1;
//WTimeS = 0;
switch(Sta)
{
case ACKY:
AckY();
break;
case ACKN:
AckN();
break;
case RESEND:
memcpy(tempbuf,lastframe,lastframelen);
WriteCardFifo(tempbuf,lastframelen);
SetRecvOrSend(START_SEND_AND_RECV);
// PutDatUart(tempbuf,lastframelen);
break;
case ONSENDNEXT:
cblock_num = !cblock_num;
wtempfc[0] = CCid_En?0X0A:0X02;
wtempfc[0]= CardBufferLength>CardMLen?((tempbuf[0] | 0X10) | cblock_num):(tempbuf[0] | cblock_num);
wtempfc[1] = CCID;
len = (CardBufferLength>(CardMLen))?CardMLen:CardBufferLength;
memcpy(&tempbuf[(unsigned char)CCid_En+1],&CardBuffer[CardBufPoint],len);
WriteCardFifo(tempbuf,(unsigned char)(len+(unsigned char)CCid_En+1));
SetRecvOrSend(START_SEND_AND_RECV);
// PutDatUart(tempbuf,(unsigned char)(len+((unsigned char)CCid_En)+1));
CardBufPoint = CardBufPoint + len;
CardBufferLength = CardBufferLength - len;
break;
case SENDDEL:
SDeselect();
SetCardIdle();
break;
case SENDWTX:
Timer0Delay(FIFTY_MINISECOND);
//这个时间根据卡返回的ATS中的参数确定,默认为4.8ms,在定时器中断中发WTX,并禁止再次中断,停止定时器
EnableTimer0Int();
break;
case GETDATA:
cblock_num= !cblock_num;
tempbuf[0] = CCid_En?0X0A:0X02;
tempbuf[0] = CardBufferLength>CardMLen?((tempbuf[0] | 0X10) | cblock_num):(tempbuf[0] | cblock_num)
tempbuf[1] = CCID;
CardBufPoint = 0;
len = (CardBufferLength>CardMLen)?CardMLen:CardBufferLength;
memcpy(&tempbuf[(unsigned char)CCid_En+1],&CardBuffer[CardBufPoint],len+(unsigned char)CCid_En+1);
WriteCardFifo(tempbuf,(unsigned char)(len+((unsigned char)CCid_En)+1));
SetRecvOrSend(START_SEND_AND_RECV);
// PutDatUart(tempbuf,(unsigned char)(len+((unsigned char)CCid_En)+1));
CardBufPoint = CardBufPoint + len;
CardBufferLength = CardBufferLength - len;
break;
case DONOTHING:
default:break;
} return OK;
}最后,关于WTX的处理,需要一个定时器,其初值由ATS的内容确定,这里不再叙述