串口通信类JustinIO.CommPort及使用方法

  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Text;
  4. namespace JustinIO
  5. {
  6.     public class CommPort
  7.     {
  8.         public string PortName;
  9.         public int BaudRate;
  10.         public byte DataBits;
  11.         public byte Parity; // 0-4=no,odd,even,mark,space 
  12.         public byte StopBits; // 0,1,2 = 1, 1.5, 2 
  13.         public int ReadTimeout;
  14.         //comm port win32 file handle
  15.         private int hComm = -1;
  16.         public bool Opened = false;
  17.         public bool IsOpen = false;
  18.         //win32 api constants
  19.         private const uint GENERIC_READ = 0x80000000;
  20.         private const uint GENERIC_WRITE = 0x40000000;
  21.         private const int OPEN_EXISTING = 3;
  22.         private const int INVALID_HANDLE_VALUE = -1;
  23.         [StructLayout(LayoutKind.Sequential)]
  24.         public struct DCB
  25.         {
  26.             //taken from c struct in platform sdk 
  27.             public int DCBlength; // sizeof(DCB) 
  28.             public int BaudRate; // 指定当前波特率 current baud rate
  29.             // these are the c struct bit fields, bit twiddle flag to set
  30.             public int fBinary; // 指定是否允许二进制模式,在windows95中必须主TRUE binary mode, no EOF check 
  31.             public int fParity; // 指定是否允许奇偶校验 enable parity checking 
  32.             public int fOutxCtsFlow; // 指定CTS是否用于检测发送控制,当为TRUE是CTS为OFF,发送将被挂起。 CTS output flow control 
  33.             public int fOutxDsrFlow; // 指定CTS是否用于检测发送控制 DSR output flow control 
  34.             public int fDtrControl; // DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手" DTR flow control type 
  35.             public int fDsrSensitivity; // 当该值为TRUE时DSR为OFF时接收的字节被忽略 DSR sensitivity 
  36.             public int fTXContinueOnXoff; // 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止。TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出XoffChar字符中止接收字节之后,发送继续进行。 FALSE时,在接收缓冲区接收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。XOFF continues Tx 
  37.             public int fOutX; // TRUE时,接收到XoffChar之后便停止发送接收到XonChar之后将重新开始 XON/XOFF out flow control 
  38.             public int fInX; // TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去 XON/XOFF in flow control 
  39.             public int fErrorChar; // 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字符 enable error replacement 
  40.             public int fNull; // eTRUE时,接收时去掉空(0值)字节 enable null stripping 
  41.             public int fRtsControl; // RTS flow control 
  42.             /*RTS_CONTROL_DISABLE时,RTS置为OFF
  43.               
  44.             RTS_CONTROL_ENABLE时, RTS置为ON
  45.             RTS_CONTROL_HANDSHAKE时,
  46.             当接收缓冲区小于半满时RTS为ON
  47.             当接收缓冲区超过四分之三满时RTS为OFF
  48.             RTS_CONTROL_TOGGLE时,
  49.             当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFF*/
  50.             public int fAbortOnError; // TRUE时,有错误发生时中止读和写操作 abort on error 
  51.             public int fDummy2; // 未使用 reserved 
  52.             public uint flags;
  53.             public ushort wReserved; // 未使用,必须为0 not currently used 
  54.             public ushort XonLim; // 指定在XON字符发送这前接收缓冲区中可允许的最小字节数 transmit XON threshold 
  55.             public ushort XoffLim; // 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数 transmit XOFF threshold 
  56.             public byte ByteSize; // 指定端口当前使用的数据位 number of bits/byte, 4-8 
  57.             public byte Parity; // 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space 
  58.             public byte StopBits; // 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2 
  59.             public char XonChar; // 指定用于发送和接收字符XON的值 Tx and Rx XON character 
  60.             public char XoffChar; // 指定用于发送和接收字符XOFF值 Tx and Rx XOFF character 
  61.             public char ErrorChar; // 本字符用来代替接收到的奇偶校验发生错误时的值 error replacement character 
  62.             public char EofChar; // 当没有使用二进制模式时,本字符可用来指示数据的结束 end of input character 
  63.             public char EvtChar; // 当接收到此字符时,会产生一个事件 received event character 
  64.             public ushort wReserved1; // 未使用 reserved; do not use 
  65.         }
  66.         [StructLayout(LayoutKind.Sequential)]
  67.         private struct COMMTIMEOUTS
  68.         {
  69.             public int ReadIntervalTimeout;
  70.             public int ReadTotalTimeoutMultiplier;
  71.             public int ReadTotalTimeoutConstant;
  72.             public int WriteTotalTimeoutMultiplier;
  73.             public int WriteTotalTimeoutConstant;
  74.         }
  75.         [StructLayout(LayoutKind.Sequential)]
  76.         private struct OVERLAPPED
  77.         {
  78.             public int Internal;
  79.             public int InternalHigh;
  80.             public int Offset;
  81.             public int OffsetHigh;
  82.             public int hEvent;
  83.         }
  84.         [DllImport("kernel32.dll")]
  85.         private static extern int CreateFile(
  86.         string lpFileName, // 要打开的串口名称
  87.         uint dwDesiredAccess, // 指定串口的访问方式,一般设置为可读可写方式
  88.         int dwShareMode, // 指定串口的共享模式,串口不能共享,所以设置为0
  89.         int lpSecurityAttributes, // 设置串口的安全属性,WIN9X下不支持,应设为NULL
  90.         int dwCreationDisposition, // 对于串口通信,创建方式只能为OPEN_EXISTING
  91.         int dwFlagsAndAttributes, // 指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信
  92.         int hTemplateFile // 对于串口通信必须设置为NULL
  93.         );
  94.         [DllImport("kernel32.dll")]
  95.         private static extern bool GetCommState(
  96.         int hFile, //通信设备句柄
  97.         ref DCB lpDCB // 设备控制块DCB
  98.         );
  99.         [DllImport("kernel32.dll")]
  100.         private static extern bool BuildCommDCB(
  101.         string lpDef, // 设备控制字符串
  102.         ref DCB lpDCB // 设备控制块
  103.         );
  104.         [DllImport("kernel32.dll")]
  105.         private static extern bool SetCommState(
  106.         int hFile, // 通信设备句柄
  107.         ref DCB lpDCB // 设备控制块
  108.         );
  109.         [DllImport("kernel32.dll")]
  110.         private static extern bool GetCommTimeouts(
  111.         int hFile, // 通信设备句柄 handle to comm device
  112.         ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values
  113.         );
  114.         [DllImport("kernel32.dll")]
  115.         private static extern bool SetCommTimeouts(
  116.         int hFile, // 通信设备句柄 handle to comm device
  117.         ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values
  118.         );
  119.         [DllImport("kernel32.dll")]
  120.         private static extern bool ReadFile(
  121.         int hFile, // 通信设备句柄 handle to file
  122.         byte[] lpBuffer, // 数据缓冲区 data buffer
  123.         int nNumberOfBytesToRead, // 多少字节等待读取 number of bytes to read
  124.         ref int lpNumberOfBytesRead, // 读取多少字节 number of bytes read
  125.         ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer
  126.         );
  127.         [DllImport("kernel32.dll")]
  128.         private static extern bool WriteFile(
  129.         int hFile, // 通信设备句柄 handle to file
  130.         byte[] lpBuffer, // 数据缓冲区 data buffer
  131.         int nNumberOfBytesToWrite, // 多少字节等待写入 number of bytes to write
  132.         ref int lpNumberOfBytesWritten, // 已经写入多少字节 number of bytes written
  133.         ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer
  134.         );
  135.         [DllImport("kernel32.dll")]
  136.         private static extern bool CloseHandle(
  137.         int hObject // handle to object
  138.         );
  139.         [DllImport("kernel32.dll")]
  140.         private static extern uint GetLastError();
  141.         public void Open()
  142.         {
  143.             DCB dcbCommPort = new DCB();
  144.             COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
  145.             // 打开串口 OPEN THE COMM PORT.
  146.             string num = PortName.Replace("COM""");
  147.             if (int.Parse(num) >= 10)
  148.                 hComm = CreateFile("//./"" + PortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  149.             else
  150.                 hComm = CreateFile(PortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  151.             // 如果串口没有打开,就打开 IF THE PORT CANNOT BE OPENED, BAIL OUT.
  152.             if (hComm == INVALID_HANDLE_VALUE)
  153.             {
  154.                 throw (new Exception("非法操作,不能打开串口!"));
  155.             }
  156.             // 设置通信超时时间 SET THE COMM TIMEOUTS.
  157.             GetCommTimeouts(hComm, ref ctoCommPort);
  158.             ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
  159.             ctoCommPort.ReadTotalTimeoutMultiplier = 0;
  160.             ctoCommPort.WriteTotalTimeoutMultiplier = 0;
  161.             ctoCommPort.WriteTotalTimeoutConstant = 0;
  162.             SetCommTimeouts(hComm, ref ctoCommPort);
  163.             // 设置串口 SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
  164.             GetCommState(hComm, ref dcbCommPort);
  165.             dcbCommPort.BaudRate = BaudRate;
  166.             dcbCommPort.flags = 0;
  167.             //dcb.fBinary=1;
  168.             dcbCommPort.flags |= 1;
  169.             if (Parity > 0)
  170.             {
  171.                 //dcb.fParity=1
  172.                 dcbCommPort.flags |= 2;
  173.             }
  174.             dcbCommPort.Parity = Parity;
  175.             dcbCommPort.ByteSize = DataBits;
  176.             dcbCommPort.StopBits = StopBits;
  177.             if (!SetCommState(hComm, ref dcbCommPort))
  178.             {
  179.                 //uint ErrorNum=GetLastError();
  180.                 throw (new ApplicationException("非法操作,不能打开串口!"));
  181.             }
  182.             //unremark to see if setting took correctly
  183.             //DCB dcbCommPort2 = new DCB();
  184.             //GetCommState(hComm, ref dcbCommPort2);
  185.             Opened = true;
  186.             IsOpen = true;
  187.         }
  188.         public void Close()
  189.         {
  190.             if (hComm != INVALID_HANDLE_VALUE)
  191.             {
  192.                 CloseHandle(hComm);
  193.             }
  194.         }
  195.         public byte[] Read(int NumBytes)
  196.         {
  197.             byte[] BufBytes;
  198.             byte[] OutBytes;
  199.             BufBytes = new byte[NumBytes];
  200.             if (hComm != INVALID_HANDLE_VALUE)
  201.             {
  202.                 OVERLAPPED ovlCommPort = new OVERLAPPED();
  203.                 int BytesRead = 0;
  204.                 ReadFile(hComm, BufBytes, NumBytes, ref BytesRead, ref ovlCommPort);
  205.                 OutBytes = new byte[BytesRead];
  206.                 Array.Copy(BufBytes, OutBytes, BytesRead);
  207.             }
  208.             else
  209.             {
  210.                 throw (new ApplicationException("串口未打开!"));
  211.             }
  212.             return OutBytes;
  213.         }
  214.         public string ReadExisting()
  215.         {
  216.             return Encoding.ASCII.GetString(Read(128));
  217.         }
  218.         public void Write(byte[] WriteBytes)
  219.         {
  220.             if (hComm != INVALID_HANDLE_VALUE)
  221.             {
  222.                 OVERLAPPED ovlCommPort = new OVERLAPPED();
  223.                 int BytesWritten = 0;
  224.                 WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
  225.             }
  226.             else
  227.             {
  228.                 throw (new ApplicationException("串口未打开!"));
  229.             }
  230.         }
  231.         public void Write(string WriteString, Encoding CoderType)
  232.         {
  233.             Write(CoderType.GetBytes(WriteString));
  234.         }
  235.         public void Write(string WriteString)
  236.         {
  237.             Write(Encoding.ASCII.GetBytes(WriteString));
  238.         }
  239.     }
  240. }

介绍JustinIO的使用方法: 

打开串口: 

函数原型:public void Open() 

说明:打开事先设置好的端口 

示例: 

using JustinIO; 

static JustinIO.CommPort ss_port = new JustinIO.CommPort(); 
ss_port.PortNum = COM1; //端口号 
ss_port.BaudRate = 19200; //串口通信波特率 
ss_port.ByteSize = 8; //数据位 
ss_port.Parity = 0; //奇偶校验 
ss_port.StopBits = 1;//停止位 
ss_port.ReadTimeout = 1000; //读超时 
try 

if (ss_port.Opened) 

ss_port.Close(); 
ss_port.Open(); //打开串口 

else 

ss_port.Open();//打开串口 

return true; 

catch(Exception e) 

MessageBox.Show("错误:" + e.Message); 
return false; 


写串口: 

函数原型:public void Write(byte[] WriteBytes) 

WriteBytes 就是你的写入的字节,注意,字符串要转换成字节数组才能进行通信 

示例: 

ss_port.Write(Encoding.ASCII.GetBytes("AT+CGMI/r")); //获取手机品牌 

读串口: 

函数原型:public byte[] Read(int NumBytes) 

NumBytes 读入缓存数,注意读取来的是字节数组,要实际应用中要进行字符转换 

示例: 

string response = Encoding.ASCII.GetString(ss_port.Read(128)); //读取128个字节缓存 

关闭串口: 

函数原型:ss_port.Close() 

示例: 

ss_port.Close(); 




这个好像有点问题啊,网上查了下,Close方法里面需要加个Opened=false;但是如果打开串口,连续关闭2次串口就报错了,不知道怎么解决。


你可能感兴趣的:(C#)