背景

最近在给一个FPGA板子做上位机界面,上位机与下位机的通信采用USB方案,

驱动采用WinDriver。

但在实际调试过程中,发现WinDriver不同版本之间兼容性差,并且在win10

上表现不佳。实际的数据传输流程如下:

python usb dll(through ctypes) windriver usb device

由于dll文件是在win7机器上编译的,故仅能在win7上使用,在win10机器上出错。

使用python的项目都应该是简洁而优雅地,遂研究了在python操作usb device的两种方式。

驱动无关的调试软件使用bus hound

WinDriver

WinDriver经常与Jungo connectivity联系在一起,安装了WinDriver驱动的usb device在

设备管理器中也显示为Jungo devices。

完整的WinDriver开发流程应该从驱动开始,使用C/C++调用WinDriver提供的库与usb device

通信,将此程序编译为dll供其他程序调用。

将usb device连接上电脑,使用WinDriver给设备安装驱动。

在python中使用ctypes调用上文中的dll,完成调用过程。

PyUsb

pyusb是一个python库,可以方便地使用python操作usb设备。pyusb的数据传输流程如下:

python pyusb pyusb backend usb device

很明显可以看出省略了dll,大大减少了代码量。

具体使用过程:

1. 下载并安装pyusb backend

2. 连接usb device,使用pyusb backend安装驱动,我选择libusb,一般可以正常使用。不行就换其他的。

3. 编写python脚本,可以参考官方教程

缺点:

1. windriver有一个可视化的调试工具,可以单独发送接收数据以确定usb device是否正常,pyusb暂时没有找到。但

找到了一个非官方的基于tk的pywinusb hid调试工具

pyusb demo

我认为官方教程中的操作有些复杂,可以做如下简化:

1. 官方例程中使用get_active_configuration(), usb.util.find_descriptor()找设备描述符,我没有调试出来且繁杂,不如在 dev.set_configuration()之后直接dev.write(),前提是

已经知道设备描述符,这个可以通过一个简单的python脚本查询.

#!/usr/bin/python

# 此代码仅供示例,未测试

# 原始链接 http://www.bubuko.com/infodetail-2281652.html

import sys

import usb.core

# find USB devices

dev = usb.core.find(find_all=True)

# loop through devices, printing vendor and product ids in decimal and hex

for cfg in dev:

sys.stdout.write('Decimal VendorID=' + str(cfg.idVendor) + ' & ProductID=' + str(cfg.idProduct) + '\n')

sys.stdout.write('Hexadecimal VendorID=' + hex(cfg.idVendor) + ' & ProductID=' + hex(cfg.idProduct) + '\n\n')

一个demo代码如下,本代码同时采用了windriver和pyusb的方式。

由于完整运行该代码需要dll库文件、FPGA下位机配合,所以本代码仅供示例,大概率无法复现。

#!/bin/bash

import ctypes

from ctypes import *

# prepared to be called from the same class directory python scripts

import sys

import os

import usb.core

# now our hardware is vid = 0x03fd, pid = 0x0100)

class hardware_usb():

def __init__(self, vid, pid, read_length = 512, backend='libusb'):

'''

vid: vendor id

pid: product id

read_length : buffer length for reading

backend: select one from ['libusb', 'windriver']

'''

self.read_length = read_length

self.backend = backend

if backend == 'libusb':

usb_dev = usb.core.find(idVendor=vid, idProduct=pid)

if usb_dev != None :

usb_dev.set_configuration()

self.read_addr = 0x82

self.write_addr = 0x03

self.dev = usb_dev

self.init_status = True

else:

self.init_status = False

elif backend == 'windriver':

try:

dll = ctypes.cdll.LoadLibrary( "msdev_dll.dll")

except Exception as e :

print("Error occurs when init usb,%s:%s" %(str(e.__class__), str(e.args)))

self.init_status = False

else:

# input : void

# output : int

# assum 0 to be successful

self.init_driver = getattr(dll, '?InitDriver@@YA_NXZ')

# input : PVOID pBuffer, DWORD &dwSize

# output: bool

self._read = getattr(dll, '?Read_USB@@YA_NPAXAAK@Z')

# input : PVOID pBuffer, DWORD dwSize

# output: bool

self._write = getattr(dll, '?Write_USB@@YA_NPAXK@Z')

if 1 == self.init_driver():

self.init_status = True

else:

self.init_status = False

def write(self, data):

'''

Write data to usb

Note that data must bytes type

Return True if success

'''

if self.backend == 'windriver':

# BUG 此处使用c_char_p, 遇到\x00就被截断,可能有bug

buffer = ctypes.c_char_p()

buffer.value = data

leng = ctypes.c_ulong(len(data))

try:

status = self._write(buffer,leng)

except Exception as e :

print("Error occurs when write usb,%s:%s" %(str(e.__class__), str(e.args)))

status = 0

if status == 1:

ret = True

else :

ret = False

elif self.backend == 'libusb':

write_len = self.dev.write(self.write_addr, data)

# Test if data is written

if write_len == len(data):

ret = True

else:

ret = False

return ret

def read(self):

'''

Read data from usb

Note we will return bytes like data

Return None if error occurs

'''

if self.backend == 'windriver':

buffer_class = c_ubyte * 512

buffer = buffer_class()

leng = ctypes.c_ulong()

try :

status = self._read(buffer, ctypes.byref(leng) )

except Exception as e :

print("Error occurs when read from usb,%s:%s" %(str(e.__class__), str(e.args)))

status = 0

if status == 1:

ret = bytes(buffer[:leng.value])

else:

ret = b''

elif self.backend == 'libusb':

try:

ret = self.dev.read(self.read_addr, self.read_length)

ret = bytes(ret)

except Exception as e:

print("Error occurs when read from usb,%s:%s" %(str(e.__class__), str(e.args)))

ret = b''

return ret

if __name__ == "__main__":

usb_ins = hardware_usb(vid=0x03fd, pid=0x0100)

loop_num = 1

# 在测试中发现有一定概率写入出错

while True:

print('============================')

print('Loop num is', loop_num)

print('test write function')

data = b'\x7e\x7f\x00\x66'

try:

write_ret = usb_ins.write(data)

read_ret = usb_ins.read()

except:

print('Error occurs, return')

break

print('write function returns', write_ret)

print('test read function')

print(' read function returns', read_ret)

loop_num = loop_num + 1

python libusb_使用python开发usb的两种方式(windriver与pyusb)相关推荐

  1. python循环展示大写字母_python调用大写函数python中字典的循环遍历的两种方式

    开发中经常会用到对于字典.列表等数据的循环遍历,但是python中对于字典的遍历对于很多初学者来讲非常陌生,今天就来讲一下python中字典的循环遍历的两种方式. 注意: python2和python ...

  2. python中字典的循环遍历的两种方式

    开发中经常会用到对于字典.列表等数据的循环遍历,但是python中对于字典的遍历对于很多初学者来讲非常陌生,今天就来讲一下python中字典的循环遍历的两种方式. 注意: python2和python ...

  3. python怎么下载图片怎么保存到本地_详解Python下载图片并保存本地的两种方式

    一:使用Python中的urllib类中的urlretrieve()函数,直接从网上下载资源到本地,具体代码: import os,stat import urllib.request img_url ...

  4. python扩展屏幕截图_Python实现屏幕截图的两种方式

    Python实现屏幕截图的两种方式 使用windows API 使用PIL中的ImageGrab模块 下面对两者的特点和用法进行详细解释. 一.Python调用windows API实现屏幕截图 好处 ...

  5. python动态捕捉屏幕_Python实现屏幕截图的两种方式

    使用windows API 使用PIL中的ImageGrab模块 下面对两者的特点和用法进行详细解释. 一.Python调用windows API实现屏幕截图 好处是 灵活 速度快 缺点是: 写法繁琐 ...

  6. Python自定义类中定义属性的两种方式

    封面图片:<Python程序设计开发宝典>,ISBN:9787302472100,董付国,清华大学出版社 图书详情:https://item.jd.com/12143483.html 京东 ...

  7. python实现selenium文件上传的两种方式

    方法一.input标签上传     如果是input标签,可以直接输入路径,那么可以直接调用send_keys输入路径. 方法二.非input标签上传 这种上传方式需要借助第三方工具,主要有以下三种情 ...

  8. python 把if 写在一行的两种方式

    第一种:列表生成式 # info = '姓名=小王&年龄=16&身高=175' # 用一行代码,得到其中的年龄数字,不要数索引 info = '姓名=小王&年龄 = 16&am ...

  9. python截图拼接_Python实现屏幕截图有两种方式 - 小众知识

    使用windows API 使用PIL中的ImageGrab模块 下面对两者的特点和用法进行详细解释. 一.Python调用windows API实现屏幕截图 好处是灵活 速度快 缺点是:写法繁琐 不 ...

  10. python脚本在linux上运行的两种方式_python脚本当作Linux中的服务启动实现方法

    脚本服务化目的: python 在 文本处理中有着广泛的应用,为了满足文本数据的获取,会每天运行一些爬虫抓取数据.但是网上买的服务器会不定时进行维护,服务器会被重启.这样我们的爬虫服务就无法运行.这个 ...

最新文章

  1. Python2+Selenium入门03-元素定位
  2. 浙江高校计算机等级考试二级办公,浙江省高校计算机等级考试二级(高级办公)试题12.ppt...
  3. 【Java从0到架构师,mysql视频教程推荐
  4. 2021- 10 -9 LeetCode 958. 二叉树的完全性检验(待补完)
  5. Qt5 中 QWebEngineView 的使用,让桌面客户端和 web 端友好通信
  6. python自动化工具开发_初识TPOT:一个基于Python的自动化机器学习开发工具
  7. ubuntu 12.04 配置LAMP
  8. 记一次偶遇Adminer
  9. 24.Creating Customer Groups
  10. LINUX获得当前用户名
  11. ORA-01017: invalid username/password; logon denied
  12. C盘AppData文件占用83.7G?
  13. 轻量级配置的登录管理器选择---Silm[zt]
  14. android代码获取deviceid,获取安卓系统的设备id用getDeviceId()函数
  15. cuda9.2环境下pip安装tensorflow非官方轮子
  16. yarn : 无法加载文件 ...Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本
  17. 数据结构题集(c语言版)第2章:线性表
  18. 2022深圳国际电子设备及检测仪器展览会
  19. MathType有一些字符无法显示
  20. 佳能打印机删掉又会自动加载的原因及解决方案

热门文章

  1. 国内外你知道的设计网站!给你的设计找点灵感!
  2. C4D R18-R21
  3. 错误 LNK2005 xxx已经在 xxx.obj 中定义
  4. android 铃音制作工具,音乐剪辑铃声制作
  5. STC15单片机学习笔记1——STC15W4K56S4引脚功能整理说明
  6. Linux下pip安装教程
  7. C语言 输出乘法口诀表
  8. 一年级计算机上册计划进度表,一年级上册语文教学计划及进度表
  9. matlab中做出球面和圆柱面,用matlab作出抛物柱面y^2=x和平面x+z=1相交的图形具体步骤...
  10. 革新科技CIDE-EDA:实验1 3-8译码器