winUSB设备上位机驱动开发环境的搭建

1、winUSB设备开发的环境

     本文选择的winUSB的开发语言为python,USB的软件包为pyUSB,首先你需要准备好python的整个开发环境与相关软件,之后在命令行中执行pip install pyusb,即可完成pyusb软件包的安装。pyusb用于实现USB主机端的USB通信功能 。

        winUSB设备的开发可以参考:(8条消息) winUSB设备的开发方法_fhqlongteng的博客-CSDN博客https://blog.csdn.net/fhqlongteng/article/details/124705686?spm=1001.2014.3001.5501

2、pyUSB的使用

     pyusb的使用很简单,按如下几行代码就是发现USB设备的,可以按PID, VID的方式来查找连接到电脑上的USB设备,此时把winUSB设备连接到电脑上后,运行此代码,正常的情况下,会打印出设备的信息。

import usb.core
import usb.util

dev =  usb.core.find(idVendor= 0x1234)
if dev is None:
    raise ValueError('Device not found')
print(dev)

事情不会那么的顺利,我的就遇到了问题,无法正常输出设备信息,单独查看winusb设备在电脑上是枚举成功的。

       程序在 运行时报错:usb.core.NoBackendError: No backend available,这是说明pyusb没有找到底层驱动的后端,需要手工增加使用的后端程序libusb-1.0.dll文件,如下方法操作即可。


      点击下面的链接下载libusb-1.0.20的压缩包,解压后将MS64\dll\libusb-1.0.dll复制到C:\Windows\System32。如果还不行的话再将同一目录下的libusb-1.0.lib到Python路径下的lib\site-packages\usb文件夹中。
https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.20/libusb-1.0.20.7z/download
 

     经过以上的操作,就可以正常打印USB设备的信息了。

DEVICE ID 1234:0001 on Bus 002 Address 013 =================
 bLength                :   0x12 (18 bytes)
 bDescriptorType        :    0x1 Device
 bcdUSB                 :  0x200 USB 2.0
 bDeviceClass           :    0x0 Specified at interface
 bDeviceSubClass        :    0x0
 bDeviceProtocol        :    0x0
 bMaxPacketSize0        :   0x40 (64 bytes)
 idVendor               : 0x1234
 idProduct              : 0x0001
 bcdDevice              :  0x200 Device 2.0
 iManufacturer          :    0x1 RT-Thread Team.
 iProduct               :    0x2 Lora USB
 iSerialNumber          :    0x3 32021919830108
 bNumConfigurations     :    0x1
  CONFIGURATION 1: 100 mA ==================================
   bLength              :    0x9 (9 bytes)
   bDescriptorType      :    0x2 Configuration
   wTotalLength         :   0x20 (32 bytes)
   bNumInterfaces       :    0x1
   bConfigurationValue  :    0x1
   iConfiguration       :    0x0 
   bmAttributes         :   0xc0 Self Powered
   bMaxPower            :   0x32 (100 mA)
    INTERFACE 0: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x2
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
      ENDPOINT 0x1: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x1 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x81: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x81 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0

3、USB数据的读写

     上面的几行代码仅仅是实现了usb设备的发现,真正要做的是usb数据的读取与写入。此时调试时可以使用BusHould软件在监控usb总线的数据,用于查找解决usb读写过程中的问题。

      下面是完整的主机端winusb设备的读写软件:下面代码中向设备发送的数据经过了特定帧格式的编码,winUSB设备接收后解析按此格式的数据进行回复。

import usb.core
import usb.util
import usb.backend.libusb1
import time

winusb = 0x1234
comusb = 0x10c4
mouseusb = 0x46d
dev = usb.core.find(idVendor=winusb)
print(dev)

configuration = dev.get_active_configuration()

dev.set_configuration()

cfg_ = configuration[(0, 0)]

# 0x2 写入节点
outPoint = usb.util.find_descriptor(
    cfg_,
    # match the first OUT endpoint
    custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)

# 0x81 读取节点
inPoint = usb.util.find_descriptor(
    cfg_,
    # match the first IN endpoint
    custom_match = lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)

#查询版本,型号
msg = [0xa8,0x01,0x02,0x02,0x01,0x00,0x00,0x24]
msg[-1] = sum(msg[1:-1]) & 0xff
r = dev.write(outPoint.bEndpointAddress, msg, 1000)
a= dev.read(inPoint.bEndpointAddress, 1024, 1000)
print("query ack:", end="")
for i in a:
    print("%02X "%(i),end="")
print("end")

#启动接收
msg = [0xa8,0x01,0x03,0x02,0x03,0x00,0x05,0x0F,0x00,0x00,0x00,0x00,0x24]
time_stamp = int(time.time()) + 8*3600
msg[-2] = time_stamp & 0xff
msg[-3] = (time_stamp >> 8) & 0xff
msg[-4] = (time_stamp >> 16) & 0xff
msg[-5] = (time_stamp >> 24)& 0xff

msg[-1] = sum(msg[1:-1]) & 0xff
r = dev.write(outPoint.bEndpointAddress, msg, 1000)
a= dev.read(inPoint.bEndpointAddress, 1024, 1000)
print("start ack:", end="")
for i in a:
    print("%02X "%(i),end="")
print("end")

for j in range(5):
    try:
        a= dev.read(inPoint.bEndpointAddress, 1024, 1000)
        print("read:", end="")
        for i in a:
            print("%02X "%(i),end="")
        print(" end!")
    except usb.core.USBTimeoutError:
        pass
    except usb.core.USBError:
        print("usbError")
        break
    except Exception as e:
        print("read error!",e)
                  
print("send over")

       注意此时需要winUSB的设备配合,设备能正常的向主机发送数据,接收数据,主机侧才能正确的进行读写。如果winUSB设备不能正常的向主机发送数据,主机一直读从机设备数据后,读取不到usb主机会自动复位总线。这个问题的原因是从机不能响应主机读取的数据,主机会停止从机,复位USB总线,希望从机能重新正常来发送数据。

      正确的解决办法是检测winusb设备的软件代码,让从机能正常的发送数据给主机就可以了。

Device  Phase  Data                            Description     Cmd.Phase.Ofs(rep)
------  -----  ------------------------------------------------------------------
  20.0  CTL    21 0a 00 00  00 00 00 00              SET IDLE            7.1.0        
  20.0  USTS   c0000004                             stall pid            7.2.0

4、USB读写异常的处理

     dev.read会返回异常,usb.core.USBTimeoutError是超时异常,即没有读到从机的数据,此时可以继续进行读取数据。 usb.core.USBError发生在从机与主机连接断开时,此异常可以识别USB设备断开。

5、产品应用

      基于winUSB设备功能实现了lora无线数据协议分析软件,本文以整个软件界面来庆祝winUSB系列博文的结束。

  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值