#c# #winform #上位机 #UsbDevice #LibUsbDotNet
您好,各位朋友们,目前我在编写调试Win USB Device的上位机是遇到了几个问题,想问一下。
这是我想做成的界面。
我在网上查找资料调用的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设备描述符来查找设备的
先看一个我随便搜出来的博文
好了,这里可以回答你的第一个问题,只要你的设备管理器能找到他,你的代码就能找到他
这个东西说明,他完全没有依赖串口的意思,他采用调用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安生共同编写:
关于问题一,您可以通过修改USB设备的Vendor ID和Product ID来匹配您的设备。请注意,您的设备必须遵循USB规范,并且已经正确安装了驱动程序。如果您的设备没有正确安装驱动程序,则可能无法在代码中找到它。
关于问题二,如果您想使用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设备模拟为串行端口是一项比较复杂的任务,并且需要涉及到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,可以在设备管理器中查看。然后,您可以对获取到的设备进行相关操作。
如果我的回答解决了您的问题,请采纳!
//拿到USB的设备地址,并记录下来
device = libusb_get_device(dev_handle);
Device_Addr = libusb_get_device_address(device);