拔下USB时COM口消失 [英] COM port disappears when unplugging USB

查看:17
本文介绍了拔下USB时COM口消失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为平板电脑设计一种基于 Arduino 的扩展坞原型,使用 USB 端口作为连接器.这意味着我需要支持在平板电脑上的应用程序运行时插入/拔出 USB 连接器的能力.

I am prototyping a sort of Arduino-based docking station for a tablet, using the USB port as connector. This means I need to support to ability to plug/unplug the USB connector while the application on the tablet is running.

平板电脑运行一个 c# 应用程序(Win7 64 位上的 .net 4.5),我在其中连接到 Arduino Uno.当应用程序启动时,我使用以下命令循环所有可用的 COM 端口:

The tablet runs a c# application (.net 4.5 on Win7 64 bit) in which I am connecting to the Arduino Uno. When the application is launched I loop all available COM ports using:

var ports = SerialPort.GetPortNames(); // -> [COM3,COM4,COM8]
foreach (var port in ports)
{
     var serial = new SerialPort(portname, baudRate);
     //attempt handshake and connect to right port
}

这工作正常,但如果我拔下并重新插入 USB 电缆并重新尝试重新连接到 Arduino(当应用程序仍在运行时),Arduino 端口 (COM8) 不再列在:

This work fine, but if I unplug and replug the USB cable and reattempt to reconnect to the Arduino (while the application is still running), the Arduino port (COM8) is no longer listed in:

SerialPort.GetPortNames(); // -> [COM3,COM4] and no COM8

即使重新启动应用程序(重新插入 Arduino)也会导致仅列出 [COM3,COM4].

Even restarting the application (with the Arduino replugged) will result in only [COM3,COM4] being listed.

让它恢复工作的唯一方法是在应用程序未运行时拔下并重新插入 Arduino.

The only way to get it back to work is to unplug and replug the Arduino while the application is not running.

令我困惑的是,当我在启动应用程序后插入 Arduino Uno 时,SerialClass 确实识别新添加的端口并允许我进行连接.

What confuses me is the fact that when I plug in the Arduino Uno after starting the application, the SerialClass does recognize the newly added port and allows me to connect.

问题仅在我在应用程序运行时拔下并重新插入设备时出现.似乎尽管能够重置 COM 端口(在代码中或在设备管理器中手动),SerialClass(和本机 Win32_SerialPort - 我也检查过)无法识别这一点,除非我重新启动应用程序

The problem only occurs when I unplug and replug the device when the application is running. It seems that despite the ability to reset the COM port (in code or manually in device manager), the SerialClass (and native Win32_SerialPort - I checked this too) do not recognize this, unless I restart the application

这可能是什么原因?我如何确保我的应用程序可以重新连接到该端口?除了使用 SerialPort 处理 USB 连接器之外,还有其他选择吗?

What could be the reason for this? And how can I make sure that my application can reconnect to that port? Are there any alternatives to using the SerialPort to handle the USB connector?

推荐答案

我找到了一个可以处理插入和拔出 SerialPort 的解决方案.

I found a solution that can handle plugging and unplugging a SerialPort.

首先,它需要使用 SafeSerialPort,它允许您处理串口正确.

First of all, it requires the use the SafeSerialPort, which allows you to dispose the serial port properly.

SafeSerialPort serialPort;

private void Connect()
{
    string portname = "COM8";
    serialPort = new SafeSerialPort(portname, 9600);
    serialPort.DataReceived += port_DataReceived;
    serialPort.Open(); 
}

其次,需要使用LibUsbDotNet来检测USB 设备已连接或断开.这将允许您确定是连接到设备还是重置 COM 端口.

Second, you need to use LibUsbDotNet to detect whether a USB device is connected or disconnected. This will allow you to determine whether to connect to the device or reset the COM port.

public UsbDevice MyUsbDevice;

//Find your vendor id etc by listing all available USB devices
public UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x2341, 0x0001);
public IDeviceNotifier UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
{
    if (e.Object.ToString().Split('\n')[1].Contains("0x2341"))
    {
        if (e.EventType == EventType.DeviceArrival)
        {
            Connect();
        }
        else if(e.EventType == EventType.DeviceRemoveComplete)
        {
            ResetConnection();
        }
    }
}

最后,处理SerialPort将确保它在HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM中被Windows注册,这意味着SerialPort.GetPortNames()可以重新检测港口.

Finally, disposing the SerialPort will makes sure it is registered by Windows in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM, meaning that SerialPort.GetPortNames() can re-detect the port.

private void ResetConnection()
{
    try
    {
        //Send any data to cause an IOException
        serialPort.Write("Any value");
    }
    catch (IOException ex)
    {
        //Dispose the SafeSerialPort
        serialPort.Dispose();
        serialPort.Close();
    }
}

此过程后,您只需在连接 USB 设备时重新连接到 COM 端口即可,无需重新启动应用程序.

After this process, you can simply reconnect to the COM port when the USB device is connected without the need to restart the application.

完整代码:

using LibUsbDotNet;
using LibUsbDotNet.DeviceNotify;
using LibUsbDotNet.Info;
using LibUsbDotNet.Main;    

SafeSerialPort serialPort;

            public SerialPortTest()
            {
                Connect();

                UsbDeviceNotifier.OnDeviceNotify += OnDeviceNotifyEvent;
            }

            private void Connect()
            {
                string portname = "COM8";
                serialPort = new SafeSerialPort(portname, 9600);
                serialPort.DataReceived += port_DataReceived;
                serialPort.Open(); 
            }

            private void ResetConnection()
            {
                try
                {
                    serialPort.Write("Any value");
                }
                catch (IOException ex)
                {
                    serialPort.Dispose();
                    serialPort.Close();
                }
            }


            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                Console.WriteLine(serialPort.ReadExisting());
            }

            public UsbDevice MyUsbDevice;

            //Vendor ID etc can be found through enumerating the USB devices
            public UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x2341, 0x0001);
            public IDeviceNotifier UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
            private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
            {
                //if this is your usb device, in my case an Arduino
                if (e.Object.ToString().Split('\n')[1].Contains("0x2341"))
                {
                    if (e.EventType == EventType.DeviceArrival)
                    {
                        Connect();
                    }
                    else
                    {
                        ResetConnection();
                    }
                }
            }

这篇关于拔下USB时COM口消失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆