嵌入式技术william hill官网
直播中

申根换

7年用户 1618经验值
私信 关注
[经验]

基于winUSB设备功能实现lora无线数据协议分析软件的设计

1、winUSB设备开发的环境
     本文选择的winUSB的开发语言为python,USB的软件包为pyUSB,首先你需要准备好python的整个开发环境与相关软件,之后在命令行中执行pip install pyusb,即可完成pyusb软件包的安装。pyusb用于实现USB主机端的USB通信功能 。
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的压缩包,解压后将MS64dlllibusb-1.0.dll复制到C:WindowsSystem32。如果还不行的话再将同一目录下的libusb-1.0.lib到Python路径下的libsite-packagesusb文件夹中。
     经过以上的操作,就可以正常打印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.jpg

原作者:fhqmcu

更多回帖

发帖
×
20
完善资料,
赚取积分