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

C# 如何读取串行端口直到写入后立即超时?,c#,serial-port,cctalk,C#,Serial Port,Cctalk,我需要从串行端口向设备写入和读取数据。我测试了某些方法,首先,我使用SerialDataReceivedEventArgs接收数据,我觉得很难读取我需要定义发送where的命令的端口,因为该命令几乎有200个命令 我的第一种方法是使用:- private void ObjCom_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { if (!ObjCom.I

我需要从串行端口向设备写入和读取数据。我测试了某些方法,首先,我使用
SerialDataReceivedEventArgs
接收数据,我觉得很难读取我需要定义发送where的命令的端口,因为该命令几乎有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("-", " "));
        }
raiseeventsg
是一个委托事件,用于将当前信息传递给主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}";
    }
}
private long lngTickCount=Convert.ToInt64(1000L);
公共无效StartWritePort()
{
字节[]Cmd=null;
string strCmd=string.Empty;
字符串strMsg=null;
bool bCont=真;
长lngCurrent=0;
长lnnow=0;
尝试
{
RAISEEVENTSG(“开始写入端口”);
ObjCom.discardorBuffer();
ObjCom.DiscardInBuffer();
GetFullCommandByte(ref Cmd,Convert.ToByte(123));//使用返回和传递命令列表引用Cmd(各种命令集)
ObjCom.Write(Cmd,0,Cmd.Length);
strCmd=ByteArrayToString(Cmd);//将字节数组转换为十六进制字符串
RAISEEVENTMG(“发送:+strCmd”);
boolbtimeout=false;
lngCurrent=DateTime.Now.Ticks;
而(!bTimeout)
{
lnnow=DateTime.Now.Ticks;
如果(lngNow>(lngCurrent+(3*lngTickCount)))
{
bTimeout=true;
打破
}
}
lngCurrent=DateTime.Now.Ticks;
而(ObjCom.BytesToRead(lngCurrent+(1000*lngTickCount)))
{
bCont=假;
打破
}
}
如果(!bCont)
{
strMsg=“错误-超时命中”;
提高效率(strMsg);
返回;
}
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();
如果(TmpHex.Length==1)
{
strASCIIFull+=(“0”+TmpHex);
}
其他的
{
strASCIIFull+=(“”+TmpHex);
}
lngCurrent=DateTime.Now.Ticks;
而(ObjCom.BytesToRead(lngCurrent+(2*lngTickCount)))
{
bCont=假;
打破
}
}
Idx+=1;
}
}
RAISEEVENTSG(“Recv:+strASCIIFull”);
}
catch(System.Exception-ex)
{
字符串错误=$“StartWritePort.Message:{ex.Message}.StackTrace:{ex.StackTrace}上的异常”;
}
}
第二种方法的问题是,当我第二次调用此函数时,超时将被触发。但对于串行事件,它没有问题,超时协议设置为1秒。我的设备当前使用USB连接,没有转换器。设备的输入电缆为B型端口(类似于标准打印机端口)


是否有其他直接从端口读取的方法或对当前代码的任何改进?

您需要学习如何分层代码。目前,您有一个长函数,它尝试执行所有操作

如果您有几个较小的函数来执行特定的操作,例如读取或写入一大块信息,那么它将使您尝试执行的操作更简单

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

那么它可能简单到:

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