You need to enable JavaScript to run this app. C# 串口通信中如何实现 DTR 握手功能?
优惠活动
大模型
产品
解决方案
定价
更多

C# 串口通信中如何实现 DTR 握手功能?

C# 实现串口DTR握手的方案

.NET 自带的SerialPort类的Handshake枚举仅提供None、XOnXOff、RequestToSend、RequestToSendXOnXOff四个选项,没有原生的DTR握手选项,可通过以下两种方案实现:

方案1:手动控制DTR实现基础握手逻辑

适用于对实时性要求不高的场景,代码简单兼容性强,不需要调用平台API。
实现逻辑:

  • 初始化串口时关闭默认流控,开启DTR引脚输出
  • 通讯过程中根据对端DSR引脚状态或自定义流控规则,动态修改DtrEnable属性实现流控

代码示例:

using System.IO.Ports;

// 初始化串口配置
SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.DtrEnable = true; // 默认启用DTR引脚
serialPort.Open();

// 发送数据前判断流控状态,示例为标准DTR/DSR握手逻辑
if (!serialPort.DsrHolding)
{
    // 对端未准备好,关闭DTR暂停发送
    serialPort.DtrEnable = false;
}
else
{
    // 对端准备就绪,开启DTR恢复发送
    serialPort.DtrEnable = true;
}

方案2:P/Invoke调用Win32 API实现原生DTR握手

适用于Windows平台下对实时性要求高,需要完全匹配Win32原生串口行为的场景,直接修改底层DCB结构体的fDtrControl字段实现硬件级握手。
代码示例:

using System;
using System.IO.Ports;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

public static class SerialPortDtrExtension
{
    // DTR控制模式常量
    private const int DTR_CONTROL_HANDSHAKE = 0x02;
    private const int DCB_FLAGS_DTR_MASK = 0x0003;

    [StructLayout(LayoutKind.Sequential)]
    private struct DCB
    {
        public int DCBLength;
        public int BaudRate;
        public int Flags;
        public short wReserved;
        public short XonLim;
        public short XoffLim;
        public byte ByteSize;
        public byte Parity;
        public byte StopBits;
        public byte XonChar;
        public byte XoffChar;
        public byte ErrorChar;
        public byte EofChar;
        public byte EvtChar;
        public short wReserved1;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool GetCommState(SafeFileHandle hFile, ref DCB lpDCB);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetCommState(SafeFileHandle hFile, [In] ref DCB lpDCB);

    /// <summary>
    /// 为已打开的串口启用原生DTR硬件握手
    /// </summary>
    /// <param name="port">已打开的SerialPort实例</param>
    public static void EnableDtrHardwareHandshake(this SerialPort port)
    {
        if (!port.IsOpen)
            throw new InvalidOperationException("串口需处于打开状态才可修改握手配置");

        DCB dcb = new DCB();
        dcb.DCBLength = Marshal.SizeOf(dcb);
        SafeFileHandle portHandle = port.BaseStream.SafeFileHandle;

        // 读取当前DCB配置
        if (!GetCommState(portHandle, ref dcb))
            throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());

        // 修改DTR控制模式为硬件握手
        dcb.Flags &= ~DCB_FLAGS_DTR_MASK;
        dcb.Flags |= DTR_CONTROL_HANDSHAKE;

        // 写入新DCB配置
        if (!SetCommState(portHandle, ref dcb))
            throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    }
}

// 调用示例
public void InitSerialPortWithDtrHandshake()
{
    SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
    serialPort.Handshake = Handshake.None;
    serialPort.Open();
    // 启用原生DTR硬件握手
    serialPort.EnableDtrHardwareHandshake();
    // 后续正常使用串口即可,底层自动完成DTR流控逻辑
}

注意事项

  • 方案2仅适用于Windows平台,依赖Win32系统API
  • 修改DCB配置必须在串口打开后操作,否则会调用失败

内容的提问来源于stack exchange,提问作者domb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 08:54:04