串口通用幫助類 SerialPortHelper


Demo

private readonly SerialPortHelper _spHelper;
ctor()
{
    _spHelper = new SerialPortHelper();
    _spHelper.DataReceivedEvent += SerialPort_DataReceivedEvent;
    _spHelper.Close();
    if (_spHelper.Init("COM1"))
    {
        _spHelper.SetStartIdentifier(new byte[] { 0xFA, 0xFA });
        _spHelper.SetEndIdentifier(new byte[] { 0xFB, 0xFB });
    }
    _spHelper.WriteXORCheck(command, WatchdogIdentifiers.讀取數據);
}
private void SerialPort_DataReceivedEvent(object sender, EventArgs e)
{       
    if (e is CustomSerialPortEventArgs arg)
    {
        var data = arg.Message;
        if (_spHelper.DataXORCheck(data))
        {
            switch (data[1])
            {
                case (byte)WatchdogIdentifiers.設置數據:
                    {
                    }
                    break;
                case (byte)WatchdogIdentifiers.讀取數據:
                    {
                    }
                    break;
            }
        }
    }
}

/// <summary>
/// 看門狗的通信標識
/// </summary>
internal enum WatchdogIdentifiers
{
    /// <summary>
    /// 1_1
    /// </summary>
    [Description("1")]
    設置數據 = 1,

    /// <summary>
    /// 1_2
    /// </summary>
    [Description("2")]
    讀取數據 = 2,
}

SerialPortHelper

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;


/// <summary>
/// 串行端口通信幫助類(有幀頭、幀尾檢測)
/// </summary>
internal class SerialPortHelper
{
    private readonly WeakEvent<EventArgs> _dataReceivedEvent = new WeakEvent<EventArgs>();

    /// <summary>
    /// 返回的消息數據弱事件
    /// </summary>
    public event EventHandler<EventArgs> DataReceivedEvent
    {
        add => _dataReceivedEvent.Add(value, value.Invoke);
        remove => _dataReceivedEvent.Remove(value);
    }

    public bool IsOpen => _serialPort != null && _serialPort.IsOpen;

    private CustomSerialPort _serialPort;

    /// <summary>
    /// 設置結尾標識符
    /// </summary>
    /// <param name="end"></param>
    public void SetEndIdentifier(byte[] end)
    {
        if (_serialPort != null)
        {
            _serialPort.EndIdentifier = end;
        }
    }

    /// <summary>
    /// 設置開始標識符
    /// </summary>
    /// <param name="start"></param>
    public void SetStartIdentifier(byte[] start)
    {
        if (_serialPort != null)
        {
            _serialPort.StartIdentifier = start;
        }
    }

    /// <summary>
    /// 延遲接收數據。
    /// 默認不設置幀頭、幀尾,根據實際情況判斷數據完整性!
    /// </summary>
    /// <param name="millionsecond">默認500(ms)</param>
    public void SetDelayDataReceived(int millionsecond = 500)
    {
        if (_serialPort != null)
        {
            _serialPort.StartIdentifier = null;
            _serialPort.EndIdentifier = null;
            _serialPort.DelayRecived(millionsecond);
        }
    }

    public bool Init(string portName, int baudRate = 9600, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One)
    {
        try
        {
            _serialPort = new CustomSerialPort(portName, baudRate, parity, dataBits, stopBits);
            _serialPort.DataReceivedEvent += SerialPort_DataReceivedEvent;
            return _serialPort.IsOpen;
        }
        catch (Exception ex)
        {
            LogFactory.GetInstance().Info(ex.Message);
        }
        return false;
    }

    /// <summary>
    /// 串口數據寫(帶數據異或校驗)
    /// </summary>
    /// <param name="data"></param>
    /// <param name="identifier">通信標識</param>
    /// <param name="version">版本</param>
    public void WriteXORCheck(byte[] data, WatchdogIdentifiers identifier, int version = 1)
    {
        if (IsOpen)
        {
            // 通信命令格式: 起始符(FA FA) + 版本 + 通信標識 + 數據長度(mod 255) + 數據內容(DATA) + 數據校驗 + 結束符(F5 F5)
            int len = data.Length % 255;
            byte xor = WSCommFunc.GetXOR(data);
            List<byte> tmp = new List<byte>(data.Length + 4) { (byte)version, (byte)identifier, (byte)len };
            tmp.AddRange(data);
            tmp.Add(xor);

            _serialPort.WritePort(tmp.ToArray());
        }
    }

    /// <summary>
    /// 獲取的數據異或校驗
    /// </summary>
    /// <param name=""></param>
    /// <returns>true校驗成功</returns>
    public bool DataXORCheck(byte[] data)
    {
        // 數據格式: 版本 + 通信標識 + 數據長度(mod 255) + 數據內容(DATA) + 數據校驗
        int length = data.Length;
        if (length <= 4)
        {
            return false;
        }
        // 長度不一致,異常數據
        if (data[2] != length - 4)
        {
            return false;
        }
        byte[] temp = new byte[length - 4];
        Array.Copy(data, 3, temp, 0, length - 4);
        byte xor = WSCommFunc.GetXOR(temp);
        return xor == data[length - 1];
    }

    /// <summary>
    /// 串口數據寫
    /// </summary>
    /// <param name="data"></param>
    public void Write(byte[] data)
    {
        if (IsOpen)
        {
            _serialPort.WritePort(data);
        }
    }

    /// <summary>
    /// 串口數據寫
    /// </summary>
    /// <param name="data"></param>
    public void Write(string data)
    {
        if (IsOpen)
        {
            _serialPort.WritePort(data);
        }
    }

    public void Close()
    {
        if (_serialPort != null)
        {
            _serialPort.DataReceivedEvent -= SerialPort_DataReceivedEvent;
            _serialPort.Close();
            _serialPort = null;
        }
    }

    private void SerialPort_DataReceivedEvent(object sender, EventArgs e)
    {
        _dataReceivedEvent.Invoke(this, e);
    }
}

其中,CustomSerialPort是一般串口通信的基本功能,可自行實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM