微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#串口通信高速通信时丢失字节

如何解决C#串口通信高速通信时丢失字节

我用 C# 创建了一个程序来接收来自我的 Teensy 4.1 uController 的高速数据。控制器只是每 1 微秒测量两个通道的电压,并通过 USB 将它们与时间戳一起发送。每次读取的数据包长度为 18 字节:4 字节(前导码)+ 1 字节(数据包长度)+ 1 字节(测量类型)+ 12 字节(所有信息:4 字节(时间戳)、4 字节(电压1)、 4 个字节(电压 2)。)。因此,我通过 USB 端口获得了 18 MBps。 Teensy 以 USB 2.0 的速度工作,因此限制为 480 Mbps / 8 = 60 MBps-所以这不是问题。

就目前而言,我只发送短时间的数据,比如 1 秒。

在我的 C# 程序中,我有两种方法显示这些数据:实时处理和被动模式。

  1. 在实时处理中,我在一个线程中读取数据并在另一个线程中处理它。在这方法中,我经常遗漏数据。

  2. 在被动模式下,我首先读取数据并将其存储在内存中,在采集时间结束后,在这种情况下为 1 秒,我的代码停止接收并开始处理数据。在这方法中,丢失数据的频率较低,有时没有丢失数据。

我已经分离了串口中断,从那以后丢失的数据要高得多。

我尝试了双缓冲技术,但仍然缺少数据。

我想解决这个丢失数据的问题。任何帮助将不胜感激。

我的代码是:

调用线程的方法

// Global variables
int passiveMode = 0;
int serialReadFlag  = 0;
BlockingCollection<byte> fifo_queue = null;
int TEENSYADC = 40;
int PREAMBLE = 85;
int PREAMBLE_COUNT=4;
//
         private void requestResponse()
         {
            serialReadFlag = 1;
            serialPortTeensy.DataReceived -= new SerialDataReceivedEventHandler(this.serialPortTeensy_DataReceived);
            serialPortTeensy.discardInBuffer();
            serialPortTeensy.discardOutBuffer();
            fifo_queue = new BlockingCollection<byte>();
            serialPortTeensy.WriteLine(RESPONSE + 1); //Request response from Teensy
            passiveMode = 0; // change to 1 to enable passive mode
            if (passiveMode == 0)
            {
                Thread readThread = new Thread(readTSnewDouble);
                readThread.Priority = ThreadPriority.Highest;
                readThread.Start();
                Thread processthread = new Thread(processtSnewDouble);
                processthread.Start();
            }
            else
            {
                Thread readThread = new Thread(readTSnewfast);
                readThread.Priority = ThreadPriority.Highest;
                readThread.Start();
            }
           } 
        private void readTSnew()
        {
            while (serialReadFlag > 0 || serialPortTeensy.BytesToRead > 0) // In Passive mode,a timer interrupt method will change the serialReadFlag to 0
            {
                try
                {
                    
                    int serialbytestoread = serialPortTeensy.BytesToRead;
                    byte[] buffer = new byte[serialbytestoread];
                    serialPortTeensy.Read(buffer,buffer.Length);
                    lock (serialLock)
                    {
                        foreach (var b in buffer)
                            fifo_queue.Add(b);
                    }
                }
                catch
                {

                }
                //Thread.Sleep(1); // If I turn this on,I miss much more data. Wanted to used this to accumulate more data in the serial buffer but then its somehow results in a loss of data.
            }
            
            if (passiveMode == 1) // Passive mode will process after full data is acquired.
            {
                Thread processthread = new Thread(processtSnew);
                processthread.Start();
            }
            
      }

处理数据的方法


            while (serialReadFlag > 0 || fifo_queue.Count > 0)
            {
                try
                {
                    while (fifo_queue.Count > 0)
                    {
                        int incoming_byte = 0;
                        long message1 = 0;
                        long message2 = 0;
                        long message3 = 0;
                        if (preamble_count < PREAMBLE_COUNT)
                        {
                            incoming_byte = fifo_queue.Take();
                        }

                        if (incoming_byte == PREAMBLE && preamble_count < PREAMBLE_COUNT)
                        {
                            preamble_count++;
                        }

                        else if (fifo_queue.Count > 0 && preamble_count == PREAMBLE_COUNT)
                        {
                            int len = fifo_queue.ElementAt(0);
                            if (fifo_queue.Count > len - 1)
                            {
                                len = fifo_queue.Take();
                                int type = fifo_queue.Take();
                                switch (type)
                                {
                                    case TEENSYADC:
                                            if (len == 2)
                                            {
                                                abortReponse();
                                                serialReadFlag = 0;
                                                serialPortTeensy.DataReceived += new SerialDataReceivedEventHandler(this.serialPortTeensy_DataReceived);
                                                break;
                                            }

                                            else
                                            {

                                                message1 = (long)fifo_queue.Take() << 24;
                                                message1 |= (long)fifo_queue.Take() << 16;
                                                message1 |= (long)fifo_queue.Take() << 8;
                                                message1 |= (long)fifo_queue.Take();

                                                message2 = (long)fifo_queue.Take() << 24;
                                                message2 |= (long)fifo_queue.Take() << 16;
                                                message2 |= (long)fifo_queue.Take() << 8;
                                                message2 |= (long)fifo_queue.Take();

                                                message3 = (long)fifo_queue.Take() << 24;
                                                message3 |= (long)fifo_queue.Take() << 16;
                                                message3 |= (long)fifo_queue.Take() << 8;
                                                message3 |= (long)fifo_queue.Take();

                                                servicepResponse(message1,message2,message3);

                                            }
                                        
                                        break;

                                    default:

                                        break;
                                }
                            }
                            preamble_count = 0;
                        }

                        else // not enough data received yet or garbage was received
                        {

                        }
                    }
                }
                catch 
                { }
            }
            fifo_queue.dispose();

在下面的图片中,您会看到我在实时模式下遗漏了一些数据,但在被动模式下没有。但请记住,数据有时也会在被动模式下丢失,但频率较低。

plot for the data received in the real-time mode

plot for the data received in the passive mode

我最近开始用 C# 编程,但我对执行线程安全操作的了解不多。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。