C#上位机调试Win USB

#c# #winform #上位机 #UsbDevice #LibUsbDotNet

您好,各位朋友们,目前我在编写调试Win USB Device的上位机是遇到了几个问题,想问一下。

img

这是我想做成的界面。

我在网上查找资料调用的LibUsbDotNet库并添加在项目的一个类Readpolling.cs中,代码如下

using LibUsbDotNet;
using LibUsbDotNet.Main;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace boxed
{
    internal class Readpolling
    {
        public static UsbDevice MyUsbDevice; //公共静态定义的类名和对象

        #region SET YOUR USB Vendor and Product ID!   设置您的usb供应商和产品ID   // #region是分块预处理命令,它主要用于编译代码的分段,在编译时会被自动删除,必须以 #endregion终止

        public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(1234, 1); //公共静态定义类名和对象并且赋值

        #endregion

        //c#程序入口地址(同c的main()),访问修饰符(访问权限) + 关键字(静态) + 返回类型(不需要返回值) + 方法名(主程序) + string类(从控制台收参数) + 字符串()
        static void Main(string[] args)
        {
            //保存异常数据
            ErrorCode ec = ErrorCode.None;
            
            try
            {
                //找到并打开USB设备
                MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);

                //如果设备已经打开准备好
                if (MyUsbDevice == null)
                {
                    //若引发新的异常对象,显示设备没有被发现
                    throw new Exception("Device Not Found");
                }

                // If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
                // it exposes an IUsbDevice interface. If not (WinUSB) the 
                // 'wholeUsbDevice' variable will be null indicating this is 
                // an interface of a device; it does not require or support 
                // configuration and interface selection.
                IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
                if (!ReferenceEquals(wholeUsbDevice, null)) //比较两个引用类型的对象是否是对于同一个对象的引用
                {
                    //这是一个“whole”USB device,使用前选择configuration interface
                    //选择配置
                    wholeUsbDevice.SetConfiguration(1);

                    //接口
                    wholeUsbDevice.ClaimInterface(0);
                }

                //打开并读取endpoint1
                UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);

                byte[] readBuffer = new byte[1024]; //在内存中开辟块缓冲区,首地址readBuffer
                while (ec == ErrorCode.None) //一直在读取
                {
                    int bytesRead;

                    //如果5秒内没有发生数据,发生timeout error(ec = IoTimeOut)
                    ec = reader.Read(readBuffer, 5000, out bytesRead);

                    if (bytesRead == 0)

                        //引发新异常,将指定的 String类型的数据中的每个格式项替换为相应对象的值的文本等效项
                        throw new Exception(string.Format("{0}:No more bytes!", ec));
                    Console.WriteLine("{0} bytes read", bytesRead);

                    //将结果输出到控制台上,把当前编码字符串按指定编码方式编码为其他编码
                    Console.WriteLine(Encoding.Default.GetString(readBuffer, 0, bytesRead));


                    Console.WriteLine("\r\nDone!\r\n");

                }
            }

            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine((ec != ErrorCode.None ? ec + ":" : String.Empty) + ex.Message); //空字符串
            }

            //读取数据后执行
            finally
            {
                if (MyUsbDevice != null)
                {
                    if (!MyUsbDevice.IsOpen)
                    {
                        // If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
                        // it exposes an IUsbDevice interface. If not (WinUSB) the 
                        // 'wholeUsbDevice' variable will be null indicating this is 
                        // an interface of a device; it does not require or support 
                        // configuration and interface selection.
                        IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
                        if (!ReferenceEquals(wholeUsbDevice, null))
                        {
                            //释放interface 0
                            wholeUsbDevice.ReleaseInterface(0);
                        }
                        MyUsbDevice.Close();
                    }
                    MyUsbDevice = null;
                    //释放usb资源
                    UsbDevice.Exit();
                }

                Console.ReadKey();

            }
        }
    }
}

1.我不确定网上这个类的资料是否可以扫描到我的WinUSB Device设备。
2.在我的主体设计中,我不清楚如何通过serialport工具来调用ReadPolling类以及扫描出WinUSB Device设备。

@Java小白白又白 @根号五 @IT小生lkc @不良高须
希望获得朋友们的解答,感谢!

其他代码都无需看,只看一句话即可

#region SET YOUR USB Vendor and Product ID! 设置您的usb供应商和产品ID

这句话很明确的告诉你,你需要的答案了

Vendor and Product ID-----------------这句话说他是通过window设备描述符来查找设备的
先看一个我随便搜出来的博文

好了,这里可以回答你的第一个问题,只要你的设备管理器能找到他,你的代码就能找到他

然后回答你的第2个问题
还是先看一下这个库的官方实现

这个东西说明,他完全没有依赖串口的意思,他采用调用C++编写的一个通用usb驱动---libusb驱动来实现通讯

所以如果你想使用他,就不用考虑啥SerialPort了,因为他直接绕过串口类,直接访问驱动的,
嗯其实也不是完全不能用,你可以用它的diviceinfo过滤类名是Port,name得到串口号,然后你自己在用SerialPort连接它

跑起来打印日志试试!
编辑按钮的点击事件

不确定就试试呀,世间哪有那么多确定的事情
设备在你自己手里,你不去试,问别人,别人更不知道了呀

参考GPT:这段代码主要是使用了LibUsbDotNet库来打开和读取USB设备的数据。代码实现了从Endpoint 1读取数据,以及对异常情况的处理。

然而,这个类并没有涉及WinForm界面的相关代码。如果你想要将它与WinForm界面结合起来,你需要添加事件处理程序和控件。

可以考虑将这个类作为后台线程运行,并通过事件和委托在WinForm中更新UI。在这个线程中,你可以调用Read方法来读取USB设备发送的数据,并使用Invoke方法更新UI控件,例如TextBox等。

例如,你可以添加一个Button来启动这个线程,一个TextBox来显示USB设备发送的数据,一个Label来显示连接状态等等。

该回答引用于gpt与OKX安生共同编写:
  • 该回答引用于gpt与OKX安生共同编写:
  1. 关于问题一,您可以通过修改USB设备的Vendor ID和Product ID来匹配您的设备。请注意,您的设备必须遵循USB规范,并且已经正确安装了驱动程序。如果您的设备没有正确安装驱动程序,则可能无法在代码中找到它。

  2. 关于问题二,如果您想使用SerialPort工具与WinUSB通信,您需要将您的WinUSB设备模拟为一个串行端口。然后,您可以使用SerialPort类来打开并读取该端口。您可以在代码中创建一个新的SerialPort对象,并设置正确的端口名称、波特率、数据位数等参数。然后,您可以使用该对象的Read()方法来读取数据。在代码中,您需要调用SerialPort类的Open()方法来打开端口,并使用Close()方法关闭端口。

下面是一个简单的示例代码,可供您参考:

using System;
using System.IO.Ports;

namespace boxed
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
            serialPort.Open();

            while (true)
            {
                string data = serialPort.ReadExisting();
                Console.WriteLine(data);
            }

            serialPort.Close();
        }
    }
}

请注意,在上述代码中,我使用COM1端口和9600波特率。您应该将这些值替换为您自己的端口和波特率。

  • 如有用的话,还望采纳哦~

关于问题一,如果您已经解决了,那就很好。

  • 对于问题二,让我们深入探讨一下如何将WinUSB设备模拟为串行端口。当您使用WinUSB作为设备驱动程序时,Windows默认将其视为通用USB设备,而不是串行端口设备。为了使WinUSB设备具有类似COM端口、波特率和数据位这些串行端口属性,您需要手动编写一些代码在WinUSB设备上创建一个虚拟串行端口。下面是一些步骤,供参考:
    1. 首先,您需要安装Microsoft提供的WDK(Windows Driver Kit)。该工具包中包含了创建虚拟串行端口所需的驱动程序和示例代码。
    1. 您需要创建一个INF文件(安装程序文件),该文件描述了您的设备及其功能的详细信息。其中包括您的设备的硬件ID,以及您要创建的虚拟串行端口的名称和其他属性。您可以使用Microsoft提供的INF模板文件作为起点,并根据您的设备进行修改。
    1. 在您的设备的驱动程序中,您需要实现一些额外的代码来创建一个串行端口。这些代码涉及到枚举您的设备、打开设备句柄、设置设备属性以及创建串行端口等步骤。您可以使用Microsoft提供的示例代码作为参考,以便了解这些步骤。
    1. 随后您需要在您的C#代码中使用SerialPort类打开并读取该虚拟串口。请确保您的代码中设置正确的虚拟串口名称、波特率、数据位数等参数。

需要注意的是,将WinUSB设备模拟为串行端口是一项比较复杂的任务,并且需要涉及到Windows驱动程序开发方面的知识。如果您没有相关经验,我建议您首先阅读相关文档和示例代码,以便了解更多信息。同时,您也可以考虑寻求专业的帮助或支持。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
针对您提出的问题,以下是我的一些解答和建议。

1.关于LibUsbDotNet库
LibUsbDotNet库是一个C#封装的USB设备通信库,它可以实现USB设备的读取、写入和操作等。根据您提供的代码,您已经成功使用该库打开了您的USB设备,并且能够进行读取操作。所以您可以尝试根据您的需求进行相关调试和编写代码。

2.关于如何通过serialport工具来调用ReadPolling类
根据我了解,SerialPort可以通过调用Write和Read方法来进行串口数据的写入和读取,但是如果您想使用ReadPolling类来进行通信并不是很容易。建议您可以自己编写一个包装类来对接SerialPort和ReadPolling,通过SerialPort来发送和接收数据,然后在包装类中调用ReadPolling类进行数据处理。具体实现方法可以根据您的需求自行设计。

3.关于扫描出WinUSB Device设备
如果您想扫描WinUSB Device设备,可以使用WMI(Windows Management Instrumentation)接口来实现。您可以调用WMI中的Win32_USBHub类来获取USB设备信息,并根据设备的VID和PID属性来匹配您需要的设备。以下是一个示例代码,供您参考:

string query = "SELECT * FROM Win32_USBHub WHERE VendorID = 'YOURVID' AND ProductID = 'YOURPID'";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection collection = searcher.Get();

foreach (ManagementBaseObject obj in collection)
{
    // 获取设备信息
    string name = (string)obj.Properties["Name"].Value;
    string description = (string)obj.Properties["Description"].Value;
    string deviceId = (string)obj.Properties["DeviceID"].Value;
    
    // 如果需要可以强制转换为UsbDevice对象并进行相关操作
    UsbDevice device = new UsbDevice(deviceId);
}

其中,YOURVID和YOURPID分别为您设备的VendorID和ProductID,可以在设备管理器中查看。然后,您可以对获取到的设备进行相关操作。
如果我的回答解决了您的问题,请采纳!

问题描述:
该用户正在编写调试Win USB Device的上位机,使用了LibUsbDotNet库,并添加了一个名为Readpolling.cs的类。但是他遇到了两个问题:
1.不确定LibUsbDotNet库是否可以扫描到他的WinUSB Device设备。
2.不知道如何通过serialport工具来调用ReadPolling类以及扫描出WinUSB Device设备。
分析:
1.关于LibUsbDotNet库是否可以扫描到WinUSB Device设备,我们需要了解一下该库的作用和原理。LibUsbDotNet是一个基于.NET的USB库,它提供了一组用于访问USB设备的类和方法。它可以与多种USB设备进行通信,包括WinUSB设备。因此,只要WinUSB设备符合USB规范,就应该可以被LibUsbDotNet库扫描到。
但是,需要注意的是,LibUsbDotNet库只能扫描到已经安装了驱动程序的USB设备。如果WinUSB设备没有安装驱动程序,那么LibUsbDotNet库是无法扫描到该设备的。
2.关于如何通过serialport工具来调用ReadPolling类以及扫描出WinUSB Device设备,我们需要了解一下serialport工具的作用和原理。serialport工具是一个串口调试工具,它可以用来调试串口设备。但是,WinUSB设备并不是串口设备,因此serialport工具无法直接调用ReadPolling类或扫描WinUSB设备。
如果要调用ReadPolling类或扫描WinUSB设备,可以考虑使用其他工具或编写自己的程序。例如,可以编写一个WinForms应用程序,使用LibUsbDotNet库来扫描WinUSB设备,并调用ReadPolling类来读取数据。或者可以使用其他USB调试工具,如USBlyzer或USBView等。
总结:
1. LibUsbDotNet库可以扫描到已经安装了驱动程序的WinUSB设备。
2. serialport工具无法直接调用ReadPolling类或扫描WinUSB设备,需要使用其他工具或编写自己的程序。不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^