Python (Pyusb ベース) と C# (LibUsbDotNet ベース) の USB 通信速度の比較

1. 実験の背景

プロジェクト要件: 下位コンピューター ZYNQ は上位コンピューターと通信できるように設計する必要があり、通信プロトコルは USB2.0 です。ZYNQ 側の固定バッファ長は 16k です。つまり、ホスト コンピュータは任意のデータを ZYNQ に送信し、ZYNQ は毎回 16k の長さのバッファをフィードバックします。次に、Python (Pyusb ベース) と C# (LibUsbDotNet ベース) の USB 通信速度を実験します。実験結果は記事の最後にあります。

2、バスハウンド

この実験では、Bus Hound スーパー ソフトウェア バス プロトコル アナライザーを使用して、USB 入出力のプロトコル パケットをキャプチャし、上位コンピューターと下位コンピューター間の正常な通信を確保します。

ここに画像の説明を挿入

3. C# USB 読み取りおよび書き込み

C# は、図に示すように、LibUsbDotNet (LibUsbDotNet は、WinUsb、libusb-win32、Linux libusb v1.x に適した .NET C# USB ライブラリ) を使用して USB の読み取りと書き込みを実現します。

ここに画像の説明を挿入
具体的なコードは次のとおりです。

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、アウトバイト読み取り)

4. Python USB 読み取りおよび書き込み

図に示すように、Python は Pyusb を使用して USB の読み取りと書き込みを実装します。

ここに画像の説明を挿入
詳細なコードは次のとおりです。

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 のサイクル効率は、Python のサイクル効率よりも大幅に低くなります。 C#。読み取り数が多いと読み取り時間が長くなります。

ホストコンピュータの読み取り時間 読み取りバッファ長 C#の所要時間(秒) Python の所要時間
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

この記事が皆様のお役に立てば幸いです。上記に何か間違っている点がございましたら、ご指摘ください。

共有が高さを決定し、学習が格差を広げる

おすすめ

転載: blog.csdn.net/qq_42078934/article/details/131839031