Как установить серийные специальные символы? - PullRequest
4 голосов
/ 11 апреля 2011

В моем продолжающемся стремлении к взаимодействию с устаревшим оборудованием я обнаружил, что программное обеспечение, поставляемое поставщиком, устанавливает специальные символы на:

00 00 00 00 11 13 

Но класс SerialPort .NET установил для них:

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) и для моей попытки сопоставления даже первый обмен .

Ответы [ 2 ]

2 голосов
/ 11 апреля 2011

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 для установки состояния последовательного порта.

0 голосов
/ 14 ноября 2013

Вы можете добавить расширение к serialPort в c #:

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 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);
            }
...