Python(基于Pyusb)与C#(基于LibUsbDotNet)USB通信速度对比

1、实验背景

项目需求:下位机ZYNQ,需设计上位机与其通信,通信协议USB2.0。ZYNQ端固定Buffer长度为16k,即上位机向ZYNQ发送任意数据,ZYNQ每次反馈16k长度buffer。现对Python(基于Pyusb)与C#(基于LibUsbDotNet)的USB通信速度进行实验,实验结果见文章末尾

2、Bus Hound

Bus Hound超级软件总线协议分析器,在本实验中用于捕捉USB输入输出的协议包,以确保上位机与下位机通信正常

Python(基于Pyusb)与C#(基于LibUsbDotNet)USB通信速度对比_第1张图片

3、C# USB读写

C#使用LibUsbDotNet(LibUsbDotNet是一个.NET C#的USB库,适用于WinUsb,libusb-win32,Linux libusb v1.x)实现USB读写,如图所示:

Python(基于Pyusb)与C#(基于LibUsbDotNet)USB通信速度对比_第2张图片
具体代码如下:

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();
            }
        }
    }
}

注意此代码 byte[] readBuffer = new byte[16384],readBuffer的大小决定reader.Read(readBuffer, 100, out bytesRead)中bytesRead大小,故此大小要根据实验进行调整。 int bytesRead=4096,该值不为0即可,如果至小于byte[] readBuffer = new byte[16384]中readBuffer的大小,其不直接影响reader.Read(readBuffer, 100, out bytesRead)中bytesRead大小

4、Python USB读写

Python使用Pyusb实现USB读写,如图所示:

Python(基于Pyusb)与C#(基于LibUsbDotNet)USB通信速度对比_第3张图片
详细代码如下:

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、USB通信速度

最终实验结果如下表,综合来看Python(基于Pyusb)与C#(基于LibUsbDotNet)的USB通信速度大体相同,但是Python的循环效率远低于C#,导致read次数多时,read时间大

上位机read次数 read buffer长度 C#所需时间(s) 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

希望本文对大家有帮助,上文若有不妥之处,欢迎指正

分享决定高度,学习拉开差距

你可能感兴趣的:(笔记,一起学C#,一起学Python,python,c#,zynq,pyusb,libusbdotnet,usb2.0,bushound)