Comparación de la velocidad de comunicación USB entre Python (basado en Pyusb) y C# (basado en LibUsbDotNet)

1. Antecedentes experimentales

Requisitos del proyecto: la computadora inferior ZYNQ necesita diseñar la computadora superior para comunicarse con ella, y el protocolo de comunicación es USB2.0. La longitud fija del búfer en el lado de ZYNQ es de 16k, es decir, la computadora host envía datos arbitrarios a ZYNQ, y ZYNQ retroalimenta un búfer de 16k de longitud cada vez. Ahora experimente con la velocidad de comunicación USB de Python (basado en Pyusb) y C# (basado en LibUsbDotNet), los resultados experimentales se encuentran al final del artículo.

2, sabueso de autobús

El analizador de protocolo de bus de súper software Bus Hound se utiliza en este experimento para capturar los paquetes de protocolo de entrada y salida USB, a fin de garantizar la comunicación normal entre la computadora superior y la computadora inferior.

inserte la descripción de la imagen aquí

3. C# USB leer y escribir

C# utiliza LibUsbDotNet (LibUsbDotNet es una biblioteca USB .NET C#, adecuada para WinUsb, libusb-win32, Linux libusb v1.x) para realizar la lectura y escritura USB, como se muestra en la figura:

inserte la descripción de la imagen aquí
El código específico es el siguiente:

using System;
using System.Text;
using System.Text.RegularExpressions;
using LibUsbDotNet;
using LibUsbDotNet.Main;

namespace Examples
{
    
    
    internal class ReadWrite
    {
    
    
        public static UsbDevice MyUsbDevice;

        #region SET YOUR USB Vendor and Product ID!

        public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x04b4, 0x00f0);

        #endregion

        public static void Main(string[] args)
        {
    
    
            ErrorCode ec = ErrorCode.None;

            try
            {
    
    
                // Find and open the usb device.
                MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);

                // If the device is open and ready
                if (MyUsbDevice == null) throw new Exception("Device Not Found.");

                // If this is a "whole" usb device (libusb-win32, linux libusb)
                // it will have an IUsbDevice interface. If not (WinUSB) the 
                // variable will be null indicating this is an interface of a 
                // device.
                IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
                if (!ReferenceEquals(wholeUsbDevice, null))
                {
    
    
                    // This is a "whole" USB device. Before it can be used, 
                    // the desired configuration and interface must be selected.

                    // Select config #1
                    wholeUsbDevice.SetConfiguration(1);

                    // Claim interface #0.
                    wholeUsbDevice.ClaimInterface(0);
                }

                // open read endpoint 1.
                UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);

                // open write endpoint 1.
                UsbEndpointWriter writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);

                // Remove the exepath/startup filename text from the begining of the CommandLine.
                string cmdLine = Regex.Replace(
                    Environment.CommandLine, "^\".+?\"^.*? |^.*? ", "", RegexOptions.Singleline);

                if (!String.IsNullOrEmpty(cmdLine))
                {
    
    
                    int bytesWritten;
                    ec = writer.Write(Encoding.Default.GetBytes(cmdLine), 2000, out bytesWritten);
                    if (ec != ErrorCode.None) throw new Exception(UsbDevice.LastErrorString);

                    byte[] readBuffer = new byte[16384];
                    while (ec == ErrorCode.None)
                    {
    
    
                        int bytesRead=4096;

                        // If the device hasn't sent data in the last 100 milliseconds,
                        // a timeout error (ec = IoTimedOut) will occur. 
                        for(int i=0; i<2500;i++)
                        {
    
    
                            ec = reader.Read(readBuffer, 100, out bytesRead);
                        }


                        if (bytesRead == 0) throw new Exception("No more bytes!");

                        // Write that output to the console.
                        Console.Write(Encoding.Default.GetString(readBuffer, 0, bytesRead));
                    }

                    Console.WriteLine("\r\nDone!\r\n");
                }
                else
                    throw new Exception("Nothing to do.");
            }
            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))
                        {
    
    
                            // Release interface #0.
                            wholeUsbDevice.ReleaseInterface(0);
                        }

                        MyUsbDevice.Close();
                    }
                    MyUsbDevice = null;

                    // Free usb resources
                    UsbDevice.Exit();

                }

                // Wait for user input..
                Console.ReadKey();
            }
        }
    }
}

Tenga en cuenta que este código byte[] readBuffer = new byte[16384], el tamaño de readBuffer determina el tamaño de bytesRead en reader.Read(readBuffer, 100, out bytesRead), por lo que el tamaño debe ajustarse de acuerdo con el experimento. int bytesRead=4096, el valor no es 0, si es al menos más pequeño que el tamaño de readBuffer en byte[] readBuffer = new byte[16384], no afecta directamente el tamaño de bytesRead en reader.Read(readBuffer, 100, bytes de salidaLeer)

4. Python USB leer y escribir

Python usa Pyusb para implementar la lectura y escritura USB, como se muestra en la figura:

inserte la descripción de la imagen aquí
El código detallado es el siguiente:

import usb.core
import time

def find_usb_dev():
    all_devs = usb.core.find(find_all = True)
    for dev in all_devs:
         print(dev)

def usb_dev_enabled(dev):
    while(True):
        try:
            dev.set_configuration()
            break
        except Exception as e:
            print(e)

def usb_dev_write_bulk_out_ep(dev, endpoint, data, timeout):
    while(True):  
        try:
            data = dev.write(endpoint, data, timeout)
            break
        except Exception as e:
            print(e)
    return data
	
def usb_dev_read_bulk_in_ep(dev, endpoint, buffer_len, timeout):
    while(True):  
        try:
            data = dev.read(endpoint, buffer_len, timeout)
            break
        except Exception as e:
            print(e)
    return data


def read_dev():
    dev =  usb.core.find(idVendor= 0x04b4, idProduct= 0x00f0)
    # print(dev)
    data1 = bytes.fromhex('7e 7e')
    send1 = usb_dev_write_bulk_out_ep(dev, 0x1, data1, 2000)
    time_start = time.time()
    for i in range(10000):
        rev1 = usb_dev_read_bulk_in_ep(dev, 0x81,4096, 100)
    time_end = time.time()
    print(time_end - time_start)

if __name__ == "__main__":

    #### 普通
    read_dev()

5. Velocidad de comunicación USB

Los resultados experimentales finales se muestran en la siguiente tabla. En general, las velocidades de comunicación USB de Python (basado en Pyusb) y C# (basado en LibUsbDotNet) son aproximadamente las mismas, pero la eficiencia del ciclo de Python es mucho menor que la de C#, lo que lleva a un tiempo de lectura largo cuando el número de lecturas es grande.

Tiempos de lectura de la computadora host longitud del búfer de lectura Tiempo requerido para C# (s) Tiempo requerido para Python (s)
80000 512 2.587 5.047
40000 1024 2.692 3.038
10000 4096 2.504 2.506
20000 4096 5.004 5.001
10000 8192 5.102 5.001
2500 16384 2.615 2.569
10000 16384 10.837 10.295

Espero que este artículo sea útil para todos. Si hay algún problema con lo anterior, corríjame.

Compartir determina la altura, y aprender amplía la brecha

Supongo que te gusta

Origin blog.csdn.net/qq_42078934/article/details/131839031
Recomendado
Clasificación