C#异步数据接收串口操作类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#异步数据接收串口操作类相关的知识,希望对你有一定的参考价值。

C#异步数据接收串口操作类


  1. 使用C#调用传统32位API实现串口操作,整个结构特别的简单。接收数据只需要定义数据接收事件即可。

  2. 上传源代码我不会,需要源代码的请与我([email protected])联系。你也可以教我怎么上传源代码。

  3. using System;

  4. using System.Runtime.InteropServices;

  5. /// <summary>

  6. /// (C)2003-2005 C2217 Studio  保留所有权利

  7. /// 

  8. /// 文件名称:     IbmsSerialPort.cs

  9. /// 文件ID:

  10. /// 文件说明:

  11. ///         封装动态链接库IbmsSerialPort.dll的功能,提供在.NET环境中

  12. ///         串口异步接收和发送数据的功能。

  13. ///      

  14. /// 当前版本:   1.0

  15. /// 

  16. /// 作者:    邓杨均

  17. /// 创建日期:   2005-2-2 

  18. /// 最后修改日期: 2005-2-2

  19. /// 

  20. /// 历史修改记录:

  21. /// 

  22. /// </summary>

  23. namespace Ibms.Tool.IO

  24. {

  25.  /// <summary>

  26.  /// 当串口接收到数据时,会产生一个事件。

  27.  /// SPRecvDataArgs就是该事件的参数,参数中的RecvData包含接收到的数据。

  28.  /// 使用方法:

  29.  /// </summary>

  30.  public class SPRecvDataArgs:EventArgs

  31.  {

  32.   /// <summary>

  33.   /// 接收到的数据组成的字节数组

  34.   /// </summary>

  35.   private byte[] recvData;

  36.   /// <summary>

  37.   /// 构造函数,需要一个包含数据的byte[]作为初始化参数来实例化 SPRecvDataArgs

  38.   /// </summary>

  39.   /// <param name="recvData">接收到的数据</param>

  40.   public SPRecvDataArgs(byte[] recvData)

  41.   {

  42.    if( recvData == null)

  43.    {

  44.     throw(new ArgumentNullException());

  45.    }

  46.    this.recvData = recvData;

  47.   }

  48.   /// <summary>

  49.   /// 返回接收到的数据内容

  50.   /// </summary>

  51.   public byte[] RecvData

  52.   {

  53.    get

  54.    {

  55.     return recvData;

  56.    }

  57.   }

  58.  }

  59.  /// <summary>

  60.  /// 封装动态链接库IbmsSerialPort.dll的功能,提供在.NET环境中异步

  61.  /// 串口接收和发送功能。特别实现的是异步通过信号自动接收数据的模式。

  62.  /// </summary>

  63.  public class IbmsSerialPort:IDisposable

  64.  {

  65. #region 平台调用声明代码

  66.   /// <summary>

  67.   /// 声明IbmsSerialPort.dll的Ibms_OpenPort函数

  68.   /// </summary>

  69.   /// <param name="nPort">串口号</param>

  70.   /// <param name="nRate">波特率</param>

  71.   /// <returns></returns>

  72.   [DllImport("IbmsSerialPort.dll")]

  73.   public static extern IntPtr Ibms_OpenPort(int nPort, int nRate); 

  74.   /// <summary>

  75.   /// 声明IbmsSerialPort.dll的Ibms_Close函数

  76.   /// </summary>

  77.   [DllImport("IbmsSerialPort.dll")]

  78.   public static extern void Ibms_Close( IntPtr port);

  79.   /// <summary>

  80.   /// 声明IbmsSerialPort.dll的Ibms_SendData函数

  81.   /// </summary>

  82.   /// <param name="data"></param>

  83.   /// <param name="nDataSize"></param>

  84.   /// <returns></returns>

  85.   [DllImport("IbmsSerialPort.dll")]

  86.   public static extern bool Ibms_SendData( IntPtr port, byte[] data,int nDataSize);

  87.   /// <summary>

  88.   /// 声明IbmsSerialPort.dll的Ibms_SetFuncHandle函数

  89.   /// </summary>

  90.   /// <param name="handDataFunc"></param>

  91.   [DllImport("IbmsSerialPort.dll")]

  92.   public static extern void Ibms_SetFuncHandle( IntPtr port, HandleFunc handDataFunc);

  93. #endregion

  94.    

  95. #region 定义字段

  96.   /// <summary>

  97.   /// 定义数据处理委托,作为API的函数指针传入动态链接库

  98.   /// </summary>

  99.   public delegate void HandleFunc(IntPtr pData, int nDataSize); 

  100.   /// <summary>

  101.   /// 定义数据接收事件的原型

  102.   /// </summary>

  103.   public delegate void RecvData(object sender,SPRecvDataArgs e);

  104.   /// <summary>

  105.   /// 定义数据接收事件

  106.   /// </summary>

  107.   public event RecvData OnRecvData;

  108.   /// <summary>

  109.   /// 串口处理接收数据的委托

  110.   /// </summary>

  111.   private HandleFunc _handleDataFunc;

  112.   /// <summary>

  113.   /// 串口的编号,从1开始的整数,最大255

  114.   /// </summary>

  115.   private int port;

  116.   /// <summary>

  117.   /// 串口所支持的波特率,必须是标准波特率之一

  118.   /// </summary>

  119.   private StanderdRate rate;

  120.   /// <summary>

  121.   /// 串口当前的打开状态

  122.   /// </summary>

  123.   private bool openStatus=false;

  124.   /// <summary>

  125.   /// 串口句柄

  126.   /// </summary>

  127.   private IntPtr portHandle;

  128.   #region 定义标准的串口波特率

  129.   /// <summary>

  130.   /// 标准的波特率

  131.   /// </summary>

  132.   public enum StanderdRate

  133.   {

  134.    R50=50,

  135.    R75=75,

  136.    R110=110,

  137.    R150=150,

  138.    R300=300,

  139.    R600=600,

  140.    R1200=1200,

  141.    R2400=2400,

  142.    R4800=4800,

  143.    R9600=9600,

  144.    R19200=19200,

  145.    R38400=38400,

  146.    R57600=57600,

  147.    R76800=76800,

  148.    R115200=115200

  149.   };

  150.   

  151.   #endregion

  152. #endregion 

  153. #region 定义方法

  154.   /// <summary>

  155.   /// 构造函数

  156.   /// </summary>

  157.   public IbmsSerialPort()

  158.   {

  159.    portHandle = (IntPtr)0;

  160.    _handleDataFunc = new HandleFunc(OnDllRecvData);

  161.   }

  162.   /// <summary>

  163.   /// 打开串口

  164.   /// </summary>

  165.   /// <param name="nPort">串口号</param>

  166.   /// <param name="nRate">波特率</param>

  167.   /// /// <exception cref="ApplicationException">抛出应用程序异常,包换错误描述</exception>

  168.   public void Open(int nPort, StanderdRate nRate)

  169.   {

  170.    if(nPort > 255 || nPort < 0)

  171.    {

  172.     throw(new ArgumentOutOfRangeException());

  173.    }

  174.    port = nPort;

  175.    rate = nRate;

  176.    portHandle = Ibms_OpenPort( port, (int)rate );

  177.    if( (IntPtr)0 == portHandle  )

  178.    {

  179.     thrownew ApplicationException("打开串口失败"));

  180.    }

  181.    

  182.    //注册函数指针

  183.    Ibms_SetFuncHandle( portHandle, _handleDataFunc );

  184.    openStatus = true;

  185.   }

  186.   /// <summary>

  187.   /// 关闭串口

  188.   /// </summary>

  189.   public void Close()

  190.   {

  191.    if( openStatus )

  192.    {

  193.     Ibms_Close( portHandle);

  194.    }

  195.    openStatus = false;

  196.   }

  197.   /// <summary>

  198.   /// 发送数据

  199.   /// </summary>

  200.   /// <param name="sendData">数据内容</param>

  201.   /// <exception cref="ApplicationException">抛出应用程序异常,包换错误描述</exception>

  202.   public void SendData( byte[] data )

  203.   {

  204.    if( !openStatus )

  205.    {

  206.     thrownew ApplicationException("串口没有打开,发送数据失败") );

  207.    }

  208.    if( !Ibms_SendData( portHandle, data, data.Length ) )

  209.    {

  210.     thrownew ApplicationException("串口发送数据失败") );

  211.    }

  212.   }

  213.   /// <summary>

  214.   /// 处理接收到的串口数据

  215.   /// </summary>

  216.   /// <param name="pData">串口数据接收缓冲区首地址</param>

  217.   /// <param name="nDataSize">数据大小,一般数据大小不超过2K</param>

  218.   unsafe protected void OnDllRecvData(IntPtr pUnhandleData, int nDataSize)

  219.   {

  220.    int dataSize= nDataSize ;

  221.     

  222.    byte * pData =(byte *) pUnhandleData;

  223.    byte[] data = new byte[dataSize];

  224.    //复制数据到byte数组

  225.    for(int i=0; i<dataSize; i++)

  226.    {

  227.     data[i]= pData[i];

  228.    }

  229.    //激发事件

  230.    OnRecvData( thisnew SPRecvDataArgs(data) );

  231.   }

  232. #endregion

  233. #region 定义属性

  234.   /// <summary>

  235.   /// 返回当前的串口号

  236.   /// </summary>

  237.   public int Port

  238.   {

  239.    get

  240.    {

  241.     return port;

  242.    }

  243.   }

  244.   /// <summary>

  245.   /// 返回当前串口的波特率

  246.   /// </summary>

  247.   public StanderdRate Rate

  248.   {

  249.    get

  250.    {

  251.     return rate;

  252.    }

  253.   }

  254.   /// <summary>

  255.   /// 返回当前串口的状态

  256.   /// </summary>

  257.   public bool OpenStatus

  258.   {

  259.    get

  260.    {

  261.     return openStatus;

  262.    }

  263.   }

  264. #endregion

  265.   

  266. #region 非托管资源的及时释放

  267.   

  268.   /// <summary>

  269.   /// 因为包含了非托管的资源(占用系统串口),必须实现IDisposable接口

  270.   /// 在使用完该类的时候,必须记得调用Dispose(),回收系统资源

  271.   /// <example>

  272.   /// 

  273.   /// 方法1

  274.   /// {

  275.   ///  SerialPort port =new SerialPort();

  276.   ///  ...

  277.   ///  //在try-catch-finaly的finaly中释放资源

  278.   ///  

  279.   ///  port.Dispose();

  280.   /// }

  281.   /// 

  282.   /// 方法2

  283.   /// using( SerialPort port = new SerialPort())

  284.   /// {

  285.   ///  ...

  286.   /// }

  287.   /// 变量超出作用域时会自动调用其Dispose()方法

  288.   /// 

  289.   /// </example>

  290.   /// </summary>

  291.   ~IbmsSerialPort()

  292.   {

  293.    Dispose( false );

  294.   }

  295.   protected virtual void Dispose( bool disposing )

  296.   {

  297.    if( disposing )

  298.    {

  299.     //清理托管的对象

  300.    }

  301.    //清理非托管的资源

  302.    Close();

  303.   }

  304.   #region IDisposable 成员

  305.   public void Dispose()

  306.   {

  307.    // TODO:  添加 SerialPort.Dispose 实现

  308.    Dispose( true );

  309.    GC.SuppressFinalize(this);

  310.   }

  311.   #endregion

  312. #endregion

  313.  }

  314. }


以上是关于C#异步数据接收串口操作类的主要内容,如果未能解决你的问题,请参考以下文章

C# 串口发送不可接收的数据

想用C#写linux下的串口收发程序?

STM32串口发送接收数据

串口使用和CSerial类

c#里,通过串口收到的数据会转换为16进制字符串,想将数据存入数据库,应该怎么写?

C#定时器接收定时发送和处理接收socket异步通信,接收值放在静态变量里,有时候收到的数据不完整。