C# SerialPort 使用DataReceived接口利用空閒中斷原理接收完整一幀數據

說明

  • 使用SerialPort類
  • 使用SerialPort.DataReceived 接收事件
  • DataReceived事件觸發無規律,不可作爲一幀數據的判斷
  • 數據接收也可使用單獨一個線程輪詢判斷,判斷更爲精確,但是要完全佔用一個線程,無堵塞,費資源。
  • 歡迎補充指導

開啓串口

SerialPort mySerialPort;//本地串口
mySerialPort = new SerialPort(comName);
mySerialPort.BaudRate = (int)dr.baud;//波特率
mySerialPort.DataBits = Convert.ToInt32(dr.databits);//數據位
mySerialPort.StopBits = (StopBits)Convert.ToInt32(dr.stopbits);//停止位
mySerialPort.Parity = (Parity)Enum.Parse(typeof(Parity), dr.parity);//校驗位
mySerialPort.WriteTimeout = 500;
LocalPort localport = new LocalPort(mySerialPort);
if (mySerialPort.IsOpen == false)
{
    Console.Write("open " + comName + " Error.\r\n");
    return response; ;
}
else
{
    localport.port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(ReceiveFromDevice);//打開成功則創建接收數據事件
    localport.LocalPortName = comName;
    localportList.Add(comName, localport);
    Console.Write("open " + comName + " Ok.\r\n");

}

串口接收事件

接收到數據後使用委託處理,更爲高效,也防止堵塞串口接收數據事件

//本地串口事件  接收來自設備發向本地串口的數據
private static void ReceiveFromDevice(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort serialPort = (SerialPort)sender;

    foreach (string key in localportList.Keys)
    {
        if (serialPort.PortName == key)
        {
            LSPReceiveDelegate lsprd = new LSPReceiveDelegate(Receive);
            lsprd(localportList[key]);
        }
    }        
}    

數據處理判斷

使用類似空閒中斷方法區分一幀數據,對緩存數據大小也做了限制,同時對最後一組數據做了定時器判斷。

public static void Receive(LocalPort localPort)
{
    try
    {
        SerialPort LP = localPort.port;
        int revcount_new = LP.BytesToRead;
        TimeSpan span;
        int oneByteTime = 0;
        if (LP.Parity == Parity.None)
            oneByteTime = 1000000 / (LP.BaudRate / 10);
        else
            oneByteTime = 1000000 / (LP.BaudRate / 11);
        int diffCount = 0;
        try
        {
            if (localPort.isNewFrame)
                localPort.dt = DateTime.Now;
            DateTime dt = DateTime.Now;
            span = dt - localPort.dt;
            localPort.dt = dt;
            diffCount = revcount_new - localPort.revcount;
            localPort.revcount = revcount_new;
            if (span.Ticks > ((diffCount + 3) * oneByteTime * 10))
            {
                byte[] recvBytes = new byte[LP.BytesToRead];
                LP.Read(recvBytes, 0, recvBytes.Length);
                //string recvData = LP.ReadExisting();
                localPort.revcount = 0;
                SendToCloudDelegate stcd = SendToCloud;
                stcd("receive", LP.PortName, null, ByteToHexStr(recvBytes));
                localPort.isNewFrame = true;
            }
            else if (localPort.revcount > 2048)
            {
                byte[] recvBytes = new byte[LP.BytesToRead];
                LP.Read(recvBytes, 0, recvBytes.Length);
                //string recvData = LP.ReadExisting();
                localPort.revcount = 0;
                SendToCloudDelegate stcd = SendToCloud;
                stcd("receive", LP.PortName, null, ByteToHexStr(recvBytes));
                localPort.isNewFrame = true;
            }
            else
            {
                localPort.isNewFrame = false;
                try
                {
                    localPort.timer.Stop();
                    localPort.timer.Close();
                }
                catch
                { }
                localPort.timer = new System.Timers.Timer(10);
                localPort.timer.Elapsed += new System.Timers.ElapsedEventHandler(LSPTimeOut); //到達時間的時候執行事件;   
                localPort.timer.AutoReset = false;   //設置是執行一次(false)還是一直執行(true);   
                localPort.timer.Enabled = true;     //是否執行System.Timers.Timer.Elapsed事件;
                localPort.timer.Start();
            }
        }
        catch
        {
            Console.WriteLine(LP.PortName + "closed!");
            SendToProcess(LP.PortName + "closed!");
        }


    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
    //}

}

使用該方法可以有效區分接收一幀數據,但是也存在弊端。如最後一幀數據會有一個定時器定時的時間延時,如果數據包發送比較緩慢,每一幀數據都存在定時器那個時間的延時。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章