c# 串口操作
public class CommPort : IDisposable
{
public string Port = "";
///<summary>
///波特率9600
///</summary>
private int BaudRate = 9600;
public int BaudRater
{
set { BaudRate = value; }
}
///<summary>
///数据位4-8
///</summary>
public byte ByteSize = 8; //4-8
///<summary>
///奇偶校验0-4=no,odd,even,mark,space
///</summary>
public byte Parity = 0; //0-4=no,odd,even,mark,space
///<summary>
///停止位
///</summary>
public byte StopBits = 0; //0,1,2 = 1, 1.5, 2
///<summary>
///超时长
///</summary>
private int ReadTimeout = 200;
public int ReadTimeouter
{
set { ReadTimeout = value; }
}
///<summary>
///串口是否已经打开
///</summary>
public bool Opened = false;
///<summary>
/// COM口句柄
///</summary>
private int hComm = -1;
#region "API相关定义"
private const string DLLPATH = "kernel32";
///<summary>
/// WINAPI常量,写标志
///</summary>
private const uint GENERIC_READ = 0x80000000;
///<summary>
/// WINAPI常量,读标志
///</summary>
private const uint GENERIC_WRITE = 0x40000000;
///<summary>
/// WINAPI常量,打开已存在
///</summary>
private const int OPEN_EXISTING = 3;
///<summary>
/// WINAPI常量,无效句柄
///</summary>
private const int INVALID_HANDLE_VALUE = -1;
private const int PURGE_RXABORT = 0x2;
private const int PURGE_RXCLEAR = 0x8;
private const int PURGE_TXABORT = 0x1;
private const int PURGE_TXCLEAR = 0x4;
///<summary>
///设备控制块结构体类型
///</summary>
[StructLayout(LayoutKind.Sequential)]
public struct DCB
{
///<summary>
/// DCB长度
///</summary>
public int DCBlength;
///<summary>
///指定当前波特率
///</summary>
public int BaudRate;
///<summary>
///标志位
///</summary>
public uint flags;
///<summary>
///未使用,必须为0
///</summary>
public ushort wReserved;
///<summary>
///指定在XON字符发送这前接收缓冲区中可允许的最小字节数
///</summary>
public ushort XonLim;
///<summary>
///指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数
///</summary>
public ushort XoffLim;
///<summary>
///指定端口当前使用的数据位
///</summary>
public byte ByteSize;
///<summary>
///指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space
///</summary>
public byte Parity;
///<summary>
///指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2
///</summary>
public byte StopBits;
///<summary>
///指定用于发送和接收字符XON的值 Tx and Rx XON character
///</summary>
public byte XonChar;
///<summary>
///指定用于发送和接收字符XOFF值 Tx and Rx XOFF character
///</summary>
public byte XoffChar;
///<summary>
///本字符用来代替接收到的奇偶校验发生错误时的值
///</summary>
public byte ErrorChar;
///<summary>
///当没有使用二进制模式时,本字符可用来指示数据的结束
///</summary>
public byte EofChar;
///<summary>
///当接收到此字符时,会产生一个事件
///</summary>
public byte EvtChar;
///<summary>
///未使用
///</summary>
public ushort wReserved1;
}
///<summary>
///串口超时时间结构体类型
///</summary>
[StructLayout(LayoutKind.Sequential)]
private struct COMMTIMEOUTS
{
public int ReadIntervalTimeout;
public int ReadTotalTimeoutMultiplier;
public int ReadTotalTimeoutConstant;
public int WriteTotalTimeoutMultiplier;
public int WriteTotalTimeoutConstant;
}
///<summary>
///溢出缓冲区结构体类型
///</summary>
[StructLayout(LayoutKind.Sequential)]
private struct OVERLAPPED
{
public int Internal;
public int InternalHigh;
public int Offset;
public int OffsetHigh;
public int hEvent;
}
///<summary>
///打开串口
///</summary>
///<param name="lpFileName">要打开的串口名称</param>
///<param name="dwDesiredAccess">指定串口的访问方式,一般设置为可读可写方式</param>
///<param name="dwShareMode">指定串口的共享模式,串口不能共享,所以设置为0</param>
///<param name="lpSecurityAttributes">设置串口的安全属性,WIN9X下不支持,应设为NULL</param>
///<param name="dwCreationDisposition">对于串口通信,创建方式只能为OPEN_EXISTING</param>
///<param name="dwFlagsAndAttributes">指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信</param>
///<param name="hTemplateFile">对于串口通信必须设置为NULL</param>
[DllImport(DLLPATH)]
private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode,
int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
///<summary>
///得到串口状态
///</summary>
///<param name="hFile">通信设备句柄</param>
///<param name="lpDCB">设备控制块DCB</param>
[DllImport(DLLPATH)]
private static extern bool GetCommState(int hFile, ref DCB lpDCB);
///<summary>
///建立串口设备控制块(嵌入版没有)
///</summary>
///<param name="lpDef">设备控制字符串</param>
///<param name="lpDCB">设备控制块</param>
//[DllImport(DLLPATH)]
//private static extern bool BuildCommDCB(string lpDef, ref DCB lpDCB);
///<summary>
///设置串口状态
///</summary>
///<param name="hFile">通信设备句柄</param>
///<param name="lpDCB">设备控制块</param>
[DllImport(DLLPATH)]
private static extern bool SetCommState(int hFile, ref DCB lpDCB);
///<summary>
///读取串口超时时间
///</summary>
///<param name="hFile">通信设备句柄</param>
///<param name="lpCommTimeouts">超时时间</param>
[DllImport(DLLPATH)]
private static extern bool GetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);
///<summary>
///设置串口超时时间
///</summary>
///<param name="hFile">通信设备句柄</param>
///<param name="lpCommTimeouts">超时时间</param>
[DllImport(DLLPATH)]
private static extern bool SetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);
///<summary>
///读取串口数据
///</summary>
///<param name="hFile">通信设备句柄</param>
///<param name="lpBuffer">数据缓冲区</param>
///<param name="nNumberOfBytesToRead">多少字节等待读取</param>
///<param name="lpNumberOfBytesRead">读取多少字节</param>
///<param name="lpOverlapped">溢出缓冲区</param>
[DllImport(DLLPATH)]
private static extern bool ReadFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToRead,
ref int lpNumberOfBytesRead, ref OVERLAPPED lpOverlapped);
///<summary>
///写串口数据
///</summary>
///<param name="hFile">通信设备句柄</param>
///<param name="lpBuffer">数据缓冲区</param>
///<param name="nNumberOfBytesToWrite">多少字节等待写入</param>
///<param name="lpNumberOfBytesWritten">已经写入多少字节</param>
///<param name="lpOverlapped">溢出缓冲区</param>
[DllImport(DLLPATH)]
private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite,
ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped);
[DllImport(DLLPATH, SetLastError = true)]
private static extern bool FlushFileBuffers(int hFile);
[DllImport(DLLPATH, SetLastError = true)]
private static extern bool PurgeComm(int hFile, uint dwFlags);
///<summary>
///关闭串口
///</summary>
///<param name="hObject">通信设备句柄</param>
[DllImport(DLLPATH)]
private static extern bool CloseHandle(int hObject);
///<summary>
///得到串口最后一次返回的错误
///</summary>
[DllImport(DLLPATH)]
private static extern uint GetLastError();
#endregion
///<summary>
///设置DCB标志位
///</summary>
///<param name="whichFlag"></param>
///<param name="setting"></param>
///<param name="dcb"></param>
internal void SetDcbFlag(int whichFlag, int setting, DCB dcb)
{
uint num;
setting = setting << whichFlag;
if ((whichFlag == 4) || (whichFlag == 12))
{
num = 3;
}
else if (whichFlag == 15)
{
num = 0x1ffff;
}
else
{
num = 1;
}
dcb.flags &= ~(num << whichFlag);
dcb.flags |= (uint)setting;
}
///<summary>
///建立与串口的连接
///</summary>
public int Open()
{
if (Port == "") return -1;
DCB dcb = new DCB();
COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
// 打开串口
hComm = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hComm == INVALID_HANDLE_VALUE)
{
return -1;
}
// 设置通信超时时间
GetCommTimeouts(hComm, ref ctoCommPort);
ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
ctoCommPort.ReadTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, ref ctoCommPort);
//设置串口参数
GetCommState(hComm, ref dcb);
dcb.DCBlength = Marshal.SizeOf(dcb);
dcb.BaudRate = BaudRate;
dcb.flags = 0;
dcb.ByteSize = (byte)ByteSize;
dcb.StopBits = StopBits;
dcb.Parity = (byte)Parity;
//------------------------------
SetDcbFlag(0, 1, dcb); //二进制方式
SetDcbFlag(1, (Parity == 0) ? 0 : 1, dcb);
SetDcbFlag(2, 0, dcb); //不用CTS检测发送流控制
SetDcbFlag(3, 0, dcb); //不用DSR检测发送流控制
SetDcbFlag(4, 0, dcb); //禁止DTR流量控制
SetDcbFlag(6, 0, dcb); //对DTR信号线不敏感
SetDcbFlag(9, 1, dcb); //检测接收缓冲区
SetDcbFlag(8, 0, dcb); //不做发送字符控制
SetDcbFlag(10, 0, dcb); //是否用指定字符替换校验错的字符
SetDcbFlag(11, 0, dcb); //保留NULL字符
SetDcbFlag(12, 0, dcb); //允许RTS流量控制
SetDcbFlag(14, 0, dcb); //发送错误后,继续进行下面的读写操作
//--------------------------------
dcb.wReserved = 0; //没有使用,必须为0
dcb.XonLim = 0; //指定在XOFF字符发送之前接收到缓冲区中可允许的最小字节数
dcb.XoffLim = 0; //指定在XOFF字符发送之前缓冲区中可允许的最小可用字节数
dcb.XonChar = 0; //发送和接收的XON字符
dcb.XoffChar = 0; //发送和接收的XOFF字符
dcb.ErrorChar = 0; //代替接收到奇偶校验错误的字符
dcb.EofChar = 0; //用来表示数据的结束
dcb.EvtChar = 0; //事件字符,接收到此字符时,会产生一个事件
dcb.wReserved1 = 0; //没有使用
if (!SetCommState(hComm, ref dcb))
{
return -2;
}
Opened = true;
return 0;
}
///<summary>
///关闭串口,结束通讯
///</summary>
public void Close()
{
try
{
if (hComm != INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
}
}
catch (Exception ex)
{
}
}
///<summary>
///读取串口返回的数据
///</summary>
///<param name="NumBytes">数据长度</param>
public int Read(ref byte[] bytData, int NumBytes)
{
try
{
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesRead = 0;
ReadFile(hComm, bytData, NumBytes, ref BytesRead, ref ovlCommPort);
return BytesRead;
}
else
{
return -1;
}
}
catch (Exception ex)
{
LogInfo log = new LogInfo();
log.WriteLog(ex.Message);
return -1;
}
}
///<summary>
///向串口写数据
///</summary>
///<param name="WriteBytes">数据数组</param>
public int Write(byte[] WriteBytes, int intSize)
{
try
{
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesWritten = 0;
WriteFile(hComm, WriteBytes, intSize, ref BytesWritten, ref ovlCommPort);
return BytesWritten;
}
else
{
return -1;
}
}
catch (Exception ex)
{
LogInfo log = new LogInfo();
log.WriteLog(ex.Message);
return -1;
}
}
///<summary>
///清除接收缓冲区
///</summary>
///<returns></returns>
public void ClearReceiveBuf()
{
if (hComm != INVALID_HANDLE_VALUE)
{
PurgeComm(hComm, PURGE_RXABORT | PURGE_RXCLEAR);
}
}
///<summary>
///清除发送缓冲区
///</summary>
public void ClearSendBuf()
{
if (hComm != INVALID_HANDLE_VALUE)
{
PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR);
}
}
public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "
{
string hexString = string.Empty;
if (bytes != null)
{
StringBuilder strB = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
strB.Append(" " + bytes[i].ToString("X2"));
}
hexString = strB.ToString();
}
return hexString;
}
#region IDisposable 成员
public void Dispose()
{
ClearSendBuf();
ClearReceiveBuf();
}
#endregion
}
c# 串口操作的更多相关文章
- C# 串口操作系列(3) -- 协议篇,二进制协议数据解析
原文地址:http://blog.csdn.net/wuyazhe/article/details/5627253 我们的串口程序,除了通用的,进行串口监听收发的简单工具,大多都和下位机有关,这就需要 ...
- C# 串口操作 ---- 系列文章
C# 串口操作系列(5)--通讯库雏形 通讯库雏形的建立. 串口通讯介绍的高级篇,介绍更高级的抽象,为扩展为通用的客户端通讯库做铺垫,扩展性的考虑,能支持任意类型的流设备. ... 2010-08-0 ...
- c#实现串口操作 SerialPort
命名空间:using System.IO.Ports;该类提供了同步 I/O 和事件驱动的 I/O.对管脚和中断状态的访问以及对串行驱动程序属性的访问. 操作类声明: SerialPort sp = ...
- C# 串口操作系列(5)--通讯库雏形
C# 串口操作系列(5)--通讯库雏形 标签: 通讯c#数据分析byteclassstring 2010-08-09 00:07 21378人阅读 评论(73) 收藏 举报 分类: 通讯类库设计(4 ...
- C# 串口操作系列(4) -- 协议篇,文本协议数据解析
C# 串口操作系列(4) -- 协议篇,文本协议数据解析 标签: c#uiobjectstringbyte 2010-06-09 01:50 19739人阅读 评论(26) 收藏 举报 分类: 通讯 ...
- 【转】C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子。
C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子. 标签: c#objectnewlineexceptionbytestring 2010-05-17 01:10 117109人阅读 ...
- V-rep学习笔记:串口操作
VREP Regular API提供了串口操作的相关函数,可以对串口进行打开.关闭和读写: 下面使用一款淘宝上常见的AHRS(Attitude and heading reference system ...
- Linux下串口操作之数据拼接
串口操作中,特别以非阻塞的方式读取和发送数据,做好进程之间的同步很重要.有时我们会发现这样一个问题,在进行read操作时,一次read不能获得一个完整的数据帧,这就好比你买了一个电脑,送货的先把显示器 ...
- 【C#】串口操作实用类
做工业通 信有很长时间了,特别是串口(232/485),有VB/VC/C各种版本的串口操作代码,这些代码也经过了多年的现场考验,应该说是比较健壮的代码,但 是目前却没有C#相对成熟的串口操作代码,最近 ...
- MATLAB串口操作和GUI编程
程序说明 V1.0 2015/2/08 MATLAB串口操作和GUI编程 概述 本文介绍了程序AD9512_Serial_GUI的编程思路和功能.该程序设计到MATLAB的图像用户界面编程的基 ...
随机推荐
- C#中如何应用索引器 ( How to use Indexers )
C#中索引器是个好东西, 可以允许类或者结构的实例像数组一样进行索引. 在foreach或者直接索引时很有用. 使用索引器可以简化客户端代码, 即调用者可以简化语法,直观理解类及其用途. 索引器只能根 ...
- MMU的理解
MMU内存管理单元相关知识点总结 1.MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器.物理存储器的控制线路,同时也负责虚 ...
- MySql介绍及优化(1)
mysql 数据库 1.是关系型数据库: 2.体积小.支持多处理器.开源.免费 3.在 Internet 中小型网站中的使用率尤其高 mysql 数据库开发常见问题及优化 一.库表设计 1.1 引擎选 ...
- eclipse中如何去除警告:Class is a raw type. References to generic type Class<T> should be parameterized
转自:https://blog.csdn.net/zwr_1022/article/details/78583872 解决前的源代码: public class test {public static ...
- JavaScript高级程序设计学习笔记第十三章--事件
事件冒泡: IE 的事件流,事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档).例如: <!DOCTYPE html> <htm ...
- c程序实现unicode字符转utf-8字符
下面是一个unicode字符转换为utf-8的c程序实现: /* * ================================================================= ...
- ubuntu 下交叉编译环境的搭建
1. 安装标准的C开发环境,由于Linux安装默认是不安装的,所以需要先安装一下(如果已经安装好的话,就可以免去这一步了): #sudo apt-get install gcc g++ libgcc1 ...
- CI框架中,判断post,ajax,get请求的方法
CI框架当中并没有提供,类似tp框架中IS_POST,IS_AJAX,IS_GET的方法. 所有就得我们自己造轮子了.下面就介绍一下,如何定义这些判断请求的方法.其实很简单的. 首先打开constan ...
- EntityFramework 中的链接研究初探
很多人用EF的默认链接工厂:System.Data.Entity.Infrastructure.LocalDbConnectionFactory 然后我一开始就不习惯,然后研究了一下,截图如下 然后就 ...
- ue4学习资料
官网中文 https://docs.unrealengine.com/latest/CHN/index.html 官网英文 https://docs.unrealengine.com/latest/I ...