How to set serial special characters?

In my current quest for interacting with some kind of legacy equipment, I found that the software supplied by the vendor sets special characters:

00 00 00 00 11 13 

But the SerialPort.NET class set them to:

 1A 00 00 1A 11 13 

I believe that I have two questions:

  • What do these bytes mean?
  • How can I tell SerialPort to use a special set of special characters?

The latter is all that I really care about, but I suspect that the former will be useful to know.


Update: The following does not work:

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

Update 2:. As requested, Portmon logs are presented here for the vendor of the supplied application (filtered to remove many thousands of IOCTL_SERIAL_GET_COMMSTATUS entries) and for my attempt to match even the first exchange .

+4
source share
2 answers

NewLine is not what you are looking for. This is the usual old โ€œnew lineโ€ sequence, for example. Only CR LF or LF.

Special characters are processed as follows:

  • EOF - set to 0x1a, you cannot change it in .NET.
  • ERR - set by SerialPort.ParityReplace
  • BRK - don't know
  • EVT - set to 0x1a, you cannot change it in .NET.
  • XON - set to 0x11, you cannot change it in .NET, and it does not even make the sesn command
  • XOFF - set to 0x13, you cannot change it in .NET, and it usually doesnโ€™t even do sesn

It may be useful for you to study the structure of Win32 DCB . It is used by .NET internally to set the status of the serial port.

+2
source

You can add extenstion to serialPort in C #:

http://social.msdn.microsoft.com/Forums/vstudio/en-us/89b88e89-5814-4819-8b50-7caa3faf5f54/xonxoff-values-in-net20-serialport-class?forum=csharpgeneral

for other fields that you can change:

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

Code:

  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); } 
0
source

Source: https://habr.com/ru/post/1347528/


All Articles