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

C# 利用串口 (COM) 實現低成本開關量輸入

     編輯:關於C#

動機

普通電腦無 GPIO,但偶爾需讀取簡單開關信號(如拉繩開關觸發程序、門磁檢測)。買單片機/擴展卡太貴,串口(COM)零成本解決。

原理

串口 DB9 接口:

  • Pin 4 (DTR)、Pin 7 (RTS):可輸出 +3V~+6V 電壓(作為電源)
  • Pin 1 (DCD)、Pin 6 (DSR)、Pin 8 (CTS):可檢測輸入電壓

將 DTR/RTS 接至開關公共端,開關另一端分別接 DCD/DSR/CTS。軟體啟用 DTR/RTS,輪詢三腳位電平變化即得 3 路開關量輸入。

硬體接線

  • 準備 DB9 母頭(電腦公頭需配母頭)、開關、導線、電烙鐵
  • Pin 4 作公共 VCC,Pin 1/6/8 各串一開關
  • 無串口筆記本可用 USB 轉串口線

接線圖

核心代碼

// 輸出電壓
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;

// 讀取輸入
bool cd = serialPort.CDHolding;
bool dsr = serialPort.DsrHolding;
bool cts = serialPort.CtsHolding;

完整輪詢類

public class SerialPortSwitch {
    private readonly SerialPort _port = new SerialPort();
    private readonly PinState[] _pins = {
        new PinState { PinName = Pin.CD },
        new PinState { PinName = Pin.CTS },
        new PinState { PinName = Pin.DSR }
    };
    public event Action SwitchOn;
    public event Action SwitchOff;

    public SerialPortSwitch(string portName) {
        _port.PortName = portName;
        _port.BaudRate = 9600;
        _port.Parity = Parity.None;
        _port.DataBits = 8;
        _port.StopBits = StopBits.Two;
        _port.DtrEnable = _port.RtsEnable = true;
    }

    public void Start() { /* 啟動後台線程輪詢 */ }
    public void Stop(bool wait = true) { /* 停止線程 */ }

    private void OnRunning() {
        _port.Open();
        while (!_stopPending) {
            foreach (var pin in _pins) CheckState(pin);
            Thread.Sleep(20); // 20ms 輪詢間隔
        }
    }

    private void CheckState(PinState pin) {
        bool current = GetPinHolding(pin.PinName);
        if (pin.IsHolding == current) pin.StableTick = Environment.TickCount;
        if (Environment.TickCount - pin.StableTick > 100) { // 100ms 消抖
            if (pin.IsHolding != current) {
                pin.IsHolding = current;
                if (current) SwitchOn?.Invoke(pin.PinName);
                else SwitchOff?.Invoke(pin.PinName);
            }
        }
    }

    private bool GetPinHolding(Pin pin) => pin switch {
        Pin.CD => _port.CDHolding,
        Pin.DSR => _port.DsrHolding,
        Pin.CTS => _port.CtsHolding,
        _ => throw new ArgumentOutOfRangeException()
    };
}

public enum Pin { CD = 1, DSR = 6, CTS = 8 }
public class PinState { public Pin PinName; public bool IsHolding; public int StableTick; }

主程序測試

var sw = new SerialPortSwitch("COM6");
sw.SwitchOn += p => Console.WriteLine($"{p}\tOn");
sw.SwitchOff += p => Console.WriteLine($"{p}\tOff");
sw.Start();
Console.ReadKey();
sw.Stop();

撥動開關即可在控制台看到即時輸出。

優缺點

  • ✅ 極低成本、無需驅動開發、跨平台(Linux/macOS 同樣適用)
  • ✅ 3 路獨立輸入,可擴展更多(利用 RI 等腳位)
  • ⚠️ 僅適用簡單開關量,無法輸出電壓驅動負載
  • ⚠️ 長線纜易受干擾,建議加濾波電容
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved