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() 

說明:打開事先設置好的端口 

示例: 


[csharp] view plaincopyprint?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;   
}   

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(); 

整合代碼: 


[csharp] view plaincopyprint?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"));   
}   
}   
}   
  
}   
}   

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")); 
} 
} 
} 

} 
} 


 

C#中使用SerialPort類實現串口通信

在.NET Framework 2.0中提供了SerialPort類,該類主要實現串口數據通信等。本文章將本人在學習過程中從網絡上搜集到的相關信息寫出來供大家參考。

下面主要介紹該類的主要屬性(表1)和方法(表.2)。

如果需要了解更多的信息請登錄http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(VS.80).aspx查看。

相關文章

《使用System.IO.Ports讀取COM口數據》

http://www.devasp.net/net/articles/display/727.html



表1                                                      SerialPort類的常用屬性

名  稱
 說  明
 
BaseStream
 獲取 SerialPort 對象的基礎 Stream 對象
 
BaudRate
 獲取或設置串行波特率
 
BreakState
 獲取或設置中斷信號狀態
 
BytesToRead
 獲取接收緩沖區中數據的字節數
 
BytesToWrite
 獲取發送緩沖區中數據的字節數
 
CDHolding
 獲取端口的載波檢測行的狀態
 
CtsHolding
 獲取“可以發送”行的狀態
 
DataBits
 獲取或設置每個字節的標准數據位長度
 
DiscardNull
 獲取或設置一個值,該值指示 Null 字節在端口和接收緩沖區之間傳輸時是否被忽略
 
DsrHolding
 獲取數據設置就緒 (DSR) 信號的狀態
 
DtrEnable
 獲取或設置一個值,該值在串行通信過程中啟用數據終端就緒 (DTR) 信號
 
Encoding
 獲取或設置傳輸前后文本轉換的字節編碼
 
Handshake
 獲取或設置串行端口數據傳輸的握手協議
 
IsOpen
 獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態
 
NewLine
 獲取或設置用於解釋 ReadLine( )和WriteLine( )方法調用結束的值
 
Parity
 獲取或設置奇偶校驗檢查協議
 

續表

名  稱
 說  明
 
ParityReplace
 獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節
 
PortName
 獲取或設置通信端口,包括但不限於所有可用的 COM 端口
 
ReadBufferSize
 獲取或設置 SerialPort 輸入緩沖區的大小
 
ReadTimeout
 獲取或設置讀取操作未完成時發生超時之前的毫秒數
 
ReceivedBytesThreshold
 獲取或設置 DataReceived 事件發生前內部輸入緩沖區中的字節數
 
RtsEnable
 獲取或設置一個值,該值指示在串行通信中是否啟用請求發送 (RTS) 信號
 
StopBits
 獲取或設置每個字節的標准停止位數
 
WriteBufferSize
 獲取或設置串行端口輸出緩沖區的大小
 
WriteTimeout
 獲取或設置寫入操作未完成時發生超時之前的毫秒數
 

表2                                                     SerialPort類的常用方法

方 法 名 稱
 說  明
 
Close
 關閉端口連接,將 IsOpen 屬性設置為False,並釋放內部 Stream 對象
 
Open
 打開一個新的串行端口連接
 
Read
 從 SerialPort 輸入緩沖區中讀取
 
ReadByte
 從 SerialPort 輸入緩沖區中同步讀取一個字節
 
ReadChar
 從 SerialPort 輸入緩沖區中同步讀取一個字符
 
ReadLine
 一直讀取到輸入緩沖區中的 NewLine 值
 
ReadTo
 一直讀取到輸入緩沖區中指定 value 的字符串
 
Write
 已重載。將數據寫入串行端口輸出緩沖區
 
WriteLine
 將指定的字符串和 NewLine 值寫入輸出緩沖區
 


使用SerialPort類的方法:

方法一:

首先要添加

using System.IO;
using System.IO.Ports;

1...在類的內部定義SerialPort com;

2...打開串口

            com = new SerialPort();
            com.BaudRate = 115200;
            com.PortName = "COM1";
            com.DataBits = 8;
            com.Open();//打開串口

3...發送數據

            Byte[] TxData ={1,2,3,4,5,6,7,8 };
            com.Write(TxData, 0, 8);

4...接收數據

     4.1使用事件接收

     this.com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);

private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)

    4.2使用線程接收

     接收數據啟動一個線程,使其接收。

在類的內部定義

        Thread _readThread;
        bool _keepReading;

打開串口后啟動線程

            _keepReading = true;
            _readThread = new Thread(ReadPort);
            _readThread.Start();

線程函數

[csharp] view plaincopyprint?private void ReadPort()  
{  
    while (_keepReading)  
    {  
        if (com.IsOpen)  
        {  
            byte[] readBuffer = new byte[com.ReadBufferSize + 1];  
            try  
            {  
                // If there are bytes available on the serial port,   
                // Read returns up to "count" bytes, but will not block (wait)   
                // for the remaining bytes. If there are no bytes available   
                // on the serial port, Read will block until at least one byte   
                // is available on the port, up until the ReadTimeout milliseconds   
                // have elapsed, at which time a TimeoutException will be thrown.   
                int count = com.Read(readBuffer, 0, com.ReadBufferSize);  
                String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);  
                if (count != 0)  
                    //byteToHexStr(readBuffer);   
                    ThreadFunction(byteToHexStr(readBuffer,count));  
            }  
            catch (TimeoutException) { }  
        }  
        else  
        {  
            TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);  
            Thread.Sleep(waitTime);  
        }  
    }  
}  

        private void ReadPort()
        {
            while (_keepReading)
            {
                if (com.IsOpen)
                {
                    byte[] readBuffer = new byte[com.ReadBufferSize + 1];
                    try
                    {
                        // If there are bytes available on the serial port,
                        // Read returns up to "count" bytes, but will not block (wait)
                        // for the remaining bytes. If there are no bytes available
                        // on the serial port, Read will block until at least one byte
                        // is available on the port, up until the ReadTimeout milliseconds
                        // have elapsed, at which time a TimeoutException will be thrown.
                        int count = com.Read(readBuffer, 0, com.ReadBufferSize);
                        String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
                        if (count != 0)
                            //byteToHexStr(readBuffer);
                            ThreadFunction(byteToHexStr(readBuffer,count));
                    }
                    catch (TimeoutException) { }
                }
                else
                {
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
                    Thread.Sleep(waitTime);
                }
            }
        }



方法二:使用C#自帶的SerialPor控件。

1...在“工具箱”的“組件”中選擇SerialPor控件添加。

2...設置串口並打開

serialPort1.PortName = "COM1";

serialPort1.BaudRate = 9600;

serialPort1.Open();

3...寫入數據可以使用Write或者下面的函數

serialPort1.WriteLine(str);

4...添加數據接收的事件

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)


使用中的一些常見問題

C#中SerialPort類中DataReceived事件GUI實時處理方法(來自wanglei_wan@yahoo.com.cn 的看法)
MSDN:從 SerialPort 對象接收數據時,將在輔助線程上引發 DataReceived 事件。由於此事件在輔助線程而非主線程上引發,因此嘗試修改主線程中的一些元素(如 UI 元素)時會引發線程異常。如果有必要修改主 Form 或 Control 中的元素,必須使用 Invoke 回發更改請求,這將在正確的線程上執行.進而要想將輔助線程中所讀到的數據顯示到主線程的Form控件上時,只有通過Invoke方法來實現 
下面是代碼實例: 


[csharp] view plaincopyprint?private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)  
{  
   int SDateTemp = this.serialPort1.ReadByte();  
   //讀取串口中一個字節的數據   
   this.tB_ReceiveDate.Invoke(     
    //在擁有此控件的基礎窗口句柄的線程上執行委托Invoke(Delegate)   
    //即在textBox_ReceiveDate控件的父窗口form中執行委托.   
    new MethodInvoker(              
    /*表示一個委托,該委托可執行托管代碼中聲明為 void 且不接受任何參數的任何方法。 在對控件的 Invoke    方法進行調用時或需要一個簡單委托又不想自己定義時可以使用該委托。*/  
    delegate{                   
    /*匿名方法,C#2.0的新功能,這是一種允許程序員將一段完整代碼區塊當成參數傳遞的程序代碼編寫技術,通過此種方法可  以直接使用委托來設計事件響應程序以下就是你要在主線程上實現的功能但是有一點要注意,這里不適宜處理過多的方法,因為C#消息機制是消息流水線響應機制,如果這里在主線程上處理語句的時間過長會導致主UI線程阻塞,停止響應或響應不順暢,這時你的主form界面會延遲或卡死      */                     
    this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//輸出到主窗口文本控件   
    this.tB_ReceiveDate.Text += " ";}  
    )  
    );  
}  

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   int SDateTemp = this.serialPort1.ReadByte();
   //讀取串口中一個字節的數據
   this.tB_ReceiveDate.Invoke(   
	//在擁有此控件的基礎窗口句柄的線程上執行委托Invoke(Delegate)
	//即在textBox_ReceiveDate控件的父窗口form中執行委托.
	new MethodInvoker(            
	/*表示一個委托,該委托可執行托管代碼中聲明為 void 且不接受任何參數的任何方法。 在對控件的 Invoke 	方法進行調用時或需要一個簡單委托又不想自己定義時可以使用該委托。*/
	delegate{                 
    /*匿名方法,C#2.0的新功能,這是一種允許程序員將一段完整代碼區塊當成參數傳遞的程序代碼編寫技術,通過此種方法可 	以直接使用委托來設計事件響應程序以下就是你要在主線程上實現的功能但是有一點要注意,這里不適宜處理過多的方法,因為C#消息機制是消息流水線響應機制,如果這里在主線程上處理語句的時間過長會導致主UI線程阻塞,停止響應或響應不順暢,這時你的主form界面會延遲或卡死      */                   
	this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//輸出到主窗口文本控件
	this.tB_ReceiveDate.Text += " ";}
    )
    );
}

如何知道當前電腦有哪個串口

在窗體上添加一個comboBox控件。

然后使用comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());  或者

string[] portList = System.IO.Ports.SerialPort.GetPortNames();
            for (int i = 0; i < portList.Length; ++i)
            {
                string name = portList[i];
                comboBox1.Items.Add(name);
            }

具體請參考http://msdn.microsoft.com/zh-tw/library/system.io.ports.serialport.getportnames.aspx

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM