如何读取串行端口,直到写入后立即超时?

时间:2018-07-06 07:54:42

标签: c# serial-port cctalk

我需要从串行端口向我的设备写入和读取数据。我已经测试了某种方法,首先,我使用SerialDataReceivedEventArgs接收数据,并且我觉得很难读取需要定义命令的端口,因为该命令几乎包含200条命令。

我的第一种方法是使用:-

private void ObjCom_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            if (!ObjCom.IsOpen) return;
            byte[] data = new byte[ObjCom.BytesToRead];
            ObjCom.Read(data, 0, data.Length);
            RaiseEventMsg("Buffer String: " + BitConverter.ToString(data).Replace("-", " "));
        }

RaiseEventMsg是一个委托事件,用于将当前信息传递到主UI。第二种方法是:-

private long lngTickCount = Convert.ToInt64(1000L);
public void StartWriteToPort()
{
    byte[] Cmd = null;
    string strCmd = string.Empty;
    string strMsg = null;
    bool bCont = true;
    long lngCurrent = 0;
    long lngNow = 0;
    try
    {
        RaiseEventMsg("Start Write To Port");
        ObjCom.DiscardOutBuffer();
        ObjCom.DiscardInBuffer();

        GetFullCommandByte(ref Cmd, Convert.ToByte(123)); // Referencing Cmd with return and pass Command List(various set of command)
        ObjCom.Write(Cmd, 0, Cmd.Length);
        strCmd = ByteArrayToString(Cmd); // Convert byte array to Hex string
        RaiseEventMsg("Send: " + strCmd);
        bool bTimeout = false;
        lngCurrent = DateTime.Now.Ticks;
        while (!bTimeout)
        {
            lngNow = DateTime.Now.Ticks;
            if (lngNow > (lngCurrent + (3 * lngTickCount)))
            {
                bTimeout = true;
                break;
            }
        }

        lngCurrent = DateTime.Now.Ticks;
        while (ObjCom.BytesToRead <= 0)
        {
            lngNow = DateTime.Now.Ticks;
            if (lngNow > (lngCurrent + (1000 * lngTickCount)))
            {
                bCont = false;
                break;
            }
        }
        if (!bCont)
        {
            strMsg = "Error - Timeout Hit";
            RaiseEventMsg(strMsg);
            return;
        }

        int Idx = 0;
        string strASCIIFull = string.Empty;
        if ((ObjCom.BytesToRead > 0) & (bCont == true))
        {
            while (ObjCom.BytesToRead > 0)
            {
                var strASCII = ObjCom.ReadByte();
                var TmpHex = System.Convert.ToString(strASCII, 16).ToUpper();
                if (TmpHex.Length == 1)
                {
                    strASCIIFull += (" 0" + TmpHex);
                }
                else
                {
                    strASCIIFull += (" " + TmpHex);
                }
                lngCurrent = DateTime.Now.Ticks;
                while (ObjCom.BytesToRead <= 0)
                {
                    lngNow = DateTime.Now.Ticks;
                    if (lngNow > (lngCurrent + (2 * lngTickCount)))
                    {
                        bCont = false;
                        break;
                    }
                }
                Idx += 1;
            }
        }

        RaiseEventMsg("Recv: " + strASCIIFull);
    }
    catch (System.Exception ex)
    {
        string error = $"Exception on StartWriteToPort. Message: {ex.Message}. StackTrace: {ex.StackTrace}";
    }
}

第二种方法的问题是当我第二次调用此函数时,超时将达到。但是对于串行事件,它没有问题,超时协议设置为1秒。我的设备当前使用不带转换器的USB连接。设备的输入电缆为B型端口(如标准打印机端口)。

还有其他直接从端口读取信息的方式,还是对当前代码进行了任何改进?

1 个答案:

答案 0 :(得分:0)

您需要学习如何对代码进行分层。目前,您有一个长函数可以尝试完成所有操作。

如果您有几个较小的函数来完成特定功能,例如读取或写入大量信息,那么它将使您尝试做的事情变得更简单。

例如,串行通信通常具有某种协议,该协议封装了信息包的存储方式。假设协议为“”,则您知道每个数据包均以STX字节(0x01),长度字节开头,该字节告诉您该段中有多少字节,并且末尾必须有一个ETX字节(0x02)。您可以编写一个返回字节数组的函数,因为该函数将解释流并提取相关部分。

然后它可能很简单:

var packet1 = ReadPacket();
WritePacket(outputData);
var packet2 = ReadPacket();