1. 程式人生 > >SerialPort類的用法與示例

SerialPort類的用法與示例

try dispose lose ports cfb prope .html 緩存 pst

轉: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
        }
    }
}
技術分享圖片

SerialPort類的用法與示例