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
相关产品推荐
相关产品推荐

