使用我正在使用的读卡器,检索MIFARE卡序列号的协议如下:
Mifare防撞,
0x0202
:
功能卡防冲击
格式aa bb 05 00 00 00 02 02 00
回复aa bb 0a 00 52 51 02 02 00 46 ff a6 b8 a4
46 ff a6 b8
是上述响应中的卡序列号。
我在C#中实现此协议如下:
private SerialPort _serialPort = new SerialPort();
private string _receivedData = null;
public MifareCardReader(string comPort, int baudRate)
{
_serialPort = new SerialPort();
_serialPort.PortName = comPort;
_serialPort.BaudRate = baudRate;
_serialPort.DataBits = 8;
_serialPort.Parity = Parity.None;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
_serialPort.Open();
// Add event
_serialPort.DataReceived += SerialPort_DataReceived;
}
public string MifareAnticollision()
{
if (_serialPort != null && _serialPort.IsOpen)
{
string message = "AABB050000000202000D";
byte[] data = StringToByteArray(message);
_serialPort.Write(data, 0, data.Length);
}
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
_receivedData += _serialPort.ReadExisting();
byte[] data = Encoding.ASCII.GetBytes(receivedData);
if (data.Length >= 9)
{
if (data[8] == 0) // OK
{
// Response data is complete
if (data.Length == 14)
{
StringBuilder hex = new StringBuilder(8);
hex.AppendFormat("{0:X2}", data[9]);
hex.AppendFormat("{0:X2}", data[10]);
hex.AppendFormat("{0:X2}", data[11]);
hex.AppendFormat("{0:X2}", data[12]);
string cardID = hex.ToString();
_receivedData = string.Empty;
}
}
else // fail
{
_receivedData = string.Empty;
}
}
}
我使用3种不同的MIFARE卡进行了测试,但输出并不是我的预期:
3F463F3F
,预计:974682D6
3F450B3F
,预计:EA450B91
070D3F3F
,预计:070DEBD6
我需要更改什么才能获得正确的输出?
答案 0 :(得分:1)
您遇到的问题似乎是将值0x7F
以上的字节替换为0x3F
(问号(“?”)字符)。即只有7位值正确显示,第8位设置的值变为“?” (0x3F
)。例如。对于卡1,974682D6
被“收到”为3F463F3F
,因为0x97
,0x82
和0xD6
的第8位已设置。
此问题的根源是您使用ReadExisting()
方法从串行端口读取字符串值。默认情况下,ReadExisting()
从串行端口读取字节,使用ASCII编码(System.Text.ASCIIEncoding
)进行转换,并返回结果字符串。然后,您接受该字符串并将其转换回字节数组(再次使用ASCII编码)。
有问题的步骤是使用System.Text.ASCIIEncoding
/ Encoding.ASCII
进行的转化。 documentation说:
由于ASCII是7位编码,因此ASCII字符仅限于最低128 个Unicode字符,从U + 0000到U + 007F。在执行编码操作之前, [...] 该范围之外的字符被问号(?)替换。
因此,您应该使用Read()
或ReadByte()
方法将字节直接读入字节数组。例如。与
byte[] buffer = new byte[_serialPort.ReadBufferSize];
int bytesRead = _serialPort.Read(buffer, 0, buffer.Length);