C#串口通信编程类


C#串口通信编程类
实现打开/关闭/读/写Com端口

using System;
using System.Runtime.InteropServices;

namespace vjsdn.Tester

   public class CommLib
   {
      public CommLib()
      {
      }
      public int PortNum; //1,2,3,4
      public int BaudRate; //1200,2400,4800,9600
      public byte ByteSize; //8 bits
      public byte Parity; // 0-4=no,odd,even,mark,space
      public byte StopBits; // 0,1,2 = 1, 1.5, 2
      public int ReadTimeout; //10
      
      //comm port win32 file handle
      private int hComm = -1;
      
      public bool Opened = false;
      
      //win32 api constants
      private const uint GENERIC_READ = 0x80000000;
      private const uint GENERIC_WRITE = 0x40000000;
      private const int OPEN_EXISTING = 3;
      private const int INVALID_HANDLE_VALUE = -1;
      
      [StructLayout(LayoutKind.Sequential)]
      private struct DCB
      {
         //taken from c struct in platform sdk
         public int DCBlength; // sizeof(DCB)
         public int BaudRate; // current baud rate
         public int fBinary; // binary mode, no EOF check
         public int fParity; // enable parity checking
         public int fOutxCtsFlow; // CTS output flow control
         public int fOutxDsrFlow; // DSR output flow control
         public int fDtrControl; // DTR flow control type
         public int fDsrSensitivity; // DSR sensitivity
         public int fTXContinueOnXoff; // XOFF continues Tx
         public int fOutX; // XON/XOFF out flow control
         public int fInX; // XON/XOFF in flow control
         public int fErrorChar; // enable error replacement
         public int fNull; // enable null stripping
         public int fRtsControl; // RTS flow control
         public int fAbortOnError; // abort on error
         public int fDummy2; // reserved
         public ushort wReserved; // not currently used
         public ushort XonLim; // transmit XON threshold
         public ushort XoffLim; // transmit XOFF threshold
         public byte ByteSize; // number of bits/byte, 4-8
         public byte Parity; // 0-4=no,odd,even,mark,space
         public byte StopBits; // 0,1,2 = 1, 1.5, 2
         public char XonChar; // Tx and Rx XON character
         public char XoffChar; // Tx and Rx XOFF character
         public char ErrorChar; // error replacement character
         public char EofChar; // end of input character
         public char EvtChar; // received event character
         public ushort wReserved1; // reserved; do not use
      }
      
      [StructLayout(LayoutKind.Sequential)]
      private struct COMMTIMEOUTS
      {
         public int ReadIntervalTimeout;
         public int ReadTotalTimeoutMultiplier;
         public int ReadTotalTimeoutConstant;
         public int WriteTotalTimeoutMultiplier;
         public int WriteTotalTimeoutConstant;
      }
      
      [StructLayout(LayoutKind.Sequential)]
      private struct OVERLAPPED
      {
         public int Internal;
         public int InternalHigh;
         public int Offset;
         public int OffsetHigh;
         public int hEvent;
      }
      
      [DllImport("kernel32.dll")]
      private static extern int CreateFile(
      string lpFileName, // file name
      uint dwDesiredAccess, // access mode
      int dwShareMode, // share mode
      int lpSecurityAttributes, // SD
      int dwCreationDisposition, // how to create
      int dwFlagsAndAttributes, // file attributes
      int hTemplateFile // handle to template file
      );
      [DllImport("kernel32.dll")]
      private static extern bool GetCommState(
      int hFile, // handle to communications device
      ref DCB lpDCB // device-control block
      );
      [DllImport("kernel32.dll")]
      private static extern bool BuildCommDCB(
      string lpDef, // device-control string
      ref DCB lpDCB // device-control block
      );
      [DllImport("kernel32.dll")]
      private static extern bool SetCommState(
      int hFile, // handle to communications device
      ref DCB lpDCB // device-control block
      );
      [DllImport("kernel32.dll")]
      private static extern bool GetCommTimeouts(
      int hFile, // handle to comm device
      ref COMMTIMEOUTS lpCommTimeouts // time-out values
      );
      [DllImport("kernel32.dll")]
      private static extern bool SetCommTimeouts(
      int hFile, // handle to comm device
      ref COMMTIMEOUTS lpCommTimeouts // time-out values
      );
      [DllImport("kernel32.dll")]
      private static extern bool ReadFile(
      int hFile, // handle to file
      byte[] lpBuffer, // data buffer
      int nNumberOfBytesToRead, // number of bytes to read
      ref int lpNumberOfBytesRead, // number of bytes read
      ref OVERLAPPED lpOverlapped // overlapped buffer
      );
      [DllImport("kernel32.dll")]
      private static extern bool WriteFile(
      int hFile, // handle to file
      byte[] lpBuffer, // data buffer
      int nNumberOfBytesToWrite, // number of bytes to write
      ref int lpNumberOfBytesWritten, // number of bytes written
      ref OVERLAPPED lpOverlapped // overlapped buffer
      );
      [DllImport("kernel32.dll")]
      private static extern bool CloseHandle(
      int hObject // handle to object
      );
      
      public void Open()
      {
         DCB dcbCommPort = new DCB();
         COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
         
         // OPEN THE COMM PORT. 
         hComm = CreateFile("COM" + PortNum ,GENERIC_READ | GENERIC_WRITE,0, 0,OPEN_EXISTING,0,0);
         
         // IF THE PORT CANNOT BE OPENED, BAIL OUT.
         if(hComm == INVALID_HANDLE_VALUE)
         {
            throw(new ApplicationException("Comm Port Can Not Be Opened"));
         }
         
         // SET THE COMM TIMEOUTS. 
         GetCommTimeouts(hComm,ref ctoCommPort);
         ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
         ctoCommPort.ReadTotalTimeoutMultiplier = 0;
         ctoCommPort.WriteTotalTimeoutMultiplier = 0;
         ctoCommPort.WriteTotalTimeoutConstant = 0;
         SetCommTimeouts(hComm,ref ctoCommPort);
         
         // SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
         // THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST.
         // IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER
         // THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
         // ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
         
         dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
         GetCommState(hComm, ref dcbCommPort);
         dcbCommPort.BaudRate=BaudRate;
         dcbCommPort.Parity=Parity;
         dcbCommPort.ByteSize=ByteSize;
         dcbCommPort.StopBits=StopBits;
         SetCommState(hComm, ref dcbCommPort);
         
         Opened = true;
         
      }
      
      public void Close()
      {
         if (hComm!=INVALID_HANDLE_VALUE)
         {
            CloseHandle(hComm);
            Opened=false;
         }
      }
      
      public byte[] Read(int NumBytes)
      {
         byte[] BufBytes;
         byte[] OutBytes;
         BufBytes = new byte[NumBytes];
         if (hComm!=INVALID_HANDLE_VALUE)
         {
            OVERLAPPED ovlCommPort = new OVERLAPPED();
            int BytesRead=0;
            ReadFile(hComm,BufBytes,NumBytes,ref BytesRead,ref ovlCommPort);
            OutBytes = new byte[BytesRead];
            Array.Copy(BufBytes,OutBytes,BytesRead);
         }
         else
         {
            throw(new ApplicationException("Comm Port Not Open"));
         }
         return OutBytes;
      }
      
      public int Write(byte[] WriteBytes)
      {
         int BytesWritten = 0;
         if (hComm!=INVALID_HANDLE_VALUE)
         {
            OVERLAPPED ovlCommPort = new OVERLAPPED();
            WriteFile(hComm,WriteBytes,WriteBytes.Length,ref BytesWritten,ref ovlCommPort);
         }
         else
         {
            throw(new ApplicationException("Comm Port Not Open"));
         }
         return BytesWritten;
      }
   }
}

转自: http://www.chinaaspx.com/comm/dotnetbbs/Go.aspx?Forum_ID=6&id=81202&PPage=1&Action=prev
带中文注释:
using System;
using System.Runtime.InteropServices;

namespace JustinIO {
   class CommPort {
      
      public string PortNum;
      public int BaudRate;
      public byte ByteSize;
      public byte Parity; // 0-4=no,odd,even,mark,space
      public byte StopBits; // 0,1,2 = 1, 1.5, 2
      public int ReadTimeout;
      
      //comm port win32 file handle
      private int hComm = -1;
      
      public bool Opened = false;
      
      //win32 api constants
      private const uint GENERIC_READ = 0x80000000;
      private const uint GENERIC_WRITE = 0x40000000;
      private const int OPEN_EXISTING = 3;
      private const int INVALID_HANDLE_VALUE = -1;
      
      [StructLayout(LayoutKind.Sequential)]
      public struct DCB {
         //taken from c struct in platform sdk
         public int DCBlength; // sizeof(DCB)
         public int BaudRate; // 指定当前波特率 current baud rate
         // these are the c struct bit fields, bit twiddle flag to set
         public int fBinary; // 指定是否允许二进制模式,在windows95中必须主TRUE binary mode, no EOF check
         public int fParity; // 指定是否允许奇偶校验 enable parity checking
         public int fOutxCtsFlow; // 指定CTS是否用于检测发送控制,当为TRUE是CTS为OFF,发送将被挂起。 CTS output flow control
         public int fOutxDsrFlow; // 指定CTS是否用于检测发送控制 DSR output flow control
         public int fDtrControl; // DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手" DTR flow control type
         public int fDsrSensitivity; // 当该值为TRUE时DSR为OFF时接收的字节被忽略 DSR sensitivity
         public int fTXContinueOnXoff; // 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止。TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出XoffChar字符中止接收字节之后,发送继续进行。 FALSE时,在接收缓冲区接收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。XOFF continues Tx
         public int fOutX; // TRUE时,接收到XoffChar之后便停止发送接收到XonChar之后将重新开始 XON/XOFF out flow control
         public int fInX; // TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去 XON/XOFF in flow control
         public int fErrorChar; // 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字符 enable error replacement
         public int fNull; // eTRUE时,接收时去掉空(0值)字节 enable null stripping
         public int fRtsControl; // RTS flow control
          /*RTS_CONTROL_DISABLE时,RTS置为OFF
            RTS_CONTROL_ENABLE时, RTS置为ON
            RTS_CONTROL_HANDSHAKE时,
            当接收缓冲区小于半满时RTS为ON
             当接收缓冲区超过四分之三满时RTS为OFF
            RTS_CONTROL_TOGGLE时,
            当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFF*/
         
         
         public int fAbortOnError; // TRUE时,有错误发生时中止读和写操作 abort on error
         public int fDummy2; // 未使用 reserved
         
         public uint flags;
         public ushort wReserved; // 未使用,必须为0 not currently used
         public ushort XonLim; // 指定在XON字符发送这前接收缓冲区中可允许的最小字节数 transmit XON threshold
         public ushort XoffLim; // 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数 transmit XOFF threshold
         public byte ByteSize; // 指定端口当前使用的数据位 number of bits/byte, 4-8
         public byte Parity; // 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space
         public byte StopBits; // 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2
         public char XonChar; // 指定用于发送和接收字符XON的值 Tx and Rx XON character
         public char XoffChar; // 指定用于发送和接收字符XOFF值 Tx and Rx XOFF character
         public char ErrorChar; // 本字符用来代替接收到的奇偶校验发生错误时的值 error replacement character
         public char EofChar; // 当没有使用二进制模式时,本字符可用来指示数据的结束 end of input character
         public char EvtChar; // 当接收到此字符时,会产生一个事件 received event character
         public ushort wReserved1; // 未使用 reserved; do not use
      }
      
      [StructLayout(LayoutKind.Sequential)]
      private struct COMMTIMEOUTS {
         public int ReadIntervalTimeout;
         public int ReadTotalTimeoutMultiplier;
         public int ReadTotalTimeoutConstant;
         public int WriteTotalTimeoutMultiplier;
         public int WriteTotalTimeoutConstant;
      }
      
      [StructLayout(LayoutKind.Sequential)]
      private struct OVERLAPPED {
         public int Internal;
         public int InternalHigh;
         public int Offset;
         public int OffsetHigh;
         public int hEvent;
      }
      
      [DllImport("kernel32.dll")]
      private static extern int CreateFile(
      string lpFileName, // 要打开的串口名称
      uint dwDesiredAccess, // 指定串口的访问方式,一般设置为可读可写方式
      int dwShareMode, // 指定串口的共享模式,串口不能共享,所以设置为0
      int lpSecurityAttributes, // 设置串口的安全属性,WIN9X下不支持,应设为NULL
      int dwCreationDisposition, // 对于串口通信,创建方式只能为OPEN_EXISTING
      int dwFlagsAndAttributes, // 指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信
      int hTemplateFile // 对于串口通信必须设置为NULL
      );
      [DllImport("kernel32.dll")]
      private static extern bool GetCommState(
      int hFile, //通信设备句柄
      ref DCB lpDCB // 设备控制块DCB
      );
      [DllImport("kernel32.dll")]
      private static extern bool BuildCommDCB(
      string lpDef, // 设备控制字符串
      ref DCB lpDCB // 设备控制块
      );
      [DllImport("kernel32.dll")]
      private static extern bool SetCommState(
      int hFile, // 通信设备句柄
      ref DCB lpDCB // 设备控制块
      );
      [DllImport("kernel32.dll")]
      private static extern bool GetCommTimeouts(
      int hFile, // 通信设备句柄 handle to comm device
      ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values
      );
      [DllImport("kernel32.dll")]
      private static extern bool SetCommTimeouts(
      int hFile, // 通信设备句柄 handle to comm device
      ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values
      );
      [DllImport("kernel32.dll")]
      private static extern bool ReadFile(
      int hFile, // 通信设备句柄 handle to file
      byte[] lpBuffer, // 数据缓冲区 data buffer
      int nNumberOfBytesToRead, // 多少字节等待读取 number of bytes to read
      ref int lpNumberOfBytesRead, // 读取多少字节 number of bytes read
      ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer
      );
      [DllImport("kernel32.dll")]
      private static extern bool WriteFile(
      int hFile, // 通信设备句柄 handle to file
      byte[] lpBuffer, // 数据缓冲区 data buffer
      int nNumberOfBytesToWrite, // 多少字节等待写入 number of bytes to write
      ref int lpNumberOfBytesWritten, // 已经写入多少字节 number of bytes written
      ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer
      );
      [DllImport("kernel32.dll")]
      private static extern bool CloseHandle(
      int hObject // handle to object
      );
      [DllImport("kernel32.dll")]
      private static extern uint GetLastError();
      
      public void Open()
      {
         
         DCB dcbCommPort = new DCB();
         COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
         
         // 打开串口 OPEN THE COMM PORT.
         hComm = CreateFile(PortNum ,GENERIC_READ | GENERIC_WRITE,0, 0,OPEN_EXISTING,0,0);
         // 如果串口没有打开,就打开 IF THE PORT CANNOT BE OPENED, BAIL OUT.
         if(hComm == INVALID_HANDLE_VALUE)
         {
            throw(new ApplicationException("非法操作,不能打开串口!"));
         }
         
         // 设置通信超时时间 SET THE COMM TIMEOUTS.
         GetCommTimeouts(hComm,ref ctoCommPort);
         ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
         ctoCommPort.ReadTotalTimeoutMultiplier = 0;
         ctoCommPort.WriteTotalTimeoutMultiplier = 0;
         ctoCommPort.WriteTotalTimeoutConstant = 0;
         SetCommTimeouts(hComm,ref ctoCommPort);
         
         // 设置串口 SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
         GetCommState(hComm, ref dcbCommPort);
         dcbCommPort.BaudRate=BaudRate;
         dcbCommPort.flags=0;
         //dcb.fBinary=1;
         dcbCommPort.flags|=1;
         if (Parity>0)
         {
            //dcb.fParity=1
            dcbCommPort.flags|=2;
         }
         dcbCommPort.Parity=Parity;
         dcbCommPort.ByteSize=ByteSize;
         dcbCommPort.StopBits=StopBits;
         if (!SetCommState(hComm, ref dcbCommPort))
         {
            //uint ErrorNum=GetLastError();
            throw(new ApplicationException("非法操作,不能打开串口!"));
         }
         //unremark to see if setting took correctly
         //DCB dcbCommPort2 = new DCB();
         //GetCommState(hComm, ref dcbCommPort2);
         Opened = true;
      }
      
      public void Close() {
         if (hComm!=INVALID_HANDLE_VALUE) {
            CloseHandle(hComm);
         }
      }
      
      public byte[] Read(int NumBytes) {
         byte[] BufBytes;
         byte[] OutBytes;
         BufBytes = new byte[NumBytes];
         if (hComm!=INVALID_HANDLE_VALUE) {
            OVERLAPPED ovlCommPort = new OVERLAPPED();
            int BytesRead=0;
            ReadFile(hComm,BufBytes,NumBytes,ref BytesRead,ref ovlCommPort);
            OutBytes = new byte[BytesRead];
            Array.Copy(BufBytes,OutBytes,BytesRead);
         }
         else {
            throw(new ApplicationException("串口未打开!"));
         }
         return OutBytes;
      }
      
      public void Write(byte[] WriteBytes) {
         if (hComm!=INVALID_HANDLE_VALUE) {
            OVERLAPPED ovlCommPort = new OVERLAPPED();
            int BytesWritten = 0;
            WriteFile(hComm,WriteBytes,WriteBytes.Length,ref BytesWritten,ref ovlCommPort);
         }
         else {
            throw(new ApplicationException("串口未打开!"));
         }
      }
   }
   
   class HexCon {
      // 把十六进制字符串转换成字节型和把字节型转换成十六进制字符串 converter hex string to byte and byte to hex string
      public static string ByteToString(byte[] InBytes) {
         string StringOut="";
         foreach (byte InByte in InBytes) {
            StringOut=StringOut + String.Format("{0:X2} ",InByte);
         }
         return StringOut;
      }
      public static byte[] StringToByte(string InString) {
         string[] ByteStrings;
         ByteStrings = InString.Split(" ".ToCharArray());
         byte[] ByteOut;
         ByteOut = new byte[ByteStrings.Length-1];
         for (int i = 0;i==ByteStrings.Length-1;i++) {
            ByteOut[i] = Convert.ToByte(("0x" + ByteStrings[i]));
         }
         return ByteOut;
      }
   }
}




版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
C/S框架网
上一篇:C#开发自定义控件-设置显示工具箱中的图标
下一篇:纯C#代码的Excel读取器(不需要Office Excel Com组件)
评论列表

发表评论

评论内容
昵称:
关联文章

C#串口通信编程
C#异步编程(多线程)
C#实现.Net Remoting服务端与客户端通信
基于WCF通信C/S系统快速开发框架的部分架构设计
OOP:面向对象编程
C# OOP编程 模拟做早餐探索同步异步机制
开发平台WCF架构(Web服务)使用压缩数据双向通信测试报告
软件开发与设计 - MIS-管理信息系统(福建XXX通信软件有限公司数据库设计)
HtmlAgilityPack编程 - HtmlDocument删除html的样式
HtmlAgilityPack编程 - 替换样式(style)的值
取消UpdateTotalAmount方法及改变编程方式
C#调用成员
C#四舍五入
MES软件开发工具|MES用什么编程语言开发更快速
HtmlAgilityPack编程 - 使用DocumentNode.InnerText去除HTML标签
C# WebService代理详解
C# ImageHelper 图片帮助
和对象
C# JsonSettings/JsonSerializerSettings参数设置
C#SQL注入攻击检查SQLInjection

热门标签
.NET5 .NET6 .NET7 APP Auth-软件授权注册系统 Axios B/S B/S开发框架 Bug Bug记录 C#加密解密 C#源码 C/S CHATGPT CMS系统 CodeGenerator CSFramework.DB CSFramework.EF CSFrameworkV1学习版 CSFrameworkV2标准版 CSFrameworkV3高级版 CSFrameworkV4企业版 CSFrameworkV5旗舰版 CSFrameworkV6.0 DAL数据访问层 Database datalock DbFramework Demo教学 Demo下载 DevExpress教程 DOM EF框架 Element-UI EntityFramework ERP ES6 Excel FastReport GIT HR IDatabase IIS JavaScript LINQ MES MiniFramework MIS NavBarControl Node.JS NPM OMS ORM PaaS POS Promise API Redis SAP SEO SQL SQLConnector TMS系统 Token令牌 VS2022 VSCode VUE WCF WebApi WebApi NETCore WebApi框架 WEB开发框架 Windows服务 Winform 开发框架 Winform 开发平台 WinFramework Workflow工作流 Workflow流程引擎 版本区别 报表 踩坑日记 操作手册 代码生成器 迭代开发记录 基础资料窗体 架构设计 角色权限 开发sce 开发技巧 开发教程 开发框架 开发平台 开发指南 客户案例 快速搭站系统 快速开发平台 秘钥 密钥 权限设计 软件报价 软件测试报告 软件简介 软件开发框架 软件开发平台 软件开发文档 软件体系架构 软件下载 软著证书 三层架构 设计模式 生成代码 实用小技巧 收钱音箱 数据锁 数据同步 微信小程序 未解决问题 文档下载 喜鹊ERP 喜鹊软件 系统对接 详细设计说明书 行政区域数据库 需求分析 疑难杂症 蝇量级框架 蝇量框架 用户管理 用户开发手册 用户控件 在线支付 纸箱ERP 智能语音收款机 自定义窗体 自定义组件 自动升级程序