www.pudn.com > rfid.rar > 14443.c, change:2012-04-22,size:14216b


/******************************************************************************* 
 * 文件名称:14443.c 
 * 功    能:ISO14443A和ISO14443B协议的实现 
 * 作    者:Ronnie 
 * 公    司:湘潭斯凯电子科技有限公司 
 *           www.sikai-tech.com 
 * 日    期:2011-06-22 
 ******************************************************************************/ 
 
 
/* 包含头文件 */ 
/********************************************************************/ 
#include "14443.h" 
/********************************************************************/ 
 
 
/* 变量定义 */ 
/********************************************************************/ 
unsigned char	completeUID[14]; 
unsigned char   UIDString[25]; 
/********************************************************************/ 
 
 
/********************************************************************* 
 * 函数名称:SelectCommand 
 * 功    能:Select命令 
 * 入口参数:select    串级 
 *           UID       唯一标识符 
 * 出口参数:无 
 * 返 回 值:无 
 ********************************************************************/ 
char SelectCommand(unsigned char select, unsigned char *UID) 
{ 
  unsigned char	j; 
  char  ret = 0; 
 
  buf[50] = ISOControl; 
  buf[51] = 0x08; 
  WriteSingle(&buf[50], 2); 
 
  for(j = 0; j < 5; j++) buf[j + 7] = *(UID + j); 
  buf[0] = 0x8f; 
  buf[1] = 0x91; 
  buf[2] = 0x3d; 
  buf[3] = 0x00; 
  buf[4] = 0x70; 
  buf[5] = select; 
  buf[6] = 0x70; 
 
  RAWwrite(buf, 12); 
 
  i_reg = 0x01; 
  RXTXstate = 1; 
 
  while(i_reg == 0x01) 
  { 
  } 
   
  i_reg = 0x01; 
 
  CounterSet(); 
  countValue = 0x2000;	 
  startCounter;		 
 
  while(i_reg == 0x01) 
  { 
  }						 
 
  if(!POLLING) 
  { 
    if(i_reg == 0xFF) 
    { 
      if((buf[1] & BIT2) == BIT2) 
      { 
        kputchar('('); 
	for(j = 1; j < RXTXstate; j++) 
	{ 
	  Put_byte(buf[j]); 
	} 
 
	kputchar(')'); 
	ret = 1; 
	goto FINISH; 
      } 
      else 
      { 
        kputchar('['); 
	for(j = 1; j < RXTXstate; j++) 
	{ 
	  Put_byte(buf[j]); 
	} 
 
        kputchar(']'); 
	ret = 0; 
	goto FINISH; 
      } 
    } 
    else if(i_reg == 0x02) 
    { 
      kputchar('['); 
      kputchar('z'); 
      kputchar(']'); 
    } 
    else if(i_reg == 0x00) 
    { 
      kputchar('['); 
      kputchar(']'); 
    } 
    else 
      ; 
  }						 
 
FINISH: 
  return(ret); 
}	 
 
 
/********************************************************************* 
 * 函数名称:AnticollisionLoopA 
 * 功    能:ISO14443A防碰撞循环 
 * 入口参数:select    串级 
 *           NVB       有效字节数量 
 *           UID       唯一标识符 
 * 出口参数:无 
 * 返 回 值:无 
 ********************************************************************/ 
void AnticollisionLoopA(unsigned char select, unsigned char NVB,  
                        unsigned char *UID) 
{ 
  unsigned char	i, lenght, newUID[4], more = 0; 
  unsigned char	NvBytes = 0, NvBits = 0, Xbits, found = 0; 
   
  buf[50] = ISOControl;			 
  buf[51] = 0x88; 
  WriteSingle(&buf[50], 2); 
 
  buf[0] = 0x1a; 
  buf[1] = 0x40; 
  WriteSingle(buf, 2); 
   
  RXErrorFlag = 0; 
  CollPoss = 0; 
 
  lenght = 5 + (NVB >> 4); 
  if((NVB & 0x0f) != 0x00) 
  { 
    lenght++; 
    NvBytes = (NVB >> 4) - 2;	 
    Xbits = NVB & 0x07;	 
 
    for(i = 0; i < Xbits; i++) 
    { 
      NvBits = NvBits << 1; 
      NvBits = NvBits + 1; 
    } 
  } 
 
  buf[0] = 0x8f;			 
  if(NVB == 0x70)			 
    buf[1] = 0x91;		 
  else 
    buf[1] = 0x90; 
  buf[2] = 0x3d; 
  buf[3] = 0x00; 
  buf[4] = NVB & 0xf0;	 
  if((NVB & 0x07) != 0x00) buf[4] |= ((NVB & 0x07) << 1) + 1; 
  buf[5] = select;			 
  buf[6] = NVB;				 
  buf[7] = *UID; 
  buf[8] = *(UID + 1); 
  buf[9] = *(UID + 2); 
  buf[10] = *(UID + 3); 
 
  RAWwrite(&buf[0], lenght); 
 
  RXTXstate = 1;				 
 
  i_reg = 0x01; 
  while(i_reg != 0x00) 
  { 
    CounterSet(); 
    countValue = count1ms * 10;	 
    startCounter;			 
    LPM0; 
  }	 
 
  i_reg = 0x01; 
  i = 0; 
  while((i_reg == 0x01) && (i < 2)) 
  {	 
    i++; 
    CounterSet(); 
    countValue = count1ms * 10;						 
    startCounter;								 
    LPM0; 
  } 
 
  if(RXErrorFlag == 0x02) i_reg = 0x02; 
 
  if(i_reg == 0xff) 
  { 
    if(!POLLING) 
    { 
      kputchar('('); 
      for(i = 1; i < 6; i++) Put_byte(buf[i]); 
      kputchar(')'); 
    } 
 
    switch(select) 
    { 
      case 0x93:									 
	if((buf[1] == 0x88) || (*UID == 0x88)) 
	{										 
	  if(NvBytes > 0) 
	  { 
	    for(i = 0; i < 4; i++) 
	    { 
	      if(i < (NvBytes - 1))  
                completeUID[i] = *(UID + i + 1); 
	      else if(i == (NvBytes - 1)) 
	        completeUID[i] = (buf[i + 2 - NvBytes] &~NvBits) | (*(UID + i + 1) & NvBits); 
	      else 
		completeUID[i] = buf[i + 2 - NvBytes]; 
	    }	 
	  } 
	  else 
	  { 
	    completeUID[0] = (buf[2] &~NvBits) | (*UID & NvBits); 
	    for(i = 0; i < 4; i++) 
	    { 
	      completeUID[i + 1] = buf[i + 3]; 
	    }								 
	  }									 
 
	  buf[1] = 0x88; 
	  for(i = 0; i < 4; i++) buf[i + 2] = completeUID[i]; 
 
	  SelectCommand(select, &buf[1]); 
	  NVB = 0x20; 
	  more = 1; 
	} 
	else 
	{										 
	  if(POLLING) 
	  { 
	    found = 1; 
	  } 
	  else 
	  { 
	    kputchar('['); 
	    if(NvBytes > 0) 
	    { 
	      for(i = 0; i < 4; i++) 
	      { 
	        if(i < (NvBytes - 1))	 
		  Put_byte(*(UID + i + 1));	 
		else if(i = (NvBytes - 1)) 
		  Put_byte((buf[i + 2 - NvBytes] &~NvBits) | (*(UID + i + 1) & NvBits)); 
		else 
		  Put_byte(buf[i + 2 - NvBytes]); 
	      }						 
	    } 
	    else 
	    { 
	      Put_byte((buf[1] &~NvBits) | (*UID & NvBits)); 
	      for(i = 0; i < 4; i++) 
	      { 
	        Put_byte(buf[i + 2]); 
	      }						 
	    }							 
 
            kputchar(']'); 
	  } 
	} 
 
	select = 0x95; 
	break; 
 
	case 0x95:								 
	  if(buf[1] == 0x88) 
	  { 
	    for(i = 0; i < 4; i++) 
	    { 
	      completeUID[i + 4] = buf[i + 2]; 
	    } 
 
	    SelectCommand(select, &buf[1]); 
	    more = 1; 
	  } 
	  else 
	  {			 
	    for(i = 0; i < 5; i++) 
	    { 
	      completeUID[i + 4] = buf[i + 1]; 
	    } 
 
	    if(POLLING) 
	    { 
	      found = 1;            
	    } 
	    else 
	    { 
	      kputchar('['); 
	      for(i = 0; i < 3; i++)		 
	        Put_byte(completeUID[i]); 
	      Put_byte(completeUID[3]);	 
 
	      for(i = 4; i < 8; i++)		 
	        Put_byte(completeUID[i]); 
	      Put_byte(completeUID[8]); 
	      kputchar(']'); 
	    } 
	  } 
 
	  select = 0x97; 
	  break; 
 
	case 0x97:						 
	  for(i = 0; i < 5; i++) 
	  {							 
	    completeUID[i + 8] = buf[i + 1]; 
	  } 
 
	  if(POLLING) 
	  { 
	    found = 1;              
	  } 
	  else 
	  { 
	    kputchar('['); 
	    for(i = 0; i < 3; i++)	 
	      Put_byte(completeUID[i]); 
	    Put_byte(completeUID[3]);	 
 
	    for(i = 4; i < 7; i++)		 
	      Put_byte(completeUID[i]); 
	    Put_byte(completeUID[7]);	 
 
	    for(i = 8; i < 12; i++)		 
	      Put_byte(completeUID[i]); 
	    Put_byte(completeUID[12]);	 
	    kputchar(']'); 
	  } 
	  break; 
    } 
  } 
  else if(i_reg == 0x02) 
  { 
    if(!POLLING) 
    { 
      kputchar('('); 
      kputchar('z'); 
      kputchar(')'); 
    } 
  } 
  else if(i_reg == 0x00) 
  { 
    if(!POLLING) 
    { 
      kputchar('('); 
      kputchar(')'); 
    } 
  } 
  else 
    ; 
 
  if(i_reg == 0x02) 
  {						 
    CollPoss++;			 
    for(i = 1; i < 5; i++) newUID[i - 1] = buf[i]; 
 
    CounterSet(); 
    countValue = count1ms * 2;	 
    startCounter;		 
    i_reg = 0x01; 
    while(i_reg == 0x01) 
    { 
    }					 
 
    AnticollisionLoopA(select, CollPoss, newUID);	 
  }	 
 
  if(more) 
  {	 
    AnticollisionLoopA(select, NVB, UID);	 
    if(POLLING) found = 1; 
  }	 
 
  if(found) 
  { 
    LEDtypeAON; 
    BEEP_ON; 
  } 
  else 
  { 
    LEDtypeAOFF;  
    BEEP_OFF; 
  } 
} 
 
 
/********************************************************************* 
 * 函数名称:AnticollisionSequenceA 
 * 功    能:ISO14443A防碰撞序列 
 * 入口参数:REQA   0为WUPA唤醒命令;否则为REQA命令 
 *                   
 * 出口参数:无 
 * 返 回 值:无 
 ********************************************************************/ 
void AnticollisionSequenceA(unsigned char REQA) 
{ 
  unsigned char	i, select = 0x93, NVB = 0x20; 
 
  buf[0] = ModulatorControl; 
  buf[1] = 0x21; 
  WriteSingle(buf, 2); 
 
  buf[0] = ISOControl; 
  buf[1] = 0x88; 
  WriteSingle(buf, 2); 
 
  if(REQA)  
    buf[5] = 0x26; 
  else 
    buf[5] = 0x52; 
 
  RequestCommand(&buf[0], 0x00, 0x0F, 1); 
  irqCLR; 
  irqON; 
 
  if(i_reg == 0xff || i_reg == 0x02) 
  { 
    for(i = 40; i < 45; i++) buf[i] = 0x00; 
    AnticollisionLoopA(select, NVB, &buf[40]); 
    if(POLLING)  
    { 
      LEDtypeAON; 
      BEEP_ON; 
      LCD_WriteString(0,5,"ISO14443A Found"); 
    } 
  } 
  else 
  { 
    LEDtypeAOFF; 
    BEEP_OFF; 
    LCD_WriteString(0,5,"");     
  } 
 
  buf[0] = ISOControl; 
  buf[1] = 0x08; 
  WriteSingle(buf, 2); 
  irqOFF; 
} 
 
 
/********************************************************************* 
 * 函数名称:Request14443A 
 * 功    能:ISO14443A请求命令 
 * 入口参数:pbuf     请求命令 
 *           lenght   请求命令长度 
 *           BitRate  比特率       
 * 出口参数:无 
 * 返 回 值:1表示成功执行;0表示发生错误 
 ********************************************************************/ 
unsigned char Request14443A(unsigned char *pbuf, unsigned char lenght,  
                            unsigned char BitRate) 
{ 
  unsigned char	index, j, command, RXBitRate, TXBitRate, reg[2]; 
 
  TXBitRate = ((BitRate >> 4) & 0x0F) + 0x08; 
  RXBitRate = (BitRate & 0x0F) + 0x08; 
 
  reg[0] = ISOControl; 
  reg[1] = TXBitRate; 
  WriteSingle(reg, 2); 
 
  RXTXstate = lenght; 
 
  *pbuf = 0x8f; 
  *(pbuf + 1) = 0x91; 
  *(pbuf + 2) = 0x3d; 
  *(pbuf + 3) = RXTXstate >> 4; 
  *(pbuf + 4) = RXTXstate << 4; 
 
  if(lenght > 12) lenght = 12; 
 
  RAWwrite(pbuf, lenght + 5); 
 
  irqCLR;		 
  irqON; 
 
  RXTXstate = RXTXstate - 12; 
  index = 18; 
 
  i_reg = 0x01; 
 
  while(RXTXstate > 0) 
  { 
    LPM0;						 
    if(RXTXstate > 9) 
    {							 
      lenght = 10;			 
    } 
    else if(RXTXstate < 1) 
    { 
      break;					 
    } 
    else 
    { 
      lenght = RXTXstate + 1;  
    }						 
 
    buf[index - 1] = FIFO;	 
    WriteCont(&buf[index - 1], lenght); 
    RXTXstate = RXTXstate - 9;	 
    index = index + 9; 
  }						 
 
  RXTXstate = 1;			 
  while(i_reg == 0x01) 
  { 
  } 
 
  reg[0] = ISOControl; 
  reg[1] = RXBitRate; 
  WriteSingle(reg, 2); 
 
  command = 0x16; 
  DirectCommand(&command); 
  command = 0x17; 
  DirectCommand(&command); 
 
  i_reg = 0x01; 
 
  CounterSet(); 
  countValue = 0xF000;	 
  startCounter;			 
 
  while(i_reg == 0x01) 
  { 
  }						 
 
  if(i_reg == 0xFF) 
  {						 
    kputchar('['); 
    for(j = 1; j < RXTXstate; j++) 
    { 
      Put_byte(buf[j]); 
    }					 
 
    kputchar(']'); 
    return(0); 
  } 
  else if(i_reg == 0x02) 
  {						 
    kputchar('['); 
    kputchar('z'); 
    kputchar(']'); 
    return(0); 
  } 
  else if(i_reg == 0x00) 
  {						 
    kputchar('['); 
    kputchar(']'); 
    return(1); 
  } 
  else 
    ; 
 
  irqOFF; 
  return(1); 
}	 
 
 
/********************************************************************* 
 * 函数名称:SlotMarkerCommand 
 * 功    能:ISO14443B的SlotMarker命令 
 * 入口参数:number     时隙号    
 * 出口参数:无 
 * 返 回 值:无 
 ********************************************************************/ 
void SlotMarkerCommand(unsigned char number) 
{ 
  buf[0] = 0x8f; 
  buf[1] = 0x91; 
  buf[2] = 0x3d; 
  buf[3] = 0x00; 
  buf[4] = 0x10; 
  RAWwrite(&buf[0], 5); 
 
  buf[5] = 0x3F; 
  buf[6] = (number << 4) | 0x05; 
  buf[7] = 0x00; 
	 
  i_reg = 0x01; 
	 
  RAWwrite(&buf[5], 3); 
 
  irqCLR; 
  irqON; 
 
  while(i_reg == 0x01) 
  { 
    CounterSet(); 
    countValue = 0x9c40; 
    startCounter; 
    LPM0; 
  } 
}	 
 
 
/********************************************************************* 
 * 函数名称:AnticollisionSequenceB 
 * 功    能:ISO14443B防碰撞序列 
 * 入口参数:command  命令 
 *           slots    时隙 
 * 出口参数:无 
 * 返 回 值:无 
 ********************************************************************/ 
void AnticollisionSequenceB(unsigned char command, unsigned char slots) 
{ 
  unsigned char	i, collision = 0x00, j, found = 0; 
  unsigned int	k = 0; 
 
  buf[0] = ModulatorControl; 
  buf[1] = 0x20; 
  WriteSingle(buf, 2); 
 
  RXErrorFlag = 0x00; 
 
  buf[0] = 0x8f; 
  buf[1] = 0x91; 
  buf[2] = 0x3d; 
  buf[3] = 0x00; 
  buf[4] = 0x30; 
  buf[5] = 0x05; 
  buf[6] = 0x00; 
 
 
  if(slots == 0x04) 
  { 
    EnableSlotCounter(); 
    buf[7] |= 0x08; 
  } 
 
  buf[7] = slots; 
 
  if(command == 0xB1) buf[7] |= 0x08; 
 
  i_reg = 0x01; 
 
  RAWwrite(&buf[0], 8); 
 
  irqCLR;						 
  irqON; 
 
  j = 0; 
  while((i_reg == 0x01) && (j < 2)) 
  { 
    j++; 
    CounterSet();			 
    countValue = 0x4E20;	 
    startCounter; 
    LPM0; 
  }						 
 
  i_reg = 0x01; 
 
  CounterSet();			 
  countValue = 0x4E20;	 
  startCounter; 
 
  for(i = 1; i < 17; i++) 
  { 
    RXTXstate = 1; 
 
    while(i_reg == 0x01) 
    {					 
      k++; 
      if(k == 0xFFF0) 
      { 
        i_reg = 0x00; 
	RXErrorFlag = 0x00; 
	break; 
      } 
    } 
 
    if(RXErrorFlag == 0x02) i_reg = RXErrorFlag; 
 
    if(i_reg == 0xFF) 
    {					 
      if(POLLING) 
      { 
	found = 1; 
      } 
      else 
      { 
        kputchar('['); 
	for(j = 1; j < RXTXstate; j++) Put_byte(buf[j]); 
	kputchar(']'); 
      } 
    } 
    else if(i_reg == 0x02) 
    {					 
      if(!POLLING) 
      { 
        kputchar('['); 
	kputchar('z'); 
        kputchar(']'); 
      } 
 
      collision = 0x01; 
    } 
    else if(i_reg == 0x00) 
    {					 
      if(!POLLING) 
      { 
        kputchar('['); 
	kputchar(']'); 
      } 
    } 
    else 
      ; 
 
    if((slots == 0x00) || (slots == 0x01) || (slots == 0x02) || ((slots == 0x04) && (i == 16))) break; 
 
    SlotMarkerCommand(i); 
 
    i_reg = 0x01; 
 
    if(!POLLING) 
    { 
      put_crlf(); 
    } 
  }						 
 
  if(slots == 0x04) DisableSlotCounter(); 
 
  irqOFF; 
 
  if(found) 
  { 
    LEDtypeBON; 
    BEEP_ON; 
    LCD_WriteString(0,7,"ISO14443B Found"); 
  } 
  else 
  { 
    LEDtypeBOFF; 
    BEEP_OFF; 
    LCD_WriteString(0,7,""); 
  } 
 
  if(collision != 0x00) AnticollisionSequenceB(0x20, 0x02); 
}