SerialPort 串口编程知识整理(一)

mac2022-06-30  33

1、基本概念

      MS .NET FrameWork2.0中对串口通讯进行了封装,我们可以在.net2.0及以上版本开发时直接使用SerialPort类对串口进行读写操作。

SerialPort类的属性主要包括:

串口名称(PortName

波特率(BaudRate

数据位 DataBits

停止位 StopBits

奇偶校验 Parity

握手协议 Handshake

SerialPort类的事件主要包括:

DataReceived:用于异步接收串口数据

SerialPort类的方法主要包括:

Open();Close();Read();Write()等。

相关内容可以参考MSDN或者博文

http://www.cnblogs.com/tony-yang/archive/2009/06/03/learnserialport.html

         http://www.cnblogs.com/hocylan/archive/2008/03/13/1103624.html

 

2、需求和场景介绍

      本文是基于之前开发的一个油站项目,主要功能是实现对加油机数据的采集和对加油机的一些控制,例如停开机、设置单价、定量定额加油等操作。

系统通过PC机串口,与下位机进行通讯,下位机和加油机进行通讯,负责采集加油机数据和控制加油机的操作。

 

3、设计思想

         (1)在界面设计上,由于系统启动后要始终实时监控加油数据,采用了SDI展示方式。

截图如下:

    (2)在系统设计方面,加油机监控软件具有一定的实时性、稳定性和数据并发的非功能性需求。所以在对加油数据采集时,使用事件DataReceived,用于异步接收串口数据。使用watchdog方式监控系统消息,通过缓存池对数据进行过滤,减轻数据库的压力,提高系统性能。

 

4、代码演示

         系统采用CS结构,使用SerialPort类进行串口通讯。对SerialPort类进行了封装,以保证多个窗体间对串口实例的调用。

         封装的串口通讯类参考:http://blog.csdn.net/yefanqiu/archive/2007/03/27/1543187.aspx

串口通讯类:SerialPortDao.cs /* ----------------------------------------------------------------           // Copyright (C) 北京****科技有限公司           // 版权所有。            //           // 文件名:SerialPortDao           // 文件功能描述:封装串口组件,实现对串口的统一访问和操作           //           //            // 创建标识:** 2009-5-23           //           // 修改标识:**           // 修改描述://---------------------------------------------------------------- */ using  System; using  System.Collections.Generic; using  System.Text; using  System.IO.Ports; namespace  LY.FuelStationPOS.Protocol{     ///   <summary>      ///  提供对串口的统一访问     ///   </summary>      public   sealed   class  SerialPortDao    {         #region  事件和字段定义          public   event  PortDataReceivedEventHandle Received;         public  SerialPort serialPort  =   null ;         public   bool  ReceiveEventFlag  =   false ;   // 接收事件是否有效 false表示有效          private   static   readonly  SerialPortDao instance  =   new  SerialPortDao();         #endregion          #region  属性定义          private   string  protName;         public   string  PortName        {             get  {  return  serialPort.PortName; }             set              {                 serialPort.PortName  =  value;                protName  =  value;            }        }         #endregion          #region  构造函数          private  SerialPortDao()        {            LoadSerialPort();        }         private   void  LoadSerialPort()        {            serialPort  =   new  SerialPort();            serialPort.BaudRate  =   9600 ;            serialPort.Parity  =  Parity.Even;            serialPort.DataBits  =   8 ;            serialPort.StopBits  =  StopBits.One;            serialPort.Handshake  =  Handshake.None;            serialPort.RtsEnable  =   true ;            serialPort.ReadTimeout  =   2000 ;            serialPort.DataReceived  +=   new  SerialDataReceivedEventHandler(DataReceived);        }               #endregion                      #region  串口操作集合          ///   <summary>          ///  返回串口对象的单个实例         ///   </summary>          ///   <returns></returns>          public   static  SerialPortDao GetSerialPortDao()        {                      return  instance;        }                ///   <summary>          ///  释放串口资源         ///   </summary>          ~ SerialPortDao()        {            Close();        }         ///   <summary>          ///  打开串口         ///   </summary>          public   void  Open()        {             try             {                 if  ( ! serialPort.IsOpen)                {                    serialPort.Open();                                    }            }             catch  (Exception ex)            {                 throw  ex;            }                   }         ///   <summary>          ///  关闭串口         ///   </summary>          public   void  Close()        {             if  (serialPort.IsOpen)            {                serialPort.Close();            }        }         ///   <summary>          ///  串口是否打开         ///   </summary>          ///   <returns></returns>          public   bool  IsOpen()        {             return  serialPort.IsOpen;        }                ///   <summary>          ///  数据发送         ///   </summary>          ///   <param name="data"> 要发送的数据字节 </param>          public   void  SendData( byte [] data)        {             try             {                serialPort.DiscardInBuffer();                serialPort.Write(data,  0 , data.Length);            }             catch  (Exception ex)            {                 throw  ex;            }        }         ///   <summary>          ///  发送命令         ///   </summary>          ///   <param name="SendData"> 发送数据 </param>          ///   <param name="ReceiveData"> 接收数据 </param>          ///   <param name="Overtime"> 超时时间 </param>          ///   <returns></returns>          public   int  SendCommand( byte [] SendData,  ref   byte [] ReceiveData,  int  Overtime)        {             if  (serialPort.IsOpen)            {                 try                 {                    ReceiveEventFlag  =   true ;         // 关闭接收事件                     serialPort.DiscardInBuffer();    // 清空接收缓冲区                                      serialPort.Write(SendData,  0 , SendData.Length);                    System.Threading.Thread.Sleep( 50 );                     int  num  =   0 , ret  =   0 ;                     while  (num ++   <  Overtime)                    {                         if  (serialPort.BytesToRead  >=  ReceiveData.Length)                        {                             break ;                        }                        System.Threading.Thread.Sleep( 50 );                    }                     if  (serialPort.BytesToRead  >=  ReceiveData.Length)                    {                        ret  =  serialPort.Read(ReceiveData,  0 , ReceiveData.Length);                    }                     else                     {                        ret  =  serialPort.Read(ReceiveData,  0 , serialPort.BytesToRead);                    }                    ReceiveEventFlag  =   false ;        // 打开事件                      return  ret;                }                 catch  (Exception ex)                {                    ReceiveEventFlag  =   false ;                     throw  ex;                }            }             return   - 1 ;        }         /// <summary>          /// 数据发送         /// </summary>          /// <param name="data"> 要发送的数据字符串 </param>          public   void  SendData( string  data)        {             // 禁止接收事件时直接退出              if  (ReceiveEventFlag)            {                 return ;            }             if  (serialPort.IsOpen)            {                serialPort.Write(data);            }        }          /// <summary>           /// 将指定数量的字节写入输出缓冲区中的指定偏移量处。          /// </summary>           /// <param name="data"> 发送的字节数据 </param>           /// <param name="offset"> 写入偏移量 </param>           /// <param name="count"> 写入的字节数 </param>          public   void  SendData( byte [] data,  int  offset,  int  count)        {             // 禁止接收事件时直接退出              if  (ReceiveEventFlag)            {                 return ;            }             if  (serialPort.IsOpen)            {                serialPort.Write(data, offset, count);            }        }                        ///   <summary>          ///  数据接收         ///   </summary>          ///   <param name="sender"></param>          ///   <param name="e"></param>          public   void  DataReceived( object  sender, SerialDataReceivedEventArgs e)        {             // 禁止接收事件时直接退出              if  (ReceiveEventFlag)            {                 return ;            }             try             {                 byte [] data  =   new   byte [serialPort.BytesToRead];                serialPort.Read(data,  0 , data.Length);                 if  (Received  !=   null )                {                    Received(sender,  new  PortDataReciveEventArgs(data));                }            }             catch  (Exception ex)            {                 // throw ex;             }                    }    }} 串口通讯数据类:PortDataReciveEventArgs /* ----------------------------------------------------------------           // Copyright (C) 北京****科技有限公司           // 版权所有。            //           // 文件名:PortDataReciveEventArgs           // 文件功能描述:重写PortDataReciveEventArgs参数类           //           //            // 创建标识:** 2009-5-23           //           // 修改标识:           // 修改描述:           //           // 修改标识:           // 修改描述://---------------------------------------------------------------- */ using  System; using  System.Collections.Generic; using  System.Text; namespace  LY.FuelStationPOS.Protocol{     public   delegate   void  PortDataReceivedEventHandle( object  sender, PortDataReciveEventArgs e);     public   class  PortDataReciveEventArgs : EventArgs    {         private   byte [] data;         public   byte [] Data        {             get  {  return  data; }             set  { data  =  value; }        }         public  PortDataReciveEventArgs()        {             this .data  =   null ;        }         public  PortDataReciveEventArgs( byte [] data)        {             this .data  =  data;        }            }}

转载于:https://www.cnblogs.com/deepwishly/archive/2010/04/23/2551246.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)