首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >串行端口-我如何设置字符?

串行端口-我如何设置字符?
EN

Stack Overflow用户
提问于 2012-01-31 03:24:44
回答 2查看 5K关注 0票数 4

考虑:

代码语言:javascript
运行
复制
Baud rate 19200
RTS on
DTR on
Data bits=8, Stop bits=1, Parity=None
Set chars: Eof=0x00, Error=0x2A, Break=0x2A, Event=0x00, Xon=0x11, Xoff=0x13
Handflow: ControlHandShake=(DTR_CONTROL), FlowReplace=(TRANSMIT_TOGGLE, RTS_CONTROL),
XonLimit=0, XoffLimit=4096

好的,使用端口扫描器,我发现USB设备需要这些设置来方便导入。我可以重新创建其中的大多数如下:

代码语言:javascript
运行
复制
port = new SerialPort("COM4");
port.DtrEnable = true;
port.RtsEnable = true;
port.Handshake = Handshake.None;                                  
port.BaudRate = 19200;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.DataBits = 8;    

port.Open();

byte[] a = new byte[2] { 0x0 , 0x1 };
port.Write(a, 0, 1);
port.Write(a, 0, 1);
port.Write("mem");
port.Write("mem");

string output = port.ReadExisting();

System.Diagnostics.Debug.WriteLine("Found: " + output);

然而,所制定的守则如下:

代码语言:javascript
运行
复制
Set chars: Eof=0x1A, Error=0x00, Break=0x00, Event=0x1A, Xon=0x11, Xoff=0x13
XonLimit=1024, XoffLimit=1024

我如何更改X限制,以及每个字符代码,使它有一个工作的机会?

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/0e8cb6e2-077e-45a4-b01c-2eddb831c864帖子是我迄今为止发现的最接近的东西,但我不明白。

EN

回答 2

Stack Overflow用户

发布于 2013-11-14 13:28:14

您可以在serialPort中C#中添加一个扩展--参见http://social.msdn.microsoft.com/Forums/vstudio/en-us/89b88e89-5814-4819-8b50-7caa3faf5f54/xonxoff-values-in-net20-serialport-class?forum=csharpgeneral

对于其他字段,您可以更改:

代码语言:javascript
运行
复制
dcbType.GetField("XonChar"); // "XonChar", "XoffChar", "ErrorChar", "EofChar", "EvtChar"

代码:

代码语言:javascript
运行
复制
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);
}
票数 4
EN

Stack Overflow用户

发布于 2012-01-31 04:26:11

这些设置可以由Win32 SetCommState函数配置。

不幸的是,.NET没有提供一组很好的属性来配置它们,也不允许您访问HANDLE,因此您不能使用p/invoke来调整.NET SerialPort类的设置。

相反,您将不得不放弃整个System.IO.Ports.SerialPort类,并使用Win32 API完成所有操作:

  • CreateFile
  • GetCommState
  • SetCommState
  • WriteFile(Ex)
  • ReadFile(Ex)
  • WaitCommEvent

我建议您不要为此使用C#,Win32 API更容易从C++中使用,使用C++/CLI,您可以编写与C# GUI很好地交互的类。这是一项相当大的工作,好处是Win32串口函数比.NET库提供的访问功能要强大得多。我希望有一天能被允许发布我制作的C++/CLI串口类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9073963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档