串口通信与协议

    public class BaseSerialPort {

        #region 字段
        private const int msgMaxLength = 512;//通信协议中最长的指令的字节数目,制定的通信协议最长指令不得超过msgMaxLength
        private object locker = new object();//在串口接收数据的线程中使用,保证数据接收正确
        
        private byte[] byteMsgRecv;//使用字节协议时,用于接收数据
        private string strMsgRecv;//使用字符协议时,用于接收数据

        private AutoResetEvent waiterForRsp = new AutoResetEvent(false);//用于同步用户的Logic线程和串口的DataReceived线程
        private int usingSource = 0;//保证一条指令的交互完整性,或多条指令组成的模块的交互完整性

        public SerialPort _device {
            get; private set;
        }
        private Encoding encoding;//字符编码
        #endregion

        #region 构造函数
        /// 
        /// 使用字节型通信协议调用此构造函数
        /// 
        /// 串口名
        /// 波特率
        /// 数据位
        /// 停止位
        /// 奇偶校验
        public BaseSerialPort(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity) {
            this._device = new SerialPort();
            this._device.PortName = portName;
            this._device.BaudRate = baudRate;
            this._device.DataBits = dataBits;
            this._device.StopBits = stopBits;
            this._device.Parity = parity;
            this._device.DataReceived += Device_DataReceived;
            this.encoding = null;
        }
        /// 
        /// 使用字符串型通信协议调用此构造函数
        /// 
        /// 串口名
        /// 波特率
        /// 数据位
        /// 停止位
        /// 奇偶校验
        public BaseSerialPort(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity, Encoding encoding) {
            this._device = new SerialPort();
            this._device.PortName = portName;
            this._device.BaudRate = baudRate;
            this._device.DataBits = dataBits;
            this._device.StopBits = stopBits;
            this._device.Parity = parity;
            this._device.DataReceived += Device_DataReceived;
            this.encoding = encoding;
        }
        #endregion

        #region 连接设备
        public void Connect() {
            try {
                if (!this._device.IsOpen) {
                    this._device.Open();
                }
            }
            catch {
                throw new Exception(string.Format("端口{0}已被占用或被拒绝访问",this._device.PortName));
            }
        }
        #endregion

        #region 关闭连接
        public void Close() {
            if (this._device.IsOpen) {
                this._device.Close();
            }
        }
        #endregion

        #region 接收数据
        public void Device_DataReceived(object sender, SerialDataReceivedEventArgs e) {
            lock (locker) {
                if (_device.BytesToRead > 0) {
                    byte[] buff = new byte[msgMaxLength];
                    int startIndex = 0;
                    while (_device.BytesToRead > 0) {
                        int count = _device.Read(buff, startIndex, _device.BytesToRead);
                        startIndex += count;
                        Thread.Sleep(10);
                    }

                    byte[] msg = new byte[startIndex];
                    Array.Copy(buff, msg, startIndex);

                    if (this.encoding == null) {
                        this.byteMsgRecv = msg;
                    }
                    else {
                        string strMsg = this.encoding.GetString(msg);
                        this.strMsgRecv = strMsg;
                    }
                    waiterForRsp.Set();
                }
            }
        }
        #endregion

        #region 发送消息
        public void SendMsg(byte[] msg) {
            this.Connect();
            this._device.Write(msg, 0, msg.Length);
        }

        public void SendMsg(string msg) {
            this.Connect();
            byte[] msgToByte = this.encoding.GetBytes(msg);
            this._device.Write(msgToByte, 0, msgToByte.Length);
        }
        #endregion

        #region 原子操作
        /// 
        /// 接收设备的响应消息(字节型通信协议)
        /// 
        /// 等待设备回复的最大时长
        /// 收到的设备的回复
        /// 
        public bool RecvRsp(int timeOut, out byte[] msg) {
            bool isInTime = waiterForRsp.WaitOne(timeOut);
            byte[] buff = new byte[byteMsgRecv.Length];
            Array.Copy(byteMsgRecv, buff, byteMsgRecv.Length);
            msg = buff;
            return isInTime;
        }
        /// 
        /// 接收设备的响应消息(字符型通信协议)
        /// 
        /// 等待设备回复的最大时长
        /// 收到的设备的回复
        /// 
        public bool RecvRsp(int timeOut, out string msg) {
            bool isInTime = waiterForRsp.WaitOne(timeOut);
            msg = strMsgRecv;
            return isInTime;
        }

        public void OccupyRoute() {
            while (Interlocked.Exchange(ref usingSource, 1) == 1)
                ;
        }

        public void AbandonRoute() {
            Interlocked.Exchange(ref usingSource, 0);
        }
        #endregion
    }

 

你可能感兴趣的:(串口通信与协议)