You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# SerialPort如何强制忽略奇偶校验错误?485设备通信问题

解决C# SerialPort忽略485串口奇偶校验错误的问题

1. 原生API实现忽略奇偶校验错误

.NET自带的SerialPort类没有暴露忽略奇偶校验错误的配置项,但可以通过P/Invoke调用Windows原生串口API绕过这个限制,直接修改串口控制参数:

using System;
using System.IO.Ports;
using System.Runtime.InteropServices;

public static class SerialPortExtensions
{
    [StructLayout(LayoutKind.Sequential)]
    private struct DCB
    {
        public int DCBlength;
        public int BaudRate;
        public int fBinary;
        public int fParity;
        public int fOutxCtsFlow;
        public int fOutxDsrFlow;
        public int fDtrControl;
        public int fDsrSensitivity;
        public int fTXContinueOnXoff;
        public int fOutX;
        public int fInX;
        public int fErrorChar;
        public int fNull;
        public int fRtsControl;
        public int fAbortOnError;
        public int fDummy2;
        public ushort wReserved;
        public ushort XonLim;
        public ushort XoffLim;
        public byte ByteSize;
        public byte Parity;
        public byte StopBits;
        public char XonChar;
        public char XoffChar;
        public char ErrorChar;
        public char EofChar;
        public char EvtChar;
        public ushort wReserved1;
    }

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

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

    public static void IgnoreParityErrors(this SerialPort serialPort)
    {
        var dcb = new DCB();
        dcb.DCBlength = Marshal.SizeOf(dcb);
        
        if (!GetCommState(serialPort.BaseStream.SafeFileHandle.DangerousGetHandle(), ref dcb))
            throw new System.ComponentModel.Win32Exception();
        
        // 关闭错误字符替换、禁用错误中止
        dcb.fErrorChar = 0;
        dcb.fAbortOnError = 0;

        if (!SetCommState(serialPort.BaseStream.SafeFileHandle.DangerousGetHandle(), ref dcb))
            throw new System.ComponentModel.Win32Exception();
    }
}

使用时只需在串口打开后调用扩展方法:

var port = new SerialPort("COM3", 9600, Parity.Even, 8, StopBits.One);
port.Open();
port.IgnoreParityErrors();
// 后续读取数据不会再将校验错误的字节替换为'?'

2. 手动比特位处理失效的原因

当你把Parity设为None时,Windows串口驱动会直接将原本的9位帧(8数据位+1奇偶位)按8位数据位解析,此时你拿到的字节已经是驱动错误重组后的结果——驱动已经丢弃了帧结构的边界信息,自然无法通过位运算恢复原始数据。

3. 第三方串口库推荐

如果不想写P/Invoke,可以使用SerialPortStream库,它是对Windows原生串口API的完整封装,支持直接配置忽略奇偶校验错误:

安装对应NuGet包后,直接配置参数即可:

using RJCP.IO.Ports;

var port = new SerialPortStream("COM3", 9600, 8, Parity.Even, StopBits.One);
port.ErrorChar = null; // 关闭错误字符替换
port.AbortOnError = false; // 遇到校验错误不中止通信
port.Open();
// 读取数据即可获取原始字节流

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:30:08