如何设置串行特殊字符
本文关键字:特殊字符 设置 何设置 | 更新日期: 2023-09-27 17:49:35
在我不断探索与一些遗留设备的接口时,我发现供应商提供的软件将特殊字符设置为:
00 00 00 00 11 13
但是。net的SerialPort类将它们设置为:
1A 00 00 1A 11 13
我想我有两个问题:
- 这些字节意味着什么?
- 我如何告诉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);
}