如何设置序列特殊字符?

在我不断寻求与某些传统设备接口的过程中,我发现供应商提供的软件将特殊字符设置为:

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不是您想要的。 这是普通的旧“新线”序列,例如CR LF或LF。

特殊字符的处理方式如下:

  • EOF – 设置为0x1a,您无法在.NET中更改它
  • ERR – 由SerialPort.ParityReplace设置
  • BRK – 不知道
  • EVT – 设置为0x1a,您无法在.NET中更改它
  • XON – 设置为0x11,你不能在.NET中更改它,它甚至通常不会生成sesn
  • XOFF – 设置为0x13,你不能在.NET中更改它,它甚至通常不会生成sesn

研究Win32 DCB结构可能对您有所帮助。 .NET内部用它来设置串口的状态。

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

http://social.msdn.microsoft.com/Forums/vstudio/en-us/89b88e89-5814-4819-8b50-7caa3faf5f54/xonxoff-values-in-net20-serialport-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 ap/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); }