Windows 10中的串行端口缺少传入字节

时间:2019-09-11 12:27:55

标签: c# serial-port

我正在从发送启动命令后连续发送数据的串行端口读取数据。我正在使用1408000的极高波特率和2000的采样率。我必须以以下方式处理传入的数据:2个开始字节(0xAA,0x55​​),然后是68个字节的实际数据。 在Win 7中运行程序不是问题,但是在Win 10中运行它会导致某些字节丢失-有时我会得到例如只有20个字节的数据,有时我会得到72个(总是更改值)。我想念什么吗?

这是我的代码:

SerialPort m_serialPort = new System.IO.Ports.SerialPort("COM8");
private static System.Timers.Timer timer = new System.Timers.Timer();
private static ConcurrentQueue<List<byte>> incomingdataQueue = new ConcurrentQueue<List<byte>>();
private static readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
static bool isProcessing = false;
private static List<byte> sampleData = new List<byte>();

public Form1()
{
        InitializeComponent();

        timer.Interval = 250;//250ms
        timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        m_serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        SetComConnectParam("COM8");

        if (!ComOpen()){UpdateStatus("Problem!\n");}           

        init_System(gain, sample, trigger); // sends a signal to the port to init the system
        UpdateStatus("start data recording " + DateTime.Now.ToString());
        Start_Data(); // sends a signal to the port to start data processing
        timer.Start();
}

public void SetComConnectParam(string portName, int baudRate = 1408000)
{            
    m_serialPort.PortName = portName;
    m_serialPort.BaudRate = baudRate;
    m_serialPort.Parity = Parity.None;
    m_serialPort.DataBits = 8;
    m_serialPort.StopBits = StopBits.One;                     
}

private bool ComOpen()
{
    // Closing serial port if it is open
    if (m_serialPort != null && m_serialPort.IsOpen){m_serialPort.Close();}

    if (false == m_serialPort.IsOpen)
    {
        try
        {
            m_serialPort.Open();
            m_serialPort.DiscardInBuffer(); 
        }
        catch { return false; }
    }
    return true;
}

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort comport = sender as SerialPort;
    if (comport == null || comport.BytesToRead == 0 || !comport.IsOpen) { return; }

    int dataLength = comport.BytesToRead;
    byte[] buffer = new byte[dataLength];
    int nbrDataRead = comport.Read(buffer, 0, dataLength);
    if (nbrDataRead == 0) { return; }
    incomingdataQueue.Enqueue(buffer.Take(nbrDataRead).ToList());
}

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    if (incomingdataQueue.Count == 0) { return; }
    ProcessData();
}

private void ProcessData()
{
    int byteperdatasample = 68;
    if (incomingdataQueue.Count == 0) { return; }
    if (!locker.TryEnterWriteLock(100)) { return; }
    if (isProcessing)
    {
        locker.ExitWriteLock();
        return;
    }
    isProcessing = true;
    List<byte> currentData = new List<byte>();
    while (incomingdataQueue.Count > 0)
    {
        incomingdataQueue.TryDequeue(out currentData);
        for (int i = 0; i < currentData.Count; i++)
        {
            // problem: startseq is 0xAA, 0x55. 0xAA might be last entry in         currentData list and 0x55 might be first entry in next data list
            if (i == currentData.Count - 1 && currentData[i].Equals(170)) { startIndex = -99; startFound = false; }
            if (i == 0 && currentData[i].Equals(85))
            {
                if (startIndex.Equals(-99)){startFound = true;}
                else{startFound = false;}
            }
            if (i < currentData.Count - 1 && currentData[i].Equals(170) && currentData[i + 1].Equals(85))
            {
               startFound = true;
               startIndex = i;
            }
            if (startFound)
            {
                if (startIndex == -99){sampleData.RemoveAt(sampleData.Count - 1);}//remove latest item (first start item 0xaa was added in last currentData list)

                if (sampleData.Count == byteperdatasample)//
                {
                /* whole block of data processing */
                }
                else{//error}
            else
            {
                if (i != startIndex + 1){sampleData.Add(currentData[i]);}
            }
        }
    }
    isProcessing = false;
    locker.ExitWriteLock();
}

private void ButtonStop_Click(object sender, EventArgs e)
{
    Stop_Data();
    timer.Stop();
}

1 个答案:

答案 0 :(得分:0)

可以尝试不使用计时器 如果(incomingdataQueue.Count == 0){return; }                   Task.Run(()=> ProcessData());在DataReceivedHandler处理程序中。

 private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort comport = sender as SerialPort;
            if (comport == null || comport.BytesToRead == 0 || !comport.IsOpen) { return; }

            int dataLength = comport.BytesToRead;
            byte[] buffer = new byte[dataLength];
            int nbrDataRead = comport.Read(buffer, 0, dataLength);

            if (nbrDataRead == 0) { return; }
            incomingdataQueue.Enqueue(buffer.Take(nbrDataRead).ToList());

            if (incomingdataQueue.Count > 0) {
              Task.Run(()=>ProcessData());
           }
        }