我的串口连接了我的电脑的RFID读卡器。它使用RS485,所以我需要在发送和接收状态之间切换。通信帧包含头和CRC(CRC16 ccitt-Xmodem)。 在端口上每次写入后我都在等待答案,然后计算CRC,如果失败,再次请求帧。然后,如果一切正确处理它。
使用“简单”命令可以正常工作。 (请求固件版本,启用/禁用天线等。)。
使用重要的命令(登录阅读器的界面,配置它等等)我面对下一个:很少答案正确,最大延迟为5秒,但在大多数情况下,我在缓冲区上没有得到任何东西。我可以等几分钟,但什么都没有。
结论:如果我得到答案,它会在最初几秒内发生,如果我不能,我可以随时等待,但不会发生。
我的问题是:这可能是硬件故障,还是我想念软件中的某些东西?
这是发送&收到我的部分代码:
int size;
bool msg_ok = false;
do
{
int max_attemps = 50;
port.DtrEnable = true;
port.RtsEnable = false;
port.Write(fullMsg, 0, fullMsg.Length);
port.DtrEnable = false;
port.RtsEnable = true;
do
{
Thread.Sleep(200);
size = port.BytesToRead;
}while(size <= 3 && max_attemps-- > 0);
if(size > 3){
answer = new byte[size];
port.Read(answer, 0, size);
int end = answer.Length - 1; //Trim 0-s after end
while (answer[end] == 0)
--end;
int start = 0;
while (answer[start] == 0) //Trim 0-s before header
++start;
trimmed = new byte[(end - start) + 1];
Array.Copy(answer, start, trimmed, 0, (end - start) + 1);
checkSum = new byte[2];
checkSum = crc.ComputeChecksumBytes(trimmed, trimmed.Length); //Calculate crc
if (checkSum[0] == trimmed[trimmed.Length - 1] && checkSum[1] == trimmed[trimmed.Length - 2])
{
msg_ok = true; //If it's still false on the end, restart this whole block and request again, if it's true, I can send the answer for processing
}
} else {
Console.WriteLine("Timed out.");
}
}while(!msg_ok);
答案 0 :(得分:1)
当通过串行端口发送数据时,操作系统会在数据到达时对其进行缓冲。如果仅在其中一些数据到达时查询数据,您将获得部分数据包。在开始尝试解码之前,您需要继续阅读,直到收到完整数据包。否则你的解码将在数据包的前半部分失败,在下半部分失败,然后等待另一条永远不会发出的消息。
使用串口的最佳方法是订阅DataReceived event,因为这意味着当数据到达时 和 。这避免了不得不睡觉以试图解决时间问题。您仍然有时需要将几个接收数据块拼接在一起形成一个有效的数据包,因此您应该编写代码以保持读取并附加到接收缓冲区,直到它识别出有效的完整数据包。
除非串行线路另一端的设备非常不寻常,否则您也不需要翻转握手位 - 只需发送数据并等待回复即可。通过手动更改端口上的低电平状态,可能会将传输问题引入系统。
尝试从DataReceived事件页面(上面)中的示例代码开始,您应该有更可靠的结果。