轉:https://www.cnblogs.com/hwBeta/p/6926363.html
Microsoft .Net框架SerialPort類的用法與示例
從Microsoft .Net 2.0版本以后,就默認提供了System.IO.Ports.SerialPort類,用戶可以非常簡單地編寫少量代碼就完成串口的信息收發程序。本文將介紹如何在PC端用C# .Net 來開發串口應用程序。
1. 串口硬件信號定義
DB9 Connector 信號定義
|
針腳
|
信號
|
定義
|
作用
|
|
1
|
DCD
|
載波檢測
|
Received Line Signal Detector(Data Carrier Detect)
|
|
2
|
RXD
|
接收數據
|
Received Data
|
|
3
|
TXD
|
發送數據
|
Transmit Data
|
|
4
|
DTR
|
數據終端准備好
|
Data Terminal Ready
|
|
5
|
SGND
|
信號地
|
Signal Ground
|
|
6
|
DSR
|
數據准備好
|
Data Set Ready
|
|
7
|
RTS
|
請求發送
|
Request To Send
|
|
8
|
CTS
|
清除發送
|
Clear To Send
|
|
9
|
RI
|
振鈴提示
|
Ring Indicator
|
2. 串口端口號搜索
一個最簡單的辦法:
string[] portList = System.IO.Ports.SerialPort.GetPortNames();
for (int i = 0; i < portList.Length; i++)
{
string name = portList[i];
comboBox.Items.Add(name);
}
還有一種通過調用API的方法來獲取實現,可以獲取詳細的完整串口名稱,對於USB-to-COM虛擬串口來說特別適用。
通過下面程序可以獲取到與設備管理器中一樣的名字,例如“Prolific USB-to-Serial Comm Port(COM34)”, 而上面的方法只能獲取到“COM34”。
/// <summary>
/// 枚舉win32 api
/// </summary>
public enum HardwareEnum
{
// 硬件
Win32_Processor, // CPU 處理器
Win32_PhysicalMemory, // 物理內存條
Win32_Keyboard, // 鍵盤
Win32_PointingDevice, // 點輸入設備,包括鼠標。
Win32_FloppyDrive, // 軟盤驅動器
Win32_DiskDrive, // 硬盤驅動器
Win32_CDROMDrive, // 光盤驅動器
Win32_BaseBoard, // 主板
Win32_BIOS, // BIOS 芯片
Win32_ParallelPort, // 並口
Win32_SerialPort, // 串口
Win32_SerialPortConfiguration, // 串口配置
Win32_SoundDevice, // 多媒體設置,一般指聲卡。
Win32_SystemSlot, // 主板插槽 (ISA & PCI & AGP)
Win32_USBController, // USB 控制器
Win32_NetworkAdapter, // 網絡適配器
Win32_NetworkAdapterConfiguration, // 網絡適配器設置
Win32_Printer, // 打印機
Win32_PrinterConfiguration, // 打印機設置
Win32_PrintJob, // 打印機任務
Win32_TCPIPPrinterPort, // 打印機端口
Win32_POTSModem, // MODEM
Win32_POTSModemToSerialPort, // MODEM 端口
Win32_DesktopMonitor, // 顯示器
Win32_DisplayConfiguration, // 顯卡
Win32_DisplayControllerConfiguration, // 顯卡設置
Win32_VideoController, // 顯卡細節。
Win32_VideoSettings, // 顯卡支持的顯示模式。
// 操作系統
Win32_TimeZone, // 時區
Win32_SystemDriver, // 驅動程序
Win32_DiskPartition, // 磁盤分區
Win32_LogicalDisk, // 邏輯磁盤
Win32_LogicalDiskToPartition, // 邏輯磁盤所在分區及始末位置。
Win32_LogicalMemoryConfiguration, // 邏輯內存配置
Win32_PageFile, // 系統頁文件信息
Win32_PageFileSetting, // 頁文件設置
Win32_BootConfiguration, // 系統啟動配置
Win32_ComputerSystem, // 計算機信息簡要
Win32_OperatingSystem, // 操作系統信息
Win32_StartupCommand, // 系統自動啟動程序
Win32_Service, // 系統安裝的服務
Win32_Group, // 系統管理組
Win32_GroupUser, // 系統組帳號
Win32_UserAccount, // 用戶帳號
Win32_Process, // 系統進程
Win32_Thread, // 系統線程
Win32_Share, // 共享
Win32_NetworkClient, // 已安裝的網絡客戶端
Win32_NetworkProtocol, // 已安裝的網絡協議
Win32_PnPEntity,//all device
}
/// <summary>
/// WMI取硬件信息
/// </summary>
/// <param name="hardType"></param>
/// <param name="propKey"></param>
/// <returns></returns>
public static string[] MulGetHardwareInfo(HardwareEnum hardType, string propKey)
{
List<string> strs = new List<string>();
try
{
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + hardType))
{
var hardInfos = searcher.Get();
foreach (var hardInfo in hardInfos)
{
if (hardInfo.Properties[propKey].Value.ToString().Contains("COM"))
{
strs.Add(hardInfo.Properties[propKey].Value.ToString());
}
}
searcher.Dispose();
}
return strs.ToArray();
}
catch
{
return null;
}
finally
{ strs = null; }
}
//通過WMI獲取COM端口
string[] portList = MulGetHardwareInfo(HardwareEnum.Win32_PnPEntity, "Name");
3. 串口屬性參數設置
參見MSDN上的幫助文件,SerialPort類所包含的屬性詳見下表。
| 名稱 | 說明 | |
|---|---|---|
![]() |
BaseStream |
獲取 Stream 對象的基礎 SerialPort 對象。 |
![]() |
BaudRate |
獲取或設置串行波特率。 |
![]() |
BreakState |
獲取或設置中斷信號狀態。 |
![]() |
BytesToRead |
獲取接收緩沖區中數據的字節數。 |
![]() |
BytesToWrite |
獲取發送緩沖區中數據的字節數。 |
![]() |
CanRaiseEvents |
獲取一個值,該值指示組件是否可以引發一個事件。(繼承自 Component。) |
![]() |
CDHolding |
獲取端口的載波檢測行的狀態。 |
![]() |
Container |
獲取 IContainer ,其中包含 Component。(繼承自 Component。) |
![]() |
CtsHolding |
獲取“可以發送”行的狀態。 |
![]() |
DataBits |
獲取或設置每個字節的標准數據位長度。 |
![]() |
DesignMode |
獲取一個值,該值指示是否 Component 當前處於設計模式。(繼承自 Component。) |
![]() |
DiscardNull |
獲取或設置一個值,該值指示 null 字節在端口和接收緩沖區之間傳輸時是否被忽略。 |
![]() |
DsrHolding |
獲取數據設置就緒 (DSR) 信號的狀態。 |
![]() |
DtrEnable |
獲取或設置一個值,該值在串行通信過程中啟用數據終端就緒 (DTR) 信號。 |
![]() |
Encoding |
獲取或設置傳輸前后文本轉換的字節編碼。 |
![]() |
Events |
獲取的事件處理程序附加到此列表 Component。(繼承自 Component。) |
![]() |
Handshake |
使用 Handshake 中的值獲取或設置串行端口數據傳輸的握手協議。 |
![]() |
IsOpen |
獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態。 |
![]() |
NewLine |
獲取或設置用於解釋 ReadLine 和 WriteLine 方法調用結束的值。 |
![]() |
Parity |
獲取或設置奇偶校驗檢查協議。 |
![]() |
ParityReplace |
獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節。 |
![]() |
PortName |
獲取或設置通信端口,包括但不限於所有可用的 COM 端口。 |
![]() |
ReadBufferSize |
獲取或設置 SerialPort 輸入緩沖區的大小。 |
![]() |
ReadTimeout |
獲取或設置讀取操作未完成時發生超時之前的毫秒數。 |
![]() |
ReceivedBytesThreshold |
獲取或設置 DataReceived 事件發生前內部輸入緩沖區中的字節數。 |
![]() |
RtsEnable |
獲取或設置一個值,該值指示在串行通信中是否啟用請求發送 (RTS) 信號。 |
![]() |
Site |
獲取或設置 ISite 的 Component。(繼承自 Component。) |
![]() |
StopBits |
獲取或設置每個字節的標准停止位數。 |
![]() |
WriteBufferSize |
獲取或設置串行端口輸出緩沖區的大小。 |
![]() |
WriteTimeout |
獲取或設置寫入操作未完成時發生超時之前的毫秒數。 |
簡單初始化串口參數的示例程序:
SerialPort mySerialPort = new SerialPort("COM2");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity=Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.Non;
mySerialPort.DataReceived += new SerialDataReceivedEvenHandler(DataReceive_Method);
mySerialPort.Open();
4. 串口發送信息
SerialPort類定義了多種方法用於串口發送信息。
Write(Byte[], Int32, Int32) 使用緩沖區中的數據將指定數量的字節寫入串行端口
Write(Char[], Int32, Int32) 使用緩沖區中的數據將指定數量的字符寫入串行端口
Write(String) 將指定的字符串寫入串行端口
WriteLine(String) 將指定的字符串和NewLine值寫入輸出緩沖區
下面是一個簡單的例子說明如何通過串口發送字符串和字節數據:
using System.IO.Ports;
private static void SendSampleData()
{
// Instantiate the communications
// port with some basic settings
SerialPort port = new SerialPort(
"COM1", 9600, Parity.None, 8, StopBits.One);
// Open the port for communications
port.Open();
// Write a string
port.Write("Hello World");
// Write a set of bytes
port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);
// Close the port
port.Close();
}
下面是如何發送一個文本文件的例子:
private static void SendTextFile(SerialPort port, string FileName)
{
port.Write(File.OpenText(FileName).ReadToEnd());
}
下面是如何發送一個二進制文件的例子:
private static void SendBinaryFile(SerialPort port, string FileName)
{
using (FileStream fs = File.OpenRead(FileName))
port.Write((new BinaryReader(fs)).ReadBytes((int)fs.Length), 0, (int)fs.Length);
}
5. 串口接收信息
SerialPort類定義了多種方法用於串口接收信息。
Read(Byte[], Int32, Int32) 從SerialPort輸入緩沖區讀取一些字節,並將那些字節寫入字節數組中指定的偏移量處
Read(Byte[], Int32, Int32) 從SerialPort輸入緩沖區讀取一些字符,並將那些字符寫入字符數組中指定的偏移量處
ReadByte() 從SerialPort輸入緩沖區中同步讀取一個字節
ReadChar() 從SerialPort輸入緩沖區中同步讀取一個字符
ReadExisting() 在編碼的基礎上,讀取SerialPort對象的流和輸入緩沖區中所有立即可用的字節
ReadLine() 一直讀取到輸入緩沖區中的NewLine值
ReadTo(String) 一直讀取到輸入緩沖區中的指定value的字符串
通常一個比較常見的用法就是將串口里面立即能用的字符或數據讀取然后打印在textbox等控件中顯示。
#region Namespace Inclusions
using System;
using System.IO.Ports;
using System.Windows.Forms;
#endregion
namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1",
9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}
private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there
// is data waiting in the port's buffer
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
port.Open();
// Enter an application loop to keep this thread alive
Application.Run();
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}
另外還有一種應用場合是需要緩存一段串口接收數據,然后在緩存數據中查找有用信息,這時可以采用下面例子所用的辦法。
using System;
using System.IO.Ports;
using System.Collections.Generic;
namespace SerialComBuffering
{
class Program
{
SerialPort com = new SerialPort(SerialPort.GetPortNames()[0],
9600, Parity.None, 8, StopBits.One);
List<byte> bBuffer = new List<byte>();
string sBuffer = String.Empty;
static void Main(string[] args)
{ new Program(); }
Program()
{
com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
com.Open();
Console.WriteLine("Waiting for incoming data...");
Console.ReadKey();
}
void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Use either the binary OR the string technique (but not both)
// Buffer and process binary data
while (com.BytesToRead > 0)
bBuffer.Add((byte)com.ReadByte());
ProcessBuffer(bBuffer);
// Buffer string data
sBuffer += com.ReadExisting();
ProcessBuffer(sBuffer);
}
private void ProcessBuffer(string sBuffer)
{
// Look in the string for useful information
// then remove the useful data from the buffer
}
private void ProcessBuffer(List<byte> bBuffer)
{
// Look in the byte array for useful information
// then remove the useful data from the buffer
}
}
}




