在我ongoing quest与某些传统设备接口时,我发现供应商提供的软件将特殊字符设置为:
00 00 00 00 11 13
但.NET的SerialPort类将它们设置为:
1A 00 00 1A 11 13
我想我有两个问题:
后者是我真正关心的,但我怀疑前者是有用的。
更新:以下内容不起作用:
byte[] specialchars = {
0x00,
0x00,
0x00,
0x00,
0x11,
0x13
};
this.port.NewLine = System.Text.Encoding.ASCII.GetString(specialchars);
更新2:根据要求,以下是the vendor supplied app的Portmon日志(已过滤以删除数千条IOCTL_SERIAL_GET_COMMSTATUS条目)和my attempt to match even the first exchange。
答案 0 :(得分:2)
NewLine
不是您想要的。这是普通的旧“新线”序列,例如仅CR CR或LF。
特殊字符的处理方式如下:
SerialPort.ParityReplace
您也可以学习Win32 DCB structure。它在内部用于设置串口的状态。
答案 1 :(得分:0)
您可以在c#:
中为serialPort添加扩展名您可以更改其他字段:
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);
}