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

C# Windows 10中的串行端口缺少传入字节,c#,serial-port,C#,Serial Port,我正在从一个串行端口读取数据,该端口在发送start命令后连续发送数据。我工作的波特率非常高,为1408000,采样率为2000。我必须以以下方式处理传入数据:2个起始字节(0xAA,0x55),后跟68个字节的实际数据。 在Win 7中运行该程序不是问题,但在Win 10中运行该程序会导致丢失一些字节-有时我只得到20个字节的数据,有时我得到72个字节的数据(总是改变值)。我错过什么了吗 这是我的密码: SerialPort m_serialPort = new System.IO.Ports

我正在从一个串行端口读取数据,该端口在发送start命令后连续发送数据。我工作的波特率非常高,为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();
}
SerialPort m_SerialPort=new System.IO.port.SerialPort(“COM8”);
private static System.Timers.Timer Timer=新的System.Timers.Timer();
私有静态ConcurrentQueue incomingdataQueue=新ConcurrentQueue();
私有静态ReaderWriterLockSlim locker=new ReaderWriterLockSlim();
静态bool isProcessing=false;
私有静态列表sampleData=new List();
公共表格1()
{
初始化组件();
timer.Interval=250;//250ms
timer.appeased+=新的ElapsedEventHandler(timer\u appeased);
m_serialPort.DataReceived+=新的SerialDataReceivedEventHandler(DataReceivedHandler);
SetComConnectParam(“COM8”);
如果(!ComOpen()){UpdateStatus(“问题!\n”);}
init_系统(增益、采样、触发器);//向端口发送信号以初始化系统
UpdateStatus(“开始数据记录”+DateTime.Now.ToString());
Start_Data();//向端口发送信号以开始数据处理
timer.Start();
}
public void SetComConnectParam(字符串端口名,int波特率=1408000)
{            
m_serialPort.PortName=PortName;
m_serialPort.BaudRate=波特率;
m_serialPort.Parity=奇偶校验.None;
m_serialPort.DataBits=8;
m_serialPort.StopBits=StopBits.One;
}
二等兵布尔·科莫彭()
{
//关闭串行端口(如果打开)
如果(m_serialPort!=null&&m_serialPort.IsOpen){m_serialPort.Close()}
if(false==m_serialPort.IsOpen)
{
尝试
{
m_serialPort.Open();
m_serialPort.DiscardInBuffer();
}
catch{return false;}
}
返回true;
}
私有静态void DataReceivedHandler(对象发送方,SerialDataReceivedEventArgs e)
{
SerialPort comport=发送方作为SerialPort;
如果(comport==null | | comport.BytesToRead==0 | |!comport.IsOpen){return;}
int dataLength=comport.BytesToRead;
字节[]缓冲区=新字节[dataLength];
int nbrDataRead=comport.Read(缓冲区,0,数据长度);
如果(nbrDataRead==0){return;}
incomingdataQueue.Enqueue(buffer.Take(nbrDataRead.ToList());
}
无效计时器已过(对象发送器,ElapsedEventArgs e)
{
如果(incomingdataQueue.Count==0){return;}
ProcessData();
}
私有void ProcessData()
{
int byteperdatasample=68;
如果(incomingdataQueue.Count==0){return;}
如果(!locker.TryEnterWriteLock(100)){return;}
如果(i处理)
{
locker.ExitWriteLock();
返回;
}
isProcessing=true;
List currentData=新列表();
而(incomingdataQueue.Count>0)
{
incomingdataQueue.TryDequeue(OutCurrentData);
对于(int i=0;i
可以尝试在没有计时器的情况下工作 如果(incomingdataQueue.Count==0){return;}添加新任务 在DataReceivedHandler处理程序中运行(()=>ProcessData())

 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());
           }
        }

我猜是并发访问。您保护队列不受可重入访问的影响,但不受通过DataReceived和ProcessData进行的并发访问的影响。无关:如果端口实际上已打开,则关闭端口并立即打开很可能不起作用。操作系统需要一些时间来“清理”。乍一看,我甚至更加困惑。ProcessData似乎从未使用
incomingdataQueue
currentData
似乎从未添加到???
locker
似乎没有声明任何位置…我是否遗漏了什么?抱歉,我忘记复制这些行。添加了edit。我不确定是否必须保护这些行使用锁定器排队,因为它已经是ConcurrentQueue。这只是在旧计算机上意外工作,得益于它速度较慢,因此能够在调用事件处理程序之前接收更多字节。从根本上讲,您将读取多少字节是不可预测的,请确保继续调用read()直到你得到“消息”中的所有字节。故意使用低波特率来确信代码是正确的。