Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#-串行端口RS-485和通信限制_C#_Performance_Serial Port_Communication - Fatal编程技术网

c#-串行端口RS-485和通信限制

c#-串行端口RS-485和通信限制,c#,performance,serial-port,communication,C#,Performance,Serial Port,Communication,我正试图通过串行端口使用RS-485与设备通信。一切都很好,直到我们试图加强通信以测试卡的速度限制,然后奇怪的问题似乎发生了。我们基本上先发送一个以图像为参数的命令,然后再发送另一个显示该图像的命令。每次发出命令后,卡片都会回复说该命令得到了很好的响应。但我们很快就达到了极限,这张卡应该能处理更多的问题 所以我想知道,既然传输和接收是通过同一条线进行的,是否存在某种数据冲突?我应该等待接收所有数据吗?SerialDataReceivedEventHandler在这种情况下是否太慢,我是否应该在单

我正试图通过串行端口使用RS-485与设备通信。一切都很好,直到我们试图加强通信以测试卡的速度限制,然后奇怪的问题似乎发生了。我们基本上先发送一个以图像为参数的命令,然后再发送另一个显示该图像的命令。每次发出命令后,卡片都会回复说该命令得到了很好的响应。但我们很快就达到了极限,这张卡应该能处理更多的问题

所以我想知道,既然传输和接收是通过同一条线进行的,是否存在某种数据冲突?我应该等待接收所有数据吗?SerialDataReceivedEventHandler在这种情况下是否太慢,我是否应该在单独的线程中继续读取while true循环中的字节,并在收到完整消息后向其他线程发出信号

其他资料:

  • 我们已经有了通信协议:startdelimiter,data, CRC16,结束分隔符
  • 发送两个命令是我们的方式,不能更改
  • 波特率定义为115200
  • 工程师仍在处理卡中的程序,所以问题可能也在他这边
  • 英语不是我的第一语言,所以如果我不清楚,请尽管问……)
我认识到串行端口编程不是我的强项,我一直在尝试寻找某种包装器,但没有找到任何适合我需要的。如果有人向我求婚,那就太好了,或者有人知道可能会出什么问题。 无论如何,这里有一点编码:

线程发送帧:

    public void SendOne()
        {
            timerLast = Stopwatch.GetTimestamp();

            while (!Paused && conn.ClientConnState == Connexion.ConnectionState.Connected)
            {
                timerNow = Stopwatch.GetTimestamp();

                if ((timerNow - timerLast) / (double)Stopwatch.Frequency >= 1 / (double)fps)
                {
                    averageFPS.Add((int)((double)Stopwatch.Frequency / (timerNow - timerLast)) + 1);
                    if (averageFPS.Count > 10) averageFPS.RemoveAt(0);

                    timerLast = Stopwatch.GetTimestamp();

                    if (atFrame >= toSend.Count - 1)
                    {
                        atFrame = 0;
                        if (!isLoop)
                            Paused = true;
                    }


                    SendColorImage();
                }
}



  public void SendColorImage()
    {
        conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Request.SendImage, toSend[++atFrame]));
        WaitForResponse();
        conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Request.DisplayImage, VIP16.DisplayOnArg));
        WaitForResponse();
    }

    private void WaitForResponse()
    {
        Thread.Sleep(25);
    }
所以WaitForResponse()是至关重要的,因为如果我在卡应答之前发送另一个命令,它会发疯。虽然我不喜欢使用Thread.Sleep(),因为它不是很精确,而且它会将我的速度限制在20fps,如果我使用低于25ms的速度,崩溃的风险更大。所以我准备将线程更改为“读取字节直到收到整个消息”,并忽略DataReceivedEvent。。。只是想知道我是否完全偏离了轨道

太多了

更新1

首先感谢Brad和500-内部服务器错误!但我决定现在继续使用.NET串行端口,并提高Thread.Sleep的准确性(使用timebeginperiod)。我决定等待收到完整响应,并使用ManualResetEventSlim(速度)同步线程:

然后我将SendColorIMage更改为:

   public void SendColorImage()
    {
        conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Requetes.SendImage, toSend[++atFrame]));
        WaitForResponse();
        conn.Write(VIP16.bytesToVIP16(0x70C1, VIP16.Requetes.DisplayImage, VIP16.DisplayOnArg));
        WaitForResponse2();
    }

    private void WaitForResponse()
    {
        Connexion._waitHandle.Wait(100);
        Thread.Sleep(20);
    }

    private void WaitForResponse2()
    {
        Connexion._waitHandle.Wait(100);
        //Thread.Sleep(5);
    }
使用SerialDataReceiveDevenHandler调用:

    public void Recevoir(object sender, SerialDataReceivedEventArgs e)
    {
        if (!msg.IsIncomplete)
            msg = new Vip16Message();

        lock (locker)
        {
            if (sp.BytesToRead > 0)
            {
                byte[] byteMsg = new byte[sp.BytesToRead];
                sp.Read(byteMsg, 0, byteMsg.Length);
                msg.Insert(byteMsg);
            }
        }

        if (!msg.IsIncomplete)
        {
            _waitHandle.Set();
            if (MessageRecu != null)
                MessageRecu(msg.toByte());
        }
    }
所以我发现在执行第二个命令后,我不需要调用线程。根本不需要睡眠。。。在第一次之后,我需要睡眠至少20毫秒,这样卡才不会崩溃。所以我想这是卡需要接收/处理整个图像到像素的时候了。数据冲突不应该真的发生,因为我一直等到整个消息到达,这意味着问题不在我这边!是的p

几个指针:

  • 发送后,您需要等待传输缓冲区清空事件,然后再读取响应。它是非托管的,我不记得它是如何封装在托管端的——我们的RS485代码早于.NET comport组件

  • 您可以使用timeBeginPeriod(1)调用重新编程计时器芯片,以在Thread.Sleep()上获得1毫秒的分辨率

  • 值得一提的是,我们只在发送后短暂睡眠(1毫秒),然后进入一个读取循环,在该循环中,我们一直尝试从端口读取(再次尝试,读取尝试之间的延迟为1毫秒),直到收到完整响应(或者直到超时或重试计数器耗尽)

这是timeBeginPeriod的导入声明-我不认为它可以直接在.NET中获得(还没有?):


我希望这能有所帮助。

NET串行端口类一直让我头疼。在.NET4.0中它已经变得更好了,但是我仍然有问题,特别是USB适配器。我强烈推荐康普工作室。效果很好。你可以在这里得到一个免费的版本:没有铃铛和哨子作为完整的,但串行端口部分应该是所有你需要的。
    public void Recevoir(object sender, SerialDataReceivedEventArgs e)
    {
        if (!msg.IsIncomplete)
            msg = new Vip16Message();

        lock (locker)
        {
            if (sp.BytesToRead > 0)
            {
                byte[] byteMsg = new byte[sp.BytesToRead];
                sp.Read(byteMsg, 0, byteMsg.Length);
                msg.Insert(byteMsg);
            }
        }

        if (!msg.IsIncomplete)
        {
            _waitHandle.Set();
            if (MessageRecu != null)
                MessageRecu(msg.toByte());
        }
    }
[DllImport("winmm.dll")]
internal static extern uint timeBeginPeriod(uint period);