如何设置串行特殊字符

本文关键字:特殊字符 设置 何设置 | 更新日期: 2023-09-27 17:49:35

在我不断探索与一些遗留设备的接口时,我发现供应商提供的软件将特殊字符设置为:

00 00 00 00 11 13 

但是。net的SerialPort类将它们设置为:

1A 00 00 1A 11 13 

我想我有两个问题:

  1. 这些字节意味着什么?
  2. 我如何告诉SerialPort使用一组特定的特殊字符?

后者是我真正关心的,但我怀疑知道前者会很有用。


更新:以下不工作:

byte[] specialchars = {
    0x00,
    0x00,
    0x00,
    0x00,
    0x11,
    0x13
};
this.port.NewLine = System.Text.Encoding.ASCII.GetString(specialchars);

更新2:根据请求,这里是供应商提供的应用程序的Portmon日志(过滤以删除数千个IOCTL_SERIAL_GET_COMMSTATUS条目),以及我尝试匹配甚至第一次交换的日志。

如何设置串行特殊字符

NewLine不是你要找的。它是普通的旧'new line'序列,例如CR LF或单独的LF。

特殊字符是这样处理的:

  • EOF -设置为0x1a,你不能在。net
  • 中更改它
  • ERR -由SerialPort.ParityReplace
  • 设置
  • BRK - 不知道
  • EVT -设置为0x1a,你不能在。net
  • 中更改它
  • XON -设置为0x11,你不能在。net中更改它,它甚至通常不会使会话
  • XOFF -设置为0x13,你不能在。net中更改它,它甚至通常不会使会话

这可能对您学习Win32 DCB结构也有帮助。. net内部使用它来设置串口的状态

您可以在c#中为serialPort添加扩展:

http://social.msdn.microsoft.com/forums/vstudio/en us/89b88e89 - 5814 - 4819 - 8 b50 - 7 - caa3faf5f54/xonxoff -值- - net20串口class?forum=csharpgeneral

可以修改的其他字段:

dcbType.GetField("XonChar");//"XonChar"、"XoffChar"、"ErrorChar","EofChar"、"EvtChar"

代码:

            using System;
            using System.ComponentModel;
            using System.IO.Ports;
            using System.Reflection;
            using System.Runtime.InteropServices;
            using System.Security;
            using System.Security.Permissions;
            using Microsoft.Win32.SafeHandles;
            class Program
            {
                static void Main(string[] args)
                {
                    using (var port = new SerialPort("COM1"))
                    {
                        port.Open();
                        port.SetXonXoffChars(0x12, 0x14);
                    }
                }
            }
            internal static class SerialPortExtensions
            {
                [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
                public static void SetXonXoffChars(this SerialPort port, byte xon, byte xoff)
                {
                    if (port == null)
                        throw new NullReferenceException();
                    if (port.BaseStream == null)
                        throw new InvalidOperationException("Cannot change X chars until after the port has been opened.");
                    try
                    {
                        // Get the base stream and its type which is System.IO.Ports.SerialStream
                        object baseStream = port.BaseStream;
                        Type baseStreamType = baseStream.GetType();
                        // Get the Win32 file handle for the port
                        SafeFileHandle portFileHandle = (SafeFileHandle)baseStreamType.GetField("_handle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(baseStream);
                        // Get the value of the private DCB field (a value type)
                        FieldInfo dcbFieldInfo = baseStreamType.GetField("dcb", BindingFlags.NonPublic | BindingFlags.Instance);
                        object dcbValue = dcbFieldInfo.GetValue(baseStream);
                        // The type of dcb is Microsoft.Win32.UnsafeNativeMethods.DCB which is an internal type. We can only access it through reflection.
                        Type dcbType = dcbValue.GetType();
                        dcbType.GetField("XonChar").SetValue(dcbValue, xon);
                        dcbType.GetField("XoffChar").SetValue(dcbValue, xoff);
                        // We need to call SetCommState but because dcbValue is a private type, we don't have enough
                        //  information to create a p/Invoke declaration for it. We have to do the marshalling manually.
                        // Create unmanaged memory to copy DCB into
                        IntPtr hGlobal = Marshal.AllocHGlobal(Marshal.SizeOf(dcbValue));
                        try
                        {
                            // Copy their DCB value to unmanaged memory
                            Marshal.StructureToPtr(dcbValue, hGlobal, false);
                            // Call SetCommState
                            if (!SetCommState(portFileHandle, hGlobal))
                                throw new Win32Exception(Marshal.GetLastWin32Error());
                            // Update the BaseStream.dcb field if SetCommState succeeded
                            dcbFieldInfo.SetValue(baseStream, dcbValue);
                        }
                        finally
                        {
                            if (hGlobal != IntPtr.Zero)
                                Marshal.FreeHGlobal(hGlobal);
                        }
                    }
                    catch (SecurityException) { throw; }
                    catch (OutOfMemoryException) { throw; }
                    catch (Win32Exception) { throw; }
                    catch (Exception ex)
                    {
                        throw new ApplicationException("SetXonXoffChars has failed due to incorrect assumptions about System.IO.Ports.SerialStream which is an internal type.", ex);
                    }
                }
                [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
                private static extern bool SetCommState(SafeFileHandle hFile, IntPtr lpDCB);
            }