我正在使用串行端口与远程诊断设备进行通信。SerialPort.DataReceived重复订阅/取消订阅
来自远程设备的响应长度因命令而异,但会提前知道。所以,目前我发送命令并等待接收到所需数量的响应字节。
无论何时我没有主动请求数据,我都会订阅'SerialPort.DataReceived'事件。这个事件的处理程序只是简单地将任何'主动'收到的数据转储到日志中(通常只有在远程设备意外重启时才会收到未经请求的数据,等等)。
在某些情况下,我想以大约60Hz的速率发送命令。
我的问题是,每次我调用我的'SendCommand'方法来主动请求数据时,是否最好取消订阅/订阅'SerialPort.DataReceived'事件,还是应该单独保留事件订阅,并且只需切换布尔型' TransferInProgress'标志DataReceived处理程序可用于在我主动请求时忽略传入数据?
下面是当前实现:
public virtual bool SendCommand(byte[] command, ref byte[] response) {
try {
TransferInProgress = true;
OnTransferStarted();
// temporarily unsubscribe since we're actively soliciting data
_port.DataReceived -=
new SerialDataReceivedEventHandler(SerialPort_DataReceived);
_port.DiscardInBuffer();
_port.Write(command, 0, command.Length);
OnCommandSent(command);
// read the requested number of response bytes
int responseBytesRead = 0;
while (responseBytesRead < response.Length) {
responseBytesRead +=
_port.Read(response, responseBytesRead, (response.Length - responseBytesRead));
}
OnCommandResponseReceived(response);
return true;
}
catch (Exception ex) {
OnCommandSendFailed(ex.Message);
return false;
}
finally {
_port.DataReceived +=
new SerialDataReceivedEventHandler(SerialPort_DataReceived);
OnTransferComplete();
TransferInProgress = false;
}
}
-Trevor
我喜欢使用队列来跟踪命令的想法,但我想知道如何能够检测未经请求的数据?我如何能够确定远程设备是否使用此方法在命令之间触发了几个字节? (注意:远程设备偶尔会重置自身并发送一些“启动”类型的字节,不幸的是,我无法控制它)。 – user158485 2009-08-18 16:48:18
您仍然会在您的数据接收处理程序中检测到未经请求的数据,但您会知道它是未经请求的,因为您的“SentCommandsQueue”中没有命令。 我在串口通信中遇到了类似的问题,你必须缓冲你接收到的数据,并将解出重置消息的答案拼凑在一起。一旦你有完整的回应,从你的队列中删除命令。由于重置字节似乎对序列的开头有某种签名,因此您应该能够轻松解析它们。 – nathan 2009-08-18 16:57:44
我想我可以实现像这样的东西。我唯一的预留是复位字节并不总是相同的(按顺序或数量),所以如果在正常命令之间接收到复位数据,最终可能会产生意外偏移。这就是说,我相信这个特殊的串口设备有一个选项来启用命令回显。在解析响应数组时,我可以使用echo作为标识头。 – user158485 2009-08-18 17:59:14