.NET串口通讯解决方案

网上关于.NET串口通讯的文章不少,但大多只是一些对.NET串口通讯函数的简单封装,对于实际的操作和使用,并没有太直接的帮助。本人做过几个.NET下串口通讯的小项目,借鉴了一些前人的经验(特别是SharpGps)并结合自己的一些心得和体会,写下这篇文章,算是对自己这部分工作的一个总结。

本来这篇文章的题目叫“.NET串口通讯设计”,想想觉得如果叫这个名字,那就没有写下去的必要了(网上这样的文章大把)。至于这篇文章配得上“解决方案”这四个字否? (我也不知道~) 言归正传,正文开始…

  • 设计概要

      SerialPort.cs

      ComEvent.cs

      Enumerations.cs

      以及各种协议的具体实现类,如XXX_imp.cs

  • 通讯基础类SerialPort.cs

      主要封装一些.Net串口通讯已实现的一些常用方法,这个类和网上大多数介绍.Net串口通讯的文章所介绍的差不多,唯一不同的地方是在接收部分的处理(注:接收部分采用了异步的方式),利用了.Net的事件机制,将“接收数据”这一事件根据事件类型(即协议),告知给协议的具体实现类进行相应的处理。

public class SerialPort : IDisposable
    {
        private System.IO.Ports.SerialPort com;
        private bool disposed = false;

        internal event RevMsgDelegate MsgDelegate;

        public SerialPort()
        {
            com = new System.IO.Ports.SerialPort();
            //默认参数
           com.PortName = "com1";
            com.BaudRate = 9600;
            com.DataBits = 8;
            com.StopBits = StopBits.One;
            com.Parity = Parity.None;

            com.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            disposed = false;
        }

        public void Dispose()
        {
            if (!this.disposed)
            {
                this.Stop();
                com = null;
            }
            disposed = true;

            GC.SuppressFinalize(this);
        }

        ~SerialPort()
        {
            Dispose();
        }
        /// <summary>
        /// 数据接受响应函数
       /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(500);
            System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
            String indata = sp.ReadExisting();
                     
            //接受数据消息 将接受到的数据分类 然后转发给响应的imp
            if (MsgDelegate != null)
            {
                RevMsgEventArgs RevEventArgs = new RevMsgEventArgs();
                RevEventArgs.MsgType = GetCommType(indata);
                MsgDelegate(indata, RevEventArgs);
            }
        }

        /// <summary>
        /// 反馈数据类型识别
         /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        private GTCommType GetCommType(string sentence)
        { 
//具体根据协议,进行类别的判断       
//...... 
           return commType;
        }

        public bool Write(String cmd)
        {
            try
            {
                com.Write(cmd);
            }
            catch (System.Exception e)
            {
                return false;
            }
            return true;
        }

        public bool Open()
        {
            try
            {
                com.Open();
            }
            catch (System.IO.IOException ex)
            {
                return false;
            }
            return true;
        }

        public bool IsPortOpen
        {
            get { return com.IsOpen; }
        }

        public void Stop()
        {
            if (com != null)
                if (com.IsOpen)
                    com.Close();
        }

        public String PortName
        {
            get { return com.PortName; }
            set
            {
                if (value != null)
                    com.PortName = value;
            }
        }
        public int BaudRate
        {
            get { return com.BaudRate; }
            set
            {
                if (value != 0)
                    com.BaudRate = value;
            }
        }
        public int DataBits
        {
            get { return com.DataBits; }
            set
            {
                if (value != 0)
                    com.DataBits = value;
            }
        }
        public StopBits Stopbits
        {
            get { return com.StopBits; }
            set
            {
                if (value != 0)
                    com.StopBits = value;
            }
        }
        public Parity parity
        {
            get { return com.Parity; }
            set
            {
                if (value != 0)
                    com.Parity = value;
            }
        }
    }
  • ComEvent.cs

      定义代理(事件的载体)以及事件的内容,主要包含两个代理:(1)接收数据代理RevMsgDelegate, 用来将DataReceivedHandler中接收到数据分发给相应的imp  (2)UI代理UIMsgDelegate, 用来将imp类中处理好的数据发送给UI以实现相应的逻辑,例如数据的呈现等界面操作。 注: 如果通讯是在线程中处理的,那么UI的响应需要调用Invoke方法实现。

//接收数据代理
internal delegate void RevMsgDelegate(object sender, RevMsgEventArgs e);
internal class RevMsgEventArgs : EventArgs   //接受数据事件内容
{
    public GTCommType MsgType;//接受到的数据类型
}
//UI事件代理
public delegate void UIMsgDelegate(object sender, UIMsgEventArgs e);
public class UIMsgEventArgs : EventArgs
{
    //UI事件内容
    //...... 
}
  • Enumerations.cs

      事件类型的枚举。

public enum CommMsgType
 {
     //通讯事件
     //......
 }

 public enum UIMsgType
 {      
     //UI事件
     //......
 }
  • 协议的具体实现类

      主要的功能是接收RevMsgDelegate代理发送过来的事件,根据当前协议的内容,对数据进行解析并通过UIMsgDelegate发送相应的界面事件,驱动相关联的界面操作。本类主要是根据实际情况进行封装,所以在此不多说,只列出一些重要的操作。

public class XXX_imp
    {
        private SerialPort _port;
        //UI事件
         public event UIMsgDelegate UIMsg;
        UIMsgEventArgs UIEventArgs;

        public XXX_imp(SerialPort port)
        {
            _port = port;
            //绑定数据接受事件
            port.MsgDelegate += new RevMsgDelegate(Parse);
        }

        private void Parse(object sender, RevMsgEventArgs e)
        {
            if (e.MsgType == GTCommType.XXX)
            {
            //解析数据
              //...... 
            }
        }#region 接口
        //根据需要的业务逻辑编写有关方法
        //......
        #endregion
    }

 

      到此本文就告一段落, 本人是.Net的初学者,只是略懂皮毛,写这篇文章更主要的目的还是希望大家能多多指点,有不足和改进的地方希望能予以指出。

posted on 2012-10-30 23:54  MoZhao  阅读(792)  评论(1编辑  收藏  举报

导航