c#串口通讯基类

public class SerialPortUtil
    {
       /// <summary>
        /// 接收事件是否有效 false表示有效
        /// </summary>
        public bool ReceiveEventFlag = false;


        /// <summary>
        /// 结束符
        /// </summary>
        public string EndLine = "\r\n"; //0x23;//string End = "#";


        /// <summary>
        /// 完整协议的记录处理事件
        /// </summary>
        //public event DataReceivedEventHandler DataReceived;
        public event SerialErrorReceivedEventHandler Error;
        public StringBuilder builder = new StringBuilder();
        public long receive_count;
        public long send_count;
        public string comm_status;
        public string receive_content = string.Empty;
        public string receive_cmd = string.Empty;




        #region 串口属性
        private string _portName; //= "COM1";//串口号,默认COM1
        private SerialPortBaudRates _baudRate; // = SerialPortBaudRates.BaudRate_57600;//波特率
        private Parity _parity; // = Parity.None;//校验位
        private StopBits _stopBits; // = StopBits.One;//停止位
        private SerialPortDatabits _dataBits; // = SerialPortDatabits.EightBits;//数据位


        public bool Listening = false;  //是否没有执行完invoke相关操作
        public bool Closing = false;    //是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke
         
        /// <summary>
        /// 串口号
        /// </summary>
        public string portName
        {
            get { return _portName; }
            set { _portName = value; }
        }


        /// <summary>
        /// 波特率
        /// </summary>
        public SerialPortBaudRates BaudRate
        {
            get { return _baudRate; }
            set { _baudRate = value; }
        }


        /// <summary>
        /// 奇偶校验位
        /// </summary>
        public Parity Parity
        {
            get { return _parity; }
            set { _parity = value; }
        }


        /// <summary>
        /// 数据位
        /// </summary>
        public SerialPortDatabits DataBits
        {
            get { return _dataBits; }
            set { _dataBits = value; }
        }


        /// <summary>
        /// 停止位
        /// </summary>
        public StopBits StopBits
        {
            get { return _stopBits; }
            set { _stopBits = value; }
        }


        #endregion


        public SerialPort _serialPort = new SerialPort();




        #region 构造函数


        /// <summary>
        /// 参数构造函数(使用枚举参数构造)
        /// </summary>
        /// <param name="baud">波特率</param>
        /// <param name="par">奇偶校验位</param>
        /// <param name="sBits">停止位</param>
        /// <param name="dBits">数据位</param>
        /// <param name="name">串口号</param>
        public SerialPortUtil(string name, SerialPortBaudRates baud, Parity parity, SerialPortDatabits dBits, StopBits sBits)
        {
            _portName = name;
            _baudRate = baud;
            _parity = parity;
            _dataBits = dBits;
            _stopBits = sBits;


            _serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
            _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
        }


        /// <summary>
        /// 参数构造函数(使用字符串参数构造)
        /// </summary>
        /// <param name="baud">波特率</param>
        /// <param name="par">奇偶校验位</param>
        /// <param name="sBits">停止位</param>
        /// <param name="dBits">数据位</param>
        /// <param name="name">串口号</param>
        public SerialPortUtil(string name, string baud, string pariry, string dBits, string sBits)
        {
            _portName = name;
            _baudRate = (SerialPortBaudRates)Enum.Parse(typeof(SerialPortBaudRates), baud);
            _parity = (Parity)Enum.Parse(typeof(Parity), pariry);
            _dataBits = (SerialPortDatabits)Enum.Parse(typeof(SerialPortDatabits), dBits);
            _stopBits = (StopBits)Enum.Parse(typeof(StopBits), sBits);


            _serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
            _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
        }


        /// <summary>
        /// 默认构造函数
        /// </summary>
        public SerialPortUtil()
        {
            _portName = "COM1";
            _baudRate = SerialPortBaudRates.BaudRate_9600;
            _parity = Parity.None;
            _dataBits = SerialPortDatabits.EightBits;
            _stopBits = StopBits.One;


            _serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
            _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
        }


        #endregion




        /// <summary>
        /// 端口是否已经打开
        /// </summary>
        public bool IsOpen
        {
            get
            {
                return _serialPort.IsOpen;
            }
        }


        /// <summary>
        /// 打开端口
        /// </summary>
        /// <returns></returns>
        public void OpenPort()
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    Closing = true;
                    while (Listening)
                    {
                        Application.DoEvents(); //防止假死
                    }
                    _serialPort.Close();
                }


                _serialPort.PortName = _portName;
                _serialPort.BaudRate = (int)_baudRate;
                _serialPort.Parity = _parity;
                _serialPort.DataBits = (int)_dataBits;
                _serialPort.StopBits = _stopBits;


                _serialPort.ReadTimeout = 50;
                _serialPort.WriteTimeout = 50;
                
                _serialPort.Open();
                this.DiscardBuffer();


                comm_status = "Open";
                Closing = false;
            }
            catch (Exception ex)
            {
                comm_status = "Error";
                //string cnmsg = string.Format("打开串口{0}失败: " + ex.ToString(), _serialPort.PortName);
                string enmsg = string.Format("Open Serial Port {0} Fail: " + ex.ToString(), _serialPort.PortName);
                Logger.log(enmsg, ErrorCode.EC_OpenSerialPortErr, ErrLevel.ERROR);
            }
        }




        /// <summary>
        /// 关闭端口
        /// </summary>
        public bool ClosePort()
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    Closing = true;
                    _serialPort.Close();
                    comm_status = "Close";
                }
            }
            catch (Exception ex)
            {
                //string cnmsg = string.Format("关闭串口{0}失败: " + ex.ToString(), _serialPort.PortName);
                string enmsg = string.Format("Close Serial Port {0} Fail: " + ex.ToString(), _serialPort.PortName);
                Logger.log(enmsg, ErrorCode.EC_OpenSerialPortErr, ErrLevel.ERROR);
                return false;
            }
            return true;
        }


        /// <summary>
        /// 丢弃来自串行驱动程序的接收和发送缓冲区的数据
        /// </summary>
        public void DiscardBuffer()
        {
            _serialPort.DiscardInBuffer();
            _serialPort.DiscardOutBuffer();
        }


        /// <summary>
        /// 数据接收处理
        /// </summary>
        public virtual void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(50);
            //禁止接收事件时直接退出
            if (ReceiveEventFlag) return;


            if (Closing) return;  //如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
            try
            {
                Listening = true;  //设置标记,说明已经开始处理数据,一会儿要使用系统UI
                int n = _serialPort.BytesToRead;
                byte[] buf = new byte[n];
                _serialPort.Read(buf, 0, n);
                receive_count += n;


                builder.Clear();
                builder.Append(Encoding.ASCII.GetString(buf));
                                
                receive_content = builder.ToString();


                int CRLF = -1;
                CRLF = receive_content.IndexOf("\r\n");
                if (CRLF != -1)
                {
                    string content = receive_content.Substring(0, CRLF);


                    //cEngine.updateRcvTopCommMsg(content);
                    //cEngine.cprod.event_TopScanner.Set();
                }


                //触发整条记录的处理
                //if (DataReceived != null)
                //{
                //    DataReceived(new DataReceivedEventArgs(readString));
                //}
            }
            catch (Exception ex)
            {
                string enmsg = string.Format("Serial Port {0} Communication Fail\r\n" + ex.ToString(), _serialPort.PortName);
                Logger.log(enmsg, ErrorCode.EC_SerialPortCommuErr, ErrLevel.ERROR);
            }
            finally
            {
                Listening = false;   //监听完毕, UI可关闭串口
            }
        }


        /// <summary>
        /// 错误处理函数
        /// </summary>
        public virtual void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            if (Error != null)
            {
                Error(sender, e);
            }
        }




        #region 数据发送操作


        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg)
        {
            try
            {
                if (!(_serialPort.IsOpen)) _serialPort.Open();


                _serialPort.Write(msg);
            }
            catch (Exception ex)
            {
                string enmsg = string.Format("Serial Port {0} Send Command Fail\r\n" + ex.ToString(), _serialPort.PortName);
                Logger.log(enmsg, ErrorCode.EC_SerialPortSendErr, ErrLevel.ERROR);
            }
        }


        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="msg">写入端口的字节数组</param>
        public void Send(byte[] msg)
        {
            try
            {
                if (!(_serialPort.IsOpen)) _serialPort.Open();


                _serialPort.Write(msg, 0, msg.Length);  //WriteLine
            }
            catch (Exception ex)
            {
                string enmsg = string.Format("Serial Port {0} Send Command Fail\r\n" + ex.ToString(), _serialPort.PortName);
                Logger.log(enmsg, ErrorCode.EC_SerialPortSendErr, ErrLevel.ERROR);
            }
        }


        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="msg">包含要写入端口的字节数组</param>
        /// <param name="offset">参数从0字节开始的字节偏移量</param>
        /// <param name="count">要写入的字节数</param>
        public void Send(byte[] msg, int offset, int count)
        {
            try
            {
                if (!(_serialPort.IsOpen)) _serialPort.Open();


                _serialPort.Write(msg, offset, count);
            }
            catch (Exception ex)
            {
                string enmsg = string.Format("Serial Port {0} Send Command Fail\r\n" + ex.ToString(), _serialPort.PortName);
                Logger.log(enmsg, ErrorCode.EC_SerialPortSendErr, ErrLevel.ERROR);
            }
        }
        #endregion


        #region Set Port Parameters
        /// <summary>
        /// 封装获取串口号列表
        /// </summary>
        /// <returns></returns>
        public string[] GetPortNames()
        {
            return SerialPort.GetPortNames();
        }


        /// <summary>
        /// Set Serial Port
        /// </summary>
        /// <param name="obj"></param>
        public static void SetPortNameValues(ComboBox obj)
        {
            obj.Items.Clear();
            foreach (string str in SerialPort.GetPortNames())
            {
                obj.Items.Add(str);
            }
        }


        /// <summary>
        /// Set BaudRate
        /// </summary>
        public static void SetBauRateValues(ComboBox obj)
        {
            obj.Items.Clear();
            foreach (SerialPortBaudRates rate in Enum.GetValues(typeof(SerialPortBaudRates)))
            {
                obj.Items.Add(((int)rate).ToString());
            }
        }


        /// <summary>
        /// Set DataBits
        /// </summary>
        public static void SetDataBitsValues(ComboBox obj)
        {
            obj.Items.Clear();
            foreach (SerialPortDatabits databit in Enum.GetValues(typeof(SerialPortDatabits)))
            {
                obj.Items.Add(((int)databit).ToString());
            }
        }


        /// <summary>
        /// Set Parity
        /// </summary>
        public static void SetParityValues(ComboBox obj)
        {
            obj.Items.Clear();
            foreach (string str in Enum.GetNames(typeof(Parity)))
            {
                obj.Items.Add(str);
            }
        }


        /// <summary>
        /// Set StopBits
        /// </summary>
        public static void SetStopBitValues(ComboBox obj)
        {
            obj.Items.Clear();
            foreach (string str in Enum.GetNames(typeof(StopBits)))
            {
                obj.Items.Add(str);
            }
        }


        #endregion




        #region 格式转换
        /// <summary>
        /// 转换十六进制字符串到字节数组
        /// </summary>
        /// <param name="msg">待转换字符串</param>
        /// <returns>字节数组</returns>
        public static byte[] HexToByte(string msg)
        {
            msg = msg.Replace(" ", "");//移除空格


            //create a byte array the length of the
            //divided by 2 (Hex is 2 characters in length)
            byte[] comBuffer = new byte[msg.Length / 2];
            for (int i = 0; i < msg.Length; i += 2)
            {
                //convert each set of 2 characters to a byte and add to the array
                comBuffer[i / 2] = (byte)Convert.ToByte(msg.Substring(i, 2), 16);
            }


            return comBuffer;
        }


        /// <summary>
        /// 转换字节数组到十六进制字符串
        /// </summary>
        /// <param name="comByte">待转换字节数组</param>
        /// <returns>十六进制字符串</returns>
        public static string ByteToHex(byte[] comByte)
        {
            StringBuilder builder = new StringBuilder(comByte.Length * 3);
            foreach (byte data in comByte)
            {
                builder.Append(Convert.ToString(data, 16).PadLeft(2, '0').PadRight(3, ' '));
            }


            return builder.ToString().ToUpper();
        }
        #endregion


        /// <summary>
        /// Check Serial Port Exist
        /// </summary>
        /// <param name="port_name"></param>
        /// <returns></returns>
        public bool Exists(string port_name)
        {
            foreach (string port in SerialPort.GetPortNames()) if (port == port_name) return true;
            return false;
        }


        /// <summary>
        /// 格式化端口相关属性
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        public string Format(SerialPort port)
        {
            return String.Format("{0} ({1},{2},{3},{4},{5})",
                port.PortName, port.BaudRate, port.DataBits, port.StopBits, port.Parity, port.Handshake);
        }


        public static int IndexOf_Byte(byte[] searched, byte[] find, int start)
        {
            bool matched = false;
            int end = find.Length - 1;
            int skip = 0;
            for (int index = start; index <= searched.Length - find.Length; ++index)
            {
                matched = true;
                if (find[0] != searched[index] || find[end] != searched[index + end]) continue;
                else skip++;
                if (end > 10)
                    if (find[skip] != searched[index + skip] || find[end - skip] != searched[index + end - skip])
                        continue;
                    else skip++;
                for (int subIndex = skip; subIndex < find.Length - skip; ++subIndex)
                {
                    if (find[subIndex] != searched[index + subIndex])
                    {
                        matched = false;
                        break;
                    }
                }
                if (matched)
                {
                    return index;
                }
            }
            return -1;
        } 




    }


    /// <summary>
    /// 串口数据位列表(5,6,7,8)
    /// </summary>
    public enum SerialPortDatabits : int
    {
        FiveBits = 5,
        SixBits = 6,
        SeventBits = 7,
        EightBits = 8
    }
    public enum SerialPortBaudRates : int
    {
        BaudRate_75 = 75,
        BaudRate_110 = 110,
        BaudRate_150 = 150,
        BaudRate_300 = 300,
        BaudRate_600 = 600,
        BaudRate_1200 = 1200,
        BaudRate_2400 = 2400,
        BaudRate_4800 = 4800,
        BaudRate_9600 = 9600,
        BaudRate_14400 = 14400,
        BaudRate_19200 = 19200,
        BaudRate_28800 = 28800,
        BaudRate_38400 = 38400,
        BaudRate_56000 = 56000,
        BaudRate_57600 = 57600,
        BaudRate_115200 = 115200,
        BaudRate_128000 = 128000,
        BaudRate_230400 = 230400,
        BaudRate_256000 = 256000
    }
}

猜你喜欢

转载自blog.csdn.net/qq_20410891/article/details/80570064