
rfid14443卡卡号的读取实验.pdf
18页实验八 安卓系统 RFID 1444 卡卡号的读取 【实验目的】【实验目的】 1. 熟悉 RFID 应用协议; 2. 利用协议,可以在 windows 平台上编写读取 13.56M-ISO14443 标签的程序 【实验内容】【实验内容】 1. 熟悉 RfidTest 工程,了解程序的架构,以及程序中数据的处理 2. 利用 RFID 应用协议,实现 13.56M-ISO14443 卡的卡号的读取 【基础知识】【基础知识】 1. RFID 13.56M-ISO14443 应用协议 RFID 协议协议 v1.0 数据帧定义: Byte0 Byte1 Byte2 Byte3 Byte4 - Byte4+n Byte4+n+1 - Byte4+n+2 0x43 0xBC 帧长度 操作类型 命令字节 CRC-16 校验 Byte0:帧头 1, ‘C’的 ASCII 码 Byte1:帧头 2,Byte0 的反码 Byte2:Byte0 到 Byte4+n+2 的总字节数 Byte3:表示命令操作针对的模块 0x00:表示模块配置操作,配置当前使用的模块类型 0x01:表示 125K 操作 0x02:表示 13.56M-ISO14443 操作 0x03:表示 13.56M-ISO15693 操作 0x04:表示 900M 操作 0x05:表示 Zigbee1 操作 0x06:表示 Zigbee2 操作 0x0A:表示 GPRS 操作 0x0B:表示有源标签操作 0x0C:表示蓝牙操作 0x0D:表示 wifi 操作 0xFF:表示全部关闭操作 Byte4 - Byte4+n:命令字节(后面会对不同模块类型详细说明) Byte4+n+1 - Byte4+n+2:Byte0 到 Byte4+n 的两位 CRC-16 数据校验,高字节在前,低字节 在后,CRC-16 多项式:0x8408,初始值:0xFFFF 1、CRC-16 校验码的使用: 现选择最常用的 CRC-16 校验,说明它的使用方法。
根据 Modbus 协议,常规 485 通讯的信息发送形式如下: 地址 功能码 数据信息 校验码 1byte 1byte nbyte 2byte CRC 校验是前面几段数据内容的校验值,为一个 16 位数据,发送时,低 8 位在前,高 8 为 最后 例如:信息字段代码为: 1011001,校验字段为:1010 发送方:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10 信息字段 校验字段 接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相 等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则 信息正确 2、CRC-16 校验码计算方法: 常用查表法和计算法计算方法一般都是: (1) 、预置 1 个 16 位的寄存器为十六进制 FFFF(即全为 1) ,称此寄存器为 CRC 寄存器; (2) 、把第一个 8 位二进制数据(既通讯信息帧的第一个字节)与 16 位的 CRC 寄存器的低 8 位相异或,把结果放于 CRC 寄存器,高八位数据不变; (3) 、把 CRC 寄存器的内容右移一位(朝低位)用 0 填补最高位,并检查右移后的移出位; (4) 、如果移出位为 0:重复第 3 步(再次右移一位) ;如果移出位为 1,CRC 寄存器与多 项式 A001(1010 0000 0000 0001)进行异或; (5) 、重复步骤 3 和 4,直到右移 8 次,这样整个 8 位数据全部进行了处理; (6) 、重复步骤 2 到步骤 5,进行通讯信息帧下一个字节的处理; (7) 、将该通讯信息帧所有字节按上述步骤计算完成后,得到的 16 位 CRC 寄存器的高、低 字节进行交换; (8) 、最后得到的 CRC 寄存器内容即为:CRC 码。
以上计算步骤中的多项式 A001 是 8005 按位颠倒后的结果 3、 模块配置命令(操作类型为 0x00) 命令字节定义如下: :0x02(切换当前使用模块为 13.56M-ISO14443) :0x02 0x13 0x00(关闭天线) Byte1:0x13(命令字) Byte2:0x00(关闭) :0x02 0x13 0x01(开启天线) Byte1:0x13(命令字) Byte2:0x01(开启) :0x02 0x12 0x41 Byte1:0x12(命令字) Byte2:0x41(TypeA 为 0x41,TypeB 为 0x42) :0x02 0x02 0x26 Byte1:0x02(命令字) Byte2:0x26(RegMfOutSelect) :0x01 0x03 Byte1:0x03(命令字) :0x01 0x04 Byte1:0x04(命令字) :0x01 0x01 Byte1:0x01(命令字) :0x09 0x06 0x60 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF(下载密码 A) Byte1:0x06(命令字) Byte2:0x60 (密码 A 为 0x60,密码 B 为 0x61) Byte3:0x00(扇区 0) Byte4 – Byte9:0xFF 0xFF 0xFF 0xFF 0xFF 0xFF(密码) :0x04 0x05 0x60 0x01 0x04(校验密码 A) Byte1:0x05(命令字) Byte2:0x60 (密码 A 为 0x60,密码 B 为 0x61) Byte3:0x01(扇区 1) Byte4:0x04(RegFIFOLength = (Byte3)*4) :0x02 0x08 0x02(读取块 2 数据) Byte1:0x08(命令字) Byte2:0x02(块 2) :0x12 0x09 0x02 0x12 0x34 0x56 0x78 0x90 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00(写入块 2 数据) Byte1:0x09(命令字) Byte2:0x02(块 2) Byte3 – Byte19:0x12 0x34 0x56 0x78 0x90 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00(待写入的数据) :0x02 0x14 0x00(读取身份证卡号) Byte1:0x14(命令字) 0 while (iFirstPosition 5) { //读出一个数据包 byte[] Packet = new byte[PacketLen]; int i; for (i = 0; i 1) ^ Polynomial; } else { Preset_Value = (Preset_Value 1); } } } Preset_Value = ~Preset_Value; BytesFrame[BytesFrame.Length - 2] = (byte)((Preset_Value BytesFrame[BytesFrame.Length - 1] = (byte)(Preset_Value } //校验CRC public bool CheckCRC(byte[] BytesFrame) { int Preset_Value = 0xFFFF; int Polynomial = 0x8408; byte HigherCRC, LowerCRC; for (int i = 0; i 1) ^ Polynomial; } else { Preset_Value = (Preset_Value 1); } } } Preset_Value = ~Preset_Value; HigherCRC = (byte)((Preset_Value LowerCRC = (byte)(Preset_Value if (BytesFrame[BytesFrame.Length - 2] == HigherCRC else return false; } //寻卡 private void btnFindCard_Click(object sender, EventArgs e) { if (serialPort1.IsOpen) { byte[] bytesSend = new byte[3]; bytesSend[0] = 0x02; bytesSend[1] = 0x02; bytesSend[2] = 0x26; SendBytesData(EncapsulationFrame(DO_HF14443, bytesSend)); ShowInfo(“命令:寻卡“); } else ShowInfo(“提示:请先连接串口!“); } //防冲突 private void btnAntiCollision_Click(object sender, EventArgs e) { if (serialPort1.IsOpen) { byte[] bytesSend = new byte[2]; bytesSend[0] = 0x01; bytesSend[1] = 0x03; SendBytesData(EncapsulationFrame(DO_HF14443, bytesSend)); ShowInfo(“命令:防冲突“); } else ShowInfo(“提示:请先连接串口!“); } //关闭程序时关闭串口和时钟 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (serialPort1.IsOpen) { serialPort1.Close(); } if (DisposeData.Enabled == true) { DisposeData.Stop(); } } //Timer事件,每秒接收并处理一次串口的数据 private void DisposeData_Tick(object sender, EventArgs e) { SynReceiveData(); string strtemp = ““; for (int i = 0; i iRecDataLen; i++) { strtemp += string.Format(“{0:X2}“, byteRecBuff[i]); } //ShowInfo(strtemp); ScanBuffer(); } //处理数据包 public void DateDispose(byte[] Packet) { if (CheckCRC(Packet)) { if (Packet[0] == HigherHead for (int i = 0; i DataPacket.Length; i++) { DataPacket[i] = Packet[4 + i]; } switch (Packet[3]) { case DO_Switch: DisposeSwitch(DataPacket); break; //case DO_LF: // DisposeLF125K(DataPacket); // break; case DO_HF14443: DisposeHF14443(DataPacket); break; //case DO_HF15693: // DisposeHF15693(DataPacket); // break; //case DO_UHF: // DisposeUHF900M(DataPacket); // break; //case DO_ZIGBEE1: // break; //case DO_ZIGBEE2: //break; } } } } //切换命令返回解析 public void DisposeSwitch。
