在C#中实现串口通信的常用方法


本文主要是讲述如何通过C# .net1.1平台调用API操作串口,.net2.0已经内置串口操作类!

通常,在C#中实现串口通信,我们有四种方法:

第一:通过MSCOMM控件这是最简单的,最方便的方法。可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册。可以访问
http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=320
一个外国人写的教程
第二:微软在.NET新推出了一个串口控件,基于.NET的P/Invoke调用方法实现,详细的可以访问微软网站
Serial Comm
Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications

http://msdn.microsoft.com/msdnmag/issues/02/10/netserialcomm/
第三:就是用第三方控件啦,可一般都要付费的,不太合实际,何况楼主不喜欢,不作考虑
第四:自己用API写串口通信,这样难度高点,但对于我们来说,可以方便实现自己想要的各种功能。

我们采用第四种方法来实现串口通信,用现成的已经封装好的类库,常见两个串口操作类是JustinIO和SerialStreamReader。介绍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();

整合代码:

 

using System; 
using System.Runtime.InteropServices; 

namespace JustinIO { 
class CommPort { 

public int 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; // 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 uint flags; 
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 
); 
[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("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. 
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("Comm Port Can Not Be Opened")); 
} 
//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("Comm Port Not Open")); 
} 
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("Comm Port Not Open")); 
} 
} 
} 

} 
} 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值