c# 串口SerialPort

创建SerialPortFun类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;
using LogSpace;

namespace SerialPortSpace
{
    public class SerialPortFun
    {
        /// <summary>
        /// 串口及串口缓存数据
        /// </summary>
        public static List<ComPort> LstComPort = new List<ComPort>();

        /// <summary>
        /// 是否在进行串口结束操作
        /// </summary>
        public static bool PortIsCloseing = false;

        /// <summary>
        /// 初始化串口,并返回当前串口的结构
        /// </summary>
        /// <param name="Port"></param>
        /// <param name="PortNo"></param>
        /// <param name="BaudRate"></param>
        /// <param name="ReciveData"></param>
        public static ComPort InitSerialPort(SerialPort Port, string PortNo, int BaudRate, BagStruct CurBagStruct, string StartStr, string EndStr, string PortNameDesc, string PortRemark)
        {
            Port.PortName = PortNo;
            Port.BaudRate = BaudRate;
            Port.DataBits = 8;
            Port.Parity = Parity.None;
            Port.StopBits = StopBits.One;
            Port.NewLine = "
";
            Port.WriteTimeout = 5000;
            Port.ReadTimeout = 5000;
            Port.Handshake = Handshake.None;
            Port.ReceivedBytesThreshold = 1;
            Port.RtsEnable = true;
            Port.DataReceived += Port_DataReceived;//定义接收数据事件

            ComPort PortItem = new ComPort();
            PortItem.Port = Port;
            PortItem.PortRealName = PortNameDesc;
            PortItem.PortDesc = PortRemark;
            PortItem.PortIsRcving = false;
            PortItem.LastRebackTime = DateTime.Now;
            PortItem.RcvBag = CurBagStruct;
            PortItem.StartStr = StartStr;
            PortItem.EndStr = EndStr;
            PortItem.SendOrder = new List<string>();

            PortItem.RcvData = string.Empty;
            PortItem.RcvLst = new List<PortReciveDataItem>();
            if (LstComPort.Count(c => c.Port == Port) > 0)
            {
                LstComPort.RemoveAll(c => c.Port == Port);
            }
            LstComPort.Add(PortItem);
            return PortItem;
        }
        /// <summary>
        /// 定义数据包中每项的开始位置及所占字节数
        /// </summary>
        /// <param name="StartPosition"></param>
        /// <param name="Length"></param>
        /// <returns></returns>
        public static BagItemPosition SetBagItemPosition(int StartPosition, int Length)
        {
            BagItemPosition Item = new BagItemPosition();
            Item.StartPosition = StartPosition;
            Item.Length = Length;
            return Item;
        }

        /// <summary>
        /// 定义返回数据包结构
        /// </summary>
        /// <param name="ByteOrder">字节顺序约定 0--高字节在前,低字节在后,1--高字节在后,低字节在前</param>
        /// <param name="HeadItem">包头所占字节数</param>
        /// <param name="HeadItem">命令所占字节数</param>
        /// <param name="OthItem">其他位总共占字节数</param>
        /// <param name="DataLenItem">数据长度位所占字节数</param>
        /// <param name="VerItem">校验位所占字节数</param>
        /// <param name="EndItem">包尾所占字节数</param>
        /// <returns></returns>
        public static BagStruct SetBagStruct(int ByteOrder, BagItemPosition HeadItem, BagItemPosition CmdItem, BagItemPosition OthItem, BagItemPosition DataLenItem, int RealDataItem, int VerItem, int EndItem)
        {
            BagStruct CurRcvBagStruct = new BagStruct();
            CurRcvBagStruct.ByteOrder = ByteOrder;
            CurRcvBagStruct.Head = HeadItem;
            CurRcvBagStruct.Cmd = CmdItem;
            CurRcvBagStruct.Other = OthItem;
            CurRcvBagStruct.DataLen = DataLenItem;
            CurRcvBagStruct.RealDataPos = RealDataItem;
            CurRcvBagStruct.VerifyLen = VerItem;
            CurRcvBagStruct.EndLen = EndItem;
            return CurRcvBagStruct;
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="PortName"></param>
        public static void OpenSerialPort(SerialPort Port)
        {
            if (!Port.IsOpen)
            {
                Port.Open();
            }
        }
       
        /// <summary>
        /// 发送串口数据
        /// </summary>
        /// <param name="Port"></param>
        /// <param name="Data"></param>
        public static bool SetPortData(SerialPort Port, string Data)
        {
            bool CurSendFlag = false;
            if (Port.IsOpen)
            {
                byte[] buf = strToHexByte(Data);
                Port.Write(buf, 0, buf.Length);
                CurSendFlag = true;
            }
            return CurSendFlag;
        }

        #region 接收串口应答包

        /// <summary>
        /// 接收串口应答包
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (PortIsCloseing)
            {
                return;
            }
            SerialPort port = sender as SerialPort;
            DateTime CurTime = DateTime.Now;
            string RcvData = string.Empty;
            if (LstComPort != null)
            {
                if (LstComPort.Count(c => c.Port.PortName == port.PortName) > 0)
                {
                    ComPort comPort = LstComPort.Find(c => c.Port.PortName == port.PortName);
                    try
                    {
                        Log.WriteLogToLocal(CurTime + "接收前" + comPort.PortRealName + "数据包临时数据:
" + comPort.RcvData + "
------------------------
", "Log\IBO_LOG", comPort.PortDesc + "_Receive");
                        RcvData = comPort.RcvData;
                        comPort.PortIsRcving = true;//正在接收串口数据
                        StringBuilder CurRcvData = new StringBuilder();
                        if (port.IsOpen && port.BytesToRead != 0)
                        {
                            while (port.BytesToRead != 0)
                            {
                                byte[] recvBytes = new byte[port.BytesToRead];
                                int bytes = port.Read(recvBytes, 0, recvBytes.Length);
                                if (recvBytes.Length != 0)
                                {
                                    foreach (byte b in recvBytes)
                                    {
                                        CurRcvData.Append(b.ToString("X2") + " ");
                                    }
                                }
                                //Thread.Sleep(20);
                            }
                            Log.WriteLogToLocal(CurTime + "接收" + comPort.PortRealName + "原始数据:
" + CurRcvData + "
------------------------
", "Log\IBO_LOG", comPort.PortDesc + "_Receive");
                            RcvData += CurRcvData;
                            CurRcvData.Clear();
                            //接收到的数据进行处理,并存储在串口对应的接收队列中
                            //SerialPortFun.DealPortData(comPort, RcvData, CurTime);
                            SerialPortFun.ConcatFullBag(comPort, comPort.RcvBag, RcvData, CurTime);
                            comPort.LastRebackTime = CurTime;
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.WriteLogToLocal(CurTime + "接收" + comPort.PortRealName + "串口数据(" + RcvData + ")错误:(" + ex.Message+")"+ex.StackTrace + "
", "Log\IBO_LOG\ErrorLog", comPort.PortDesc + "_Receive");
                    }
                    finally
                    {
                        comPort.PortIsRcving = false;//接收串口数据完毕
                    }
                }
            }
        }

        #endregion
        /// <summary>
        /// 接收到的数据进行处理,并存储在串口对应的接收队列中
        /// </summary>
        /// <param name="port"></param>
        /// <param name="Struct"></param>
        /// <param name="CurRcvData"></param>
        /// <param name="CurTime"></param>
        public static void ConcatFullBag(ComPort port, BagStruct Struct, string CurRcvData, DateTime CurTime)
        {
            Log.WriteLogToLocal(CurTime + "数据包处理" + port.PortRealName + "原始数据:
" + CurRcvData + "
------------------------
", "Log\IBO_LOG", port.PortDesc + "_Receive");
            string temp = CurRcvData;
            while (true)
            {
                //校验包头,包尾
                if (!temp.StartsWith(port.StartStr))
                {
                    int index = temp.IndexOf(port.StartStr);
                    if (index == -1)
                        temp = "";
                    else
                        temp = temp.Remove(0, index);
                }
                if (temp.Length > 0)
                {
                    int NoDataBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;
                    int BagDataLen = 0;
                    if (temp.Length > (Struct.DataLen.StartPosition * 3 + Struct.DataLen.Length * 3))
                    {
                        #region 获取数据包的业务数据长度
                        BagDataLen = GetBagDataLen(Struct, temp);
                        //string CurDataLen = "";
                        //string CurDataLenOrg = temp.Substring(Struct.DataLen.StartPosition * 3, Struct.DataLen.Length * 3);
                        //if (Struct.ByteOrder == 1)//高字节在后,低字节在前
                        //{
                        //    CurDataLen = ReverseStr(CurDataLenOrg, 2);
                        //    BagDataLen = Convert.ToInt32(CurDataLen, 16);//16进制
                        //}
                        //else
                        //{
                        //    CurDataLen = CurDataLenOrg;
                        //    BagDataLen = Convert.ToInt32(CurDataLen, 10);//华气特殊 10进制
                        //}
                        #endregion
                    }
                    if (BagDataLen > 0 && temp.Length / 3 >= NoDataBagLen + BagDataLen)
                    {
                        string FullBag = temp.Substring(0, (NoDataBagLen + BagDataLen) * 3);
                        BagItemContent CurBagItem = new BagItemContent();
                        CurBagItem.Head = FullBag.Substring(Struct.Head.StartPosition * 3, Struct.Head.Length * 3).Replace(" ", "");
                        CurBagItem.Cmd = FullBag.Substring(Struct.Cmd.StartPosition * 3, Struct.Cmd.Length * 3).Replace(" ", "");
                        CurBagItem.Other = FullBag.Substring(Struct.Other.StartPosition * 3, Struct.Other.Length * 3).Replace(" ", "");
                        CurBagItem.DataLen = FullBag.Substring(Struct.DataLen.StartPosition * 3, Struct.DataLen.Length * 3).Replace(" ", "");
                        CurBagItem.RealData = FullBag.Substring(Struct.RealDataPos * 3, BagDataLen * 3);
                        CurBagItem.Verify = FullBag.Substring(FullBag.Length - (Struct.VerifyLen + Struct.EndLen) * 3, Struct.VerifyLen * 3).Replace(" ", "");
                        CurBagItem.End = FullBag.Substring(FullBag.Length - Struct.EndLen * 3, Struct.EndLen * 3).Replace(" ", "");
                        if (Struct.ByteOrder == 1)//高字节在后,低字节在前
                        {
                            CurBagItem.Head = Struct.Head.Length <= 1 ? CurBagItem.Head : ReverseStr(CurBagItem.Head, 2);
                            CurBagItem.Cmd = (Struct.Cmd.Length <= 1 ? CurBagItem.Cmd : ReverseStr(CurBagItem.Cmd, 2));
                            CurBagItem.DataLen = Struct.DataLen.Length <= 1 ? CurBagItem.DataLen : ReverseStr(CurBagItem.DataLen, 2);
                            //CurBagItem.RealData,CurBagItem.Other需根据具体情况解析暂不反转
                            //CurBagItem.RealData = RealDataLen <= 1 ? CurBagItem.RealData : ReverseStr(CurBagItem.RealData, 2);
                            //CurBagItem.Other = Struct.Other.Length <= 1 ? CurBagItem.Other : ReverseStr(CurBagItem.Other, 2);
                            CurBagItem.Verify = Struct.VerifyLen <= 1 ? CurBagItem.Verify : ReverseStr(CurBagItem.Verify, 2);
                            CurBagItem.End = Struct.EndLen <= 1 ? CurBagItem.End : ReverseStr(CurBagItem.End, 2);
                        }
                        PortReciveDataItem NewItem = new PortReciveDataItem();
                        NewItem.ReciveTime = CurTime;
                        NewItem.ReciveDataItem = CurBagItem;
                        NewItem.ReciveDataStr = FullBag;
                        port.RcvLst.Add(NewItem);
                        Log.WriteLogToLocal(CurTime + "加入" + port.PortRealName + "完整数据包:
" + FullBag + "
------------------------
", "Log\IBO_LOG", port.PortDesc + "_Receive");
                        temp = temp.Remove(0, FullBag.Length);
                        if (temp.Length <= 0)
                        {
                            port.RcvData = "";
                            break;
                        }
                       // port.RcvData = temp.Substring((NoDataBagLen + BagDataLen) * 3);//剩余字符放入下个数据包
                    }
                    else
                    {
                        port.RcvData = CurRcvData;//不是完整包,等待完整数据
                        break;
                    }
                }
                else
                {
                    //丢弃不符合的串口数据
                    port.RcvData = "";
                    Log.WriteLogToLocal(CurTime + "丢弃" + port.PortRealName + "原始数据:
" + CurRcvData + "
------------------------
", "Log\IBO_LOG", port.PortDesc + "_Receive");
                    break;
                }
            }
        }
        
        /// <summary>
        /// 获取包长度
        /// </summary>
        /// <param name="Struct"></param>
        /// <param name="AllBagData"></param>
        /// <returns></returns>
        public static int GetBagDataLen(BagStruct Struct, string AllBagData)
        {
            int BagDataLen = 0;
            string CurDataLen = "";
            AllBagData = AllBagData.Replace(" ", "");
            string CurDataLenOrg = AllBagData.Substring(Struct.DataLen.StartPosition * 2, Struct.DataLen.Length * 2);
            if (Struct.ByteOrder == 1)//高字节在后,低字节在前
            {
                CurDataLen = ReverseStr(CurDataLenOrg, 2);
                BagDataLen = Convert.ToInt32(CurDataLen, 16);//16进制  需改成通用
            }
            else
            {
                CurDataLen = CurDataLenOrg;
                BagDataLen = Convert.ToInt32(CurDataLen, 10);//华气特殊 10进制
            }
            return BagDataLen;
        }
        
        /// <summary>
        /// 校验数据包
        /// </summary>
        /// <param name="BagStr"></param>
        /// <returns></returns>
        public static bool CheckBag(string BagHead, string BagEnd, BagStruct Struct, string BagStr, out int RealDataLen)
        {
            bool IsRight = true;
            RealDataLen = 0;
            BagStr = BagStr.Replace(" ", "");
            //校验包头,包尾
            if (!(BagStr.StartsWith(BagHead) && BagStr.EndsWith(BagEnd)))
            {
                IsRight = IsRight && false;
            }

            #region 校验包总长度
            int CurTotalBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;
            if (BagStr.Length < Struct.DataLen.StartPosition + Struct.DataLen.Length)
            {
                IsRight = IsRight && false;
            }
            else
            {
                string CurDataLen = "";
                string CurDataLenOrg = BagStr.Substring(Struct.DataLen.StartPosition * 2, Struct.DataLen.Length * 2);
                if (Struct.ByteOrder == 1)//高字节在后,低字节在前
                {
                    CurDataLen = ReverseStr(CurDataLenOrg, 2);
                    //for (int i = Struct.DataLen.Length; i > 0; i--)
                    //{
                    //    CurDataLen += CurDataLenOrg.Substring((i - 1) * 2, 2);
                    //}
                    RealDataLen = Convert.ToInt32(CurDataLen, 16);
                }
                else
                {
                    CurDataLen = CurDataLenOrg;
                    RealDataLen = Convert.ToInt32(CurDataLen, 10);//华气特殊
                }
                CurTotalBagLen += RealDataLen;
                if (BagStr.Length / 2 != CurTotalBagLen)
                {
                    IsRight = IsRight && false;
                }
            }
            #endregion

            return IsRight;
        }

        /// <summary>
        /// 反转字符串
        /// </summary>
        /// <param name="Str"></param>
        /// <param name="Len"></param>
        /// <returns></returns>
        public static string ReverseStr(string Str, int Len)
        {
            Str = Str.Replace(" ", "");
            string NewStr = "";
            List<string> ls = new List<string>();
            for (int i = 0; i < Str.Length; i += Len)
            {
                ls.Add(Str.Substring(i, Len)); // 两两截取
            }
            ls.Reverse();// 两两反转
            foreach (string item in ls)
            {
                NewStr += item;
            }
            return NewStr;
        }

        /// <summary>   
        /// 16进制字符串转字节数组   
        /// </summary>   
        /// <param name="hexString"></param>   
        /// <returns></returns>   
        public static byte[] strToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
            return returnBytes;
        }
    }
}

创建数据接收

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;

namespace SerialPortSpace
{
    /// <summary>
    /// 接收数据类
    /// </summary>
    public class PortReciveDataItem
    {
        public BagItemContent ReciveDataItem { get; set; }
        public DateTime ReciveTime { get; set; }
        public string ReciveDataStr { get; set; }
    }
    
    /// <summary>
    /// 串口缓存数据
    /// </summary>
    public class ComPort
    {
        /// <summary>
        /// 串口
        /// </summary>
        public SerialPort Port
        {
            set;
            get;
        }
        
        /// <summary>
        /// 当前串口名称
        /// </summary>
        public string PortRealName
        {
            set;
            get;
        }
        
        /// <summary>
        /// 当前串口描述
        /// </summary>
        public string PortDesc
        {
            set;
            get;
        }

        /// <summary>
        /// 当前串口是否正在接收数据---关闭串口判断
        /// </summary>
        public bool PortIsRcving
        {
            set;
            get;
        }

        /// <summary>
        /// 最近返回数据时间
        /// </summary>
        public DateTime LastRebackTime
        {
            get;
            set;
        }

        /// <summary>
        /// 定义接收包结构
        /// </summary>
        public BagStruct RcvBag
        {
            get;
            set;
        }
        
        /// <summary>
        /// 开始字符
        /// </summary>
        public string StartStr
        {
            set;
            get;
        }

        /// <summary>
        /// 结束字符
        /// </summary>
        public string EndStr
        {
            set;
            get;
        }
        /// <summary>
        /// 串口发送是指令集合
        /// </summary>
        public List<string> SendOrder
        {
            set;
            get;
        }

        /// <summary>
        /// 存储不完整包 临时数据
        /// </summary>
        public string RcvData
        {
            set;
            get;
        }
        
        /// <summary>
        /// 接收到的串口数据--完整包,临时存放
        /// </summary>
        public List<PortReciveDataItem> RcvLst
        {
            set;
            get;
        }
    }

    /// <summary>
    /// 接收包的结构定义
    /// </summary>
    public class BagStruct
    {
        /// <summary>
        /// 字节顺序约定 0--高字节在前,低字节在后,1--高字节在后,低字节在前
        /// </summary>
        public int ByteOrder
        {
            set;
            get;
        }
        /// <summary>
        /// 包头所占字节数
        /// </summary>
        public BagItemPosition Head
        {
            set;
            get;
        }
        /// <summary>
        /// 命令字段所占字节数
        /// </summary>
        public BagItemPosition Cmd
        {
            set;
            get;
        }
        /// <summary>
        /// 除实际数据包中数据长度及实际数据以外的其他数据项所占字节数
        /// </summary>
        public BagItemPosition Other
        {
            set;
            get;
        }

        /// <summary>
        /// 数据字段长度项所占字节数
        /// </summary>
        public BagItemPosition DataLen
        {
            set;
            get;
        }

        /// <summary>
        /// 实际数据所占字节数---可变的,可以根据实际数据包由DataLen计算所得
        /// </summary>
        public int RealDataPos//开始位置
        {
            set;
            get;
        }

        /// <summary>
        /// 校验位所占字节数
        /// </summary>
        public int VerifyLen
        {
            set;
            get;
        }

        /// <summary>
        /// 包尾所占字节数
        /// </summary>
        public int EndLen
        {
            set;
            get;
        }
    }
    /// <summary>
    /// 定义数据包中每项的开始位置及所占字节数
    /// </summary>
    public class BagItemPosition
    {
        /// <summary>
        /// 开始位置
        /// </summary>
        public int StartPosition
        {
            set;
            get;
        }
        /// <summary>
        /// 所占字节数
        /// </summary>
        public int Length
        {
            set;
            get;
        }
    }

    /// <summary>
    /// 接收包的结构内容
    /// </summary>
    public class BagItemContent
    {
        /// <summary>
        /// 包头
        /// </summary>
        public string Head
        {
            set;
            get;
        }

        /// <summary>
        /// 命令字段
        /// </summary>
        public string Cmd
        {
            set;
            get;
        }

        /// <summary>
        /// 除实际数据包中数据长度及实际数据以外的其他数据项
        /// </summary>
        public string Other
        {
            set;
            get;
        }

        /// <summary>
        /// 数据字段长度项
        /// </summary>
        public string DataLen
        {
            set;
            get;
        }

        /// <summary>
        /// 实际数据
        /// </summary>
        public string RealData
        {
            set;
            get;
        }

        /// <summary>
        /// 校验位
        /// </summary>
        public string Verify
        {
            set;
            get;
        }

        /// <summary>
        /// 包尾
        /// </summary>
        public string End
        {
            set;
            get;
        }
    }   

    
}

转载地址:https://www.cnblogs.com/TBW-Superhero/p/6839545.html

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO.Ports;using System.Threading;using LogSpace;
namespace SerialPortSpace{    public class SerialPortFun    {        /// <summary>        /// 串口及串口缓存数据        /// </summary>        public static List<ComPort> LstComPort = new List<ComPort>();
        /// <summary>        /// 是否在进行串口结束操作        /// </summary>        public static bool PortIsCloseing = false;
        /// <summary>        /// 初始化串口,并返回当前串口的结构        /// </summary>        /// <param name="Port"></param>        /// <param name="PortNo"></param>        /// <param name="BaudRate"></param>        /// <param name="ReciveData"></param>        public static ComPort InitSerialPort(SerialPort Port, string PortNo, int BaudRate, BagStruct CurBagStruct, string StartStr, string EndStr, string PortNameDesc, string PortRemark)        {            Port.PortName = PortNo;            Port.BaudRate = BaudRate;            Port.DataBits = 8;            Port.Parity = Parity.None;            Port.StopBits = StopBits.One;            Port.NewLine = " ";            Port.WriteTimeout = 5000;            Port.ReadTimeout = 5000;            Port.Handshake = Handshake.None;            Port.ReceivedBytesThreshold = 1;            Port.RtsEnable = true;            Port.DataReceived += Port_DataReceived;//定义接收数据事件
            ComPort PortItem = new ComPort();            PortItem.Port = Port;            PortItem.PortRealName = PortNameDesc;            PortItem.PortDesc = PortRemark;            PortItem.PortIsRcving = false;            PortItem.LastRebackTime = DateTime.Now;            PortItem.RcvBag = CurBagStruct;            PortItem.StartStr = StartStr;            PortItem.EndStr = EndStr;            PortItem.SendOrder = new List<string>();
            PortItem.RcvData = string.Empty;            PortItem.RcvLst = new List<PortReciveDataItem>();            if (LstComPort.Count(c => c.Port == Port) > 0)            {                LstComPort.RemoveAll(c => c.Port == Port);            }            LstComPort.Add(PortItem);            return PortItem;        }        /// <summary>        /// 定义数据包中每项的开始位置及所占字节数        /// </summary>        /// <param name="StartPosition"></param>        /// <param name="Length"></param>        /// <returns></returns>        public static BagItemPosition SetBagItemPosition(int StartPosition, int Length)        {            BagItemPosition Item = new BagItemPosition();            Item.StartPosition = StartPosition;            Item.Length = Length;            return Item;        }
        /// <summary>        /// 定义返回数据包结构        /// </summary>        /// <param name="ByteOrder">字节顺序约定 0--高字节在前,低字节在后,1--高字节在后,低字节在前</param>        /// <param name="HeadItem">包头所占字节数</param>        /// <param name="HeadItem">命令所占字节数</param>        /// <param name="OthItem">其他位总共占字节数</param>        /// <param name="DataLenItem">数据长度位所占字节数</param>        /// <param name="VerItem">校验位所占字节数</param>        /// <param name="EndItem">包尾所占字节数</param>        /// <returns></returns>        public static BagStruct SetBagStruct(int ByteOrder, BagItemPosition HeadItem, BagItemPosition CmdItem, BagItemPosition OthItem, BagItemPosition DataLenItem, int RealDataItem, int VerItem, int EndItem)        {            BagStruct CurRcvBagStruct = new BagStruct();            CurRcvBagStruct.ByteOrder = ByteOrder;            CurRcvBagStruct.Head = HeadItem;            CurRcvBagStruct.Cmd = CmdItem;            CurRcvBagStruct.Other = OthItem;            CurRcvBagStruct.DataLen = DataLenItem;            CurRcvBagStruct.RealDataPos = RealDataItem;            CurRcvBagStruct.VerifyLen = VerItem;            CurRcvBagStruct.EndLen = EndItem;            return CurRcvBagStruct;        }
        /// <summary>        /// 打开串口        /// </summary>        /// <param name="PortName"></param>        public static void OpenSerialPort(SerialPort Port)        {            if (!Port.IsOpen)            {                Port.Open();            }        }               /// <summary>        /// 发送串口数据        /// </summary>        /// <param name="Port"></param>        /// <param name="Data"></param>        public static bool SetPortData(SerialPort Port, string Data)        {            bool CurSendFlag = false;            if (Port.IsOpen)            {                byte[] buf = strToHexByte(Data);                Port.Write(buf, 0, buf.Length);                CurSendFlag = true;            }            return CurSendFlag;        }
        #region 接收串口应答包
        /// <summary>        /// 接收串口应答包        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        public static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)        {            if (PortIsCloseing)            {                return;            }            SerialPort port = sender as SerialPort;            DateTime CurTime = DateTime.Now;            string RcvData = string.Empty;            if (LstComPort != null)            {                if (LstComPort.Count(c => c.Port.PortName == port.PortName) > 0)                {                    ComPort comPort = LstComPort.Find(c => c.Port.PortName == port.PortName);                    try                    {                        Log.WriteLogToLocal(CurTime + "接收前" + comPort.PortRealName + "数据包临时数据: " + comPort.RcvData + " ------------------------ ", "Log\IBO_LOG", comPort.PortDesc + "_Receive");                        RcvData = comPort.RcvData;                        comPort.PortIsRcving = true;//正在接收串口数据                        StringBuilder CurRcvData = new StringBuilder();                        if (port.IsOpen && port.BytesToRead != 0)                        {                            while (port.BytesToRead != 0)                            {                                byte[] recvBytes = new byte[port.BytesToRead];                                int bytes = port.Read(recvBytes, 0, recvBytes.Length);                                if (recvBytes.Length != 0)                                {                                    foreach (byte b in recvBytes)                                    {                                        CurRcvData.Append(b.ToString("X2") + " ");                                    }                                }                                //Thread.Sleep(20);                            }                            Log.WriteLogToLocal(CurTime + "接收" + comPort.PortRealName + "原始数据: " + CurRcvData + " ------------------------ ", "Log\IBO_LOG", comPort.PortDesc + "_Receive");                            RcvData += CurRcvData;                            CurRcvData.Clear();                            //接收到的数据进行处理,并存储在串口对应的接收队列中                            //SerialPortFun.DealPortData(comPort, RcvData, CurTime);                            SerialPortFun.ConcatFullBag(comPort, comPort.RcvBag, RcvData, CurTime);                            comPort.LastRebackTime = CurTime;                        }                    }                    catch (Exception ex)                    {                        Log.WriteLogToLocal(CurTime + "接收" + comPort.PortRealName + "串口数据(" + RcvData + ")错误:(" + ex.Message+")"+ex.StackTrace + " ", "Log\IBO_LOG\ErrorLog", comPort.PortDesc + "_Receive");                    }                    finally                    {                        comPort.PortIsRcving = false;//接收串口数据完毕                    }                }            }        }
        #endregion        /// <summary>        /// 接收到的数据进行处理,并存储在串口对应的接收队列中        /// </summary>        /// <param name="port"></param>        /// <param name="Struct"></param>        /// <param name="CurRcvData"></param>        /// <param name="CurTime"></param>        public static void ConcatFullBag(ComPort port, BagStruct Struct, string CurRcvData, DateTime CurTime)        {            Log.WriteLogToLocal(CurTime + "数据包处理" + port.PortRealName + "原始数据: " + CurRcvData + " ------------------------ ", "Log\IBO_LOG", port.PortDesc + "_Receive");            string temp = CurRcvData;            while (true)            {                //校验包头,包尾                if (!temp.StartsWith(port.StartStr))                {                    int index = temp.IndexOf(port.StartStr);                    if (index == -1)                        temp = "";                    else                        temp = temp.Remove(0, index);                }                if (temp.Length > 0)                {                    int NoDataBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;                    int BagDataLen = 0;                    if (temp.Length > (Struct.DataLen.StartPosition * 3 + Struct.DataLen.Length * 3))                    {                        #region 获取数据包的业务数据长度                        BagDataLen = GetBagDataLen(Struct, temp);                        //string CurDataLen = "";                        //string CurDataLenOrg = temp.Substring(Struct.DataLen.StartPosition * 3, Struct.DataLen.Length * 3);                        //if (Struct.ByteOrder == 1)//高字节在后,低字节在前                        //{                        //    CurDataLen = ReverseStr(CurDataLenOrg, 2);                        //    BagDataLen = Convert.ToInt32(CurDataLen, 16);//16进制                        //}                        //else                        //{                        //    CurDataLen = CurDataLenOrg;                        //    BagDataLen = Convert.ToInt32(CurDataLen, 10);//华气特殊 10进制                        //}                        #endregion                    }                    if (BagDataLen > 0 && temp.Length / 3 >= NoDataBagLen + BagDataLen)                    {                        string FullBag = temp.Substring(0, (NoDataBagLen + BagDataLen) * 3);                        BagItemContent CurBagItem = new BagItemContent();                        CurBagItem.Head = FullBag.Substring(Struct.Head.StartPosition * 3, Struct.Head.Length * 3).Replace(" ", "");                        CurBagItem.Cmd = FullBag.Substring(Struct.Cmd.StartPosition * 3, Struct.Cmd.Length * 3).Replace(" ", "");                        CurBagItem.Other = FullBag.Substring(Struct.Other.StartPosition * 3, Struct.Other.Length * 3).Replace(" ", "");                        CurBagItem.DataLen = FullBag.Substring(Struct.DataLen.StartPosition * 3, Struct.DataLen.Length * 3).Replace(" ", "");                        CurBagItem.RealData = FullBag.Substring(Struct.RealDataPos * 3, BagDataLen * 3);                        CurBagItem.Verify = FullBag.Substring(FullBag.Length - (Struct.VerifyLen + Struct.EndLen) * 3, Struct.VerifyLen * 3).Replace(" ", "");                        CurBagItem.End = FullBag.Substring(FullBag.Length - Struct.EndLen * 3, Struct.EndLen * 3).Replace(" ", "");                        if (Struct.ByteOrder == 1)//高字节在后,低字节在前                        {                            CurBagItem.Head = Struct.Head.Length <= 1 ? CurBagItem.Head : ReverseStr(CurBagItem.Head, 2);                            CurBagItem.Cmd = (Struct.Cmd.Length <= 1 ? CurBagItem.Cmd : ReverseStr(CurBagItem.Cmd, 2));                            CurBagItem.DataLen = Struct.DataLen.Length <= 1 ? CurBagItem.DataLen : ReverseStr(CurBagItem.DataLen, 2);                            //CurBagItem.RealData,CurBagItem.Other需根据具体情况解析暂不反转                            //CurBagItem.RealData = RealDataLen <= 1 ? CurBagItem.RealData : ReverseStr(CurBagItem.RealData, 2);                            //CurBagItem.Other = Struct.Other.Length <= 1 ? CurBagItem.Other : ReverseStr(CurBagItem.Other, 2);                            CurBagItem.Verify = Struct.VerifyLen <= 1 ? CurBagItem.Verify : ReverseStr(CurBagItem.Verify, 2);                            CurBagItem.End = Struct.EndLen <= 1 ? CurBagItem.End : ReverseStr(CurBagItem.End, 2);                        }                        PortReciveDataItem NewItem = new PortReciveDataItem();                        NewItem.ReciveTime = CurTime;                        NewItem.ReciveDataItem = CurBagItem;                        NewItem.ReciveDataStr = FullBag;                        port.RcvLst.Add(NewItem);                        Log.WriteLogToLocal(CurTime + "加入" + port.PortRealName + "完整数据包: " + FullBag + " ------------------------ ", "Log\IBO_LOG", port.PortDesc + "_Receive");                        temp = temp.Remove(0, FullBag.Length);                        if (temp.Length <= 0)                        {                            port.RcvData = "";                            break;                        }                       // port.RcvData = temp.Substring((NoDataBagLen + BagDataLen) * 3);//剩余字符放入下个数据包                    }                    else                    {                        port.RcvData = CurRcvData;//不是完整包,等待完整数据                        break;                    }                }                else                {                    //丢弃不符合的串口数据                    port.RcvData = "";                    Log.WriteLogToLocal(CurTime + "丢弃" + port.PortRealName + "原始数据: " + CurRcvData + " ------------------------ ", "Log\IBO_LOG", port.PortDesc + "_Receive");                    break;                }            }        }                /// <summary>        /// 获取包长度        /// </summary>        /// <param name="Struct"></param>        /// <param name="AllBagData"></param>        /// <returns></returns>        public static int GetBagDataLen(BagStruct Struct, string AllBagData)        {            int BagDataLen = 0;            string CurDataLen = "";            AllBagData = AllBagData.Replace(" ", "");            string CurDataLenOrg = AllBagData.Substring(Struct.DataLen.StartPosition * 2, Struct.DataLen.Length * 2);            if (Struct.ByteOrder == 1)//高字节在后,低字节在前            {                CurDataLen = ReverseStr(CurDataLenOrg, 2);                BagDataLen = Convert.ToInt32(CurDataLen, 16);//16进制  需改成通用            }            else            {                CurDataLen = CurDataLenOrg;                BagDataLen = Convert.ToInt32(CurDataLen, 10);//华气特殊 10进制            }            return BagDataLen;        }                /// <summary>        /// 校验数据包        /// </summary>        /// <param name="BagStr"></param>        /// <returns></returns>        public static bool CheckBag(string BagHead, string BagEnd, BagStruct Struct, string BagStr, out int RealDataLen)        {            bool IsRight = true;            RealDataLen = 0;            BagStr = BagStr.Replace(" ", "");            //校验包头,包尾            if (!(BagStr.StartsWith(BagHead) && BagStr.EndsWith(BagEnd)))            {                IsRight = IsRight && false;            }
            #region 校验包总长度            int CurTotalBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;            if (BagStr.Length < Struct.DataLen.StartPosition + Struct.DataLen.Length)            {                IsRight = IsRight && false;            }            else            {                string CurDataLen = "";                string CurDataLenOrg = BagStr.Substring(Struct.DataLen.StartPosition * 2, Struct.DataLen.Length * 2);                if (Struct.ByteOrder == 1)//高字节在后,低字节在前                {                    CurDataLen = ReverseStr(CurDataLenOrg, 2);                    //for (int i = Struct.DataLen.Length; i > 0; i--)                    //{                    //    CurDataLen += CurDataLenOrg.Substring((i - 1) * 2, 2);                    //}                    RealDataLen = Convert.ToInt32(CurDataLen, 16);                }                else                {                    CurDataLen = CurDataLenOrg;                    RealDataLen = Convert.ToInt32(CurDataLen, 10);//华气特殊                }                CurTotalBagLen += RealDataLen;                if (BagStr.Length / 2 != CurTotalBagLen)                {                    IsRight = IsRight && false;                }            }            #endregion
            return IsRight;        }
        /// <summary>        /// 反转字符串        /// </summary>        /// <param name="Str"></param>        /// <param name="Len"></param>        /// <returns></returns>        public static string ReverseStr(string Str, int Len)        {            Str = Str.Replace(" ", "");            string NewStr = "";            List<string> ls = new List<string>();            for (int i = 0; i < Str.Length; i += Len)            {                ls.Add(Str.Substring(i, Len)); // 两两截取            }            ls.Reverse();// 两两反转            foreach (string item in ls)            {                NewStr += item;            }            return NewStr;        }
        /// <summary>           /// 16进制字符串转字节数组           /// </summary>           /// <param name="hexString"></param>           /// <returns></returns>           public static byte[] strToHexByte(string hexString)        {            hexString = hexString.Replace(" ", "");            if ((hexString.Length % 2) != 0)                hexString += " ";            byte[] returnBytes = new byte[hexString.Length / 2];            for (int i = 0; i < returnBytes.Length; i++)                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);            return returnBytes;        }    }}

原文地址:https://www.cnblogs.com/sdxlz666/p/10495496.html