zoukankan      html  css  js  c++  java
  • 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;
            }
        }   
    
        
    }
    复制代码
  • 相关阅读:
    Pandas对于CSV的简单操作
    前端之BOM和DOM
    前端之JavaScript
    前端之CSS初识
    定时ping取返回值并绘图
    etree不存在解决方法
    内置方法练习(一)
    pip使用
    python变量、变量属性
    python 爬取段子网段子写入文件
  • 原文地址:https://www.cnblogs.com/soundcode/p/9309226.html
Copyright © 2011-2022 走看看