首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 串口通訊實用類別:PortData 核心實作與 SendCommand 同步收發模式

     編輯:關於C語言

設計動機

工業現場長期使用 VB/VC/C 串口程式碼,C# 缺乏成熟對應版本。針對 Moxa 設備於 WinCE 5.0 開發,擴充完善串口操作類,特別強化 SendCommand 同步收發模式,避免事件/執行緒非同步複雜度。

PortData 類別核心架構

建構與初始化

public PortData(string portName, int baudRate, Parity parity, SerialMode mode)
{
    port = new SerialPort(portName, baudRate, parity, 8, StopBits.One);
    port.RtsEnable = true;
    port.ReadTimeout = 3000;
    port.DataReceived += DataReceived;
    port.ErrorReceived += ErrorEvent;
}

核心方法

同步指令收發 - SendCommand

public int SendCommand(byte[] sendData, ref byte[] receiveData, int overtime)
{
    if (!port.IsOpen) return -1;

    ReceiveEventFlag = true;           // 暫停事件接收
    port.DiscardInBuffer();            // 清空接收緩衝區
    port.Write(sendData, 0, sendData.Length);

    int num = 0, ret = 0;
    while (num++ < overtime)
    {
        if (port.BytesToRead >= receiveData.Length) break;
        Thread.Sleep(1);
    }

    if (port.BytesToRead >= receiveData.Length)
        ret = port.Read(receiveData, 0, receiveData.Length);

    ReceiveEventFlag = false;          // 恢復事件接收
    return ret;
}

設計精華:透過 ReceiveEventFlag 暫停事件驅動接收,改用輪詢方式在指定逾時內同步等待預期長度資料,適合主從式請求-回應協定。

事件驅動接收 - DataReceived

public void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (ReceiveEventFlag) return;  // 命令模式下忽略事件
    
    byte[] data = new byte[port.BytesToRead];
    port.Read(data, 0, data.Length);
    if (Received != null) Received(sender, new PortDataReciveEventArgs(data));
}

完整類別定義

public class PortData
{
    public event PortDataReceivedEventHandle Received;
    public event SerialErrorReceivedEventHandler Error;
    public SerialPort port;
    public bool ReceiveEventFlag = false;
    
    // 建構子、Open/Close、SendData、SendCommand、ErrorEvent、DataReceived、IsOpen
    // ... 完整程式碼見原文 ...
}

public delegate void PortDataReceivedEventHandle(object sender, PortDataReciveEventArgs e);

public class PortDataReciveEventArgs : EventArgs
{
    public byte[] Data { get; set; }
    public PortDataReciveEventArgs() { }
    public PortDataReciveEventArgs(byte[] data) { this.Data = data; }
}

連接埠命名注意事項

COM1~COM9 使用 "COMx:";COM10 以上舊版用 \\.\COMx:,但 Moxa 661 需用 $device\COM{PortNo}\0 格式,可能因驅動程式差異所致。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved