USB串口通信及pyusb库的应用
USB(Universal Serial Bus)是一种用于在计算机和外部设备之间传输数据的通用接口标准。在实际应用中,我们通常会使用USB串口进行设备间的通信,比如连接传感器、打印机、扫描仪等外部设备。
在Python中,我们可以使用pyusb库来实现USB串口通信。pyusb是一个Python语言实现的USB库,用于控制USB设备。通过使用pyusb库,我们可以在Python程序中方便地对USB设备进行读写操作。
安装pyusb库
在使用pyusb库之前,我们需要先安装它。可以通过pip工具来安装pyusb库,命令如下:
pip install pyusb
安装完成后,我们就可以开始使用pyusb库进行USB串口通信了。
USB设备的识别
在使用pyusb库与USB设备通信之前,我们需要先确认USB设备在系统中的标识信息,包括设备的厂商ID(Vendor ID)和产品ID(Product ID)。这两个信息可以帮助我们正确地辨识和连接到USB设备。
我们可以使用lsusb
命令来查看系统中已连接的USB设备的信息。下面以连接到计算机上的Arduino开发板为例,展示lsusb
命令的输出:
Bus 001 Device 003: ID 2341:0043 XYZ Corporation Arduino Uno
在这个输出中,2341是Arduino Uno的厂商ID,0043是产品ID。
使用pyusb库进行USB串口通信
接下来,我们将演示如何使用pyusb库来与USB设备进行通信。在这个示例中,我们将通过USB串口与Arduino开发板进行通信,来实现一个简单的LED控制。
首先,我们需要创建一个Python脚本,导入pyusb库,并定义USB设备的厂商ID和产品ID:
import usb.core
import usb.util
# 定义USB设备的厂商ID和产品ID
VENDOR_ID = 0x2341
PRODUCT_ID = 0x0043
接下来,我们需要编写一个函数来连接到USB设备,并打开设备的端点:
def connect_to_arduino():
# 查找指定厂商ID和产品ID的USB设备
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if dev is None:
raise ValueError("Device not found")
# 打开设备
dev.set_configuration()
# 获取设备的端点
cfg = dev.get_active_configuration()
interface_number = cfg[(0, 0)].bInterfaceNumber
alternate_setting = usb.control.get_interface(interface_number)
intf = usb.util.find_descriptor(
cfg, bInterfaceNumber = interface_number,
bAlternateSetting = alternate_setting
)
out_endpoint = usb.util.find_descriptor(
intf,
custom_match = lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT
)
in_endpoint = usb.util.find_descriptor(
intf,
custom_match = lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_IN
)
assert out_endpoint is not None and in_endpoint is not None
return dev, out_endpoint, in_endpoint
接下来,我们编写一个函数来发送指令到Arduino开发板:
def send_command(dev, out_endpoint, command):
dev.write(out_endpoint.bEndpointAddress, command)
最后,我们编写一个函数来接收Arduino开发板发送的数据:
def receive_data(dev, in_endpoint):
return dev.read(in_endpoint.bEndpointAddress, in_endpoint.wMaxPacketSize)
现在,我们可以调用以上定义的函数来实现LED控制的功能。下面是一个完整的Python脚本示例:
import usb.core
import usb.util
VENDOR_ID = 0x2341
PRODUCT_ID = 0x0043
def connect_to_arduino():
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if dev is None:
raise ValueError("Device not found")
dev.set_configuration()
cfg = dev.get_active_configuration()
interface_number = cfg[(0, 0)].bInterfaceNumber
alternate_setting = usb.control.get_interface(interface_number)
intf = usb.util.find_descriptor(
cfg, bInterfaceNumber = interface_number,
bAlternateSetting = alternate_setting
)
out_endpoint = usb.util.find_descriptor(
intf,
custom_match = lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT
)
in_endpoint = usb.util.find_descriptor(
intf,
custom_match = lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_IN
)
assert out_endpoint is not None and in_endpoint is not None
return dev, out_endpoint, in_endpoint
def send_command(dev, out_endpoint, command):
dev.write(out_endpoint.bEndpointAddress, command)
def receive_data(dev, in_endpoint):
return dev.read(in_endpoint.bEndpointAddress, in_endpoint.wMaxPacketSize)
if __name__ == "__main__":
dev, out_endpoint, in_endpoint = connect_to_arduino()
while True:
# 发送指令控制LED灯
command = input("Enter command (1 for on, 0 for off): ")
send_command(dev, out_endpoint, command.encode('utf-8'))
# 接收Arduino的返回数据
data = receive_data(dev, in_endpoint)
print(f"Received data: {data}")
在上述代码中,我们与Arduino开发板建立USB串口通信,并通过发送指令来控制LED的开关状态。我们不断循环发送指令,并接收Arduino开发板发送的数据。
运行示例代码
在运行上述示例代码之前,需要将Arduino开发板连接到计算机上,并确保其正常工作。
使用Python运行示例代码,输入指令控制LED的开关状态,即可看到LED的亮灭情况,同时可以查看Arduino开发板发送的数据。
通过使用pyusb库,我们可以方便地实现USB串口通信,与各种USB设备进行数据交互,为实际项目的开发提供了便利。
总结
本文介绍了USB串口通信的基本原理,以及如何使用pyusb库在Python中进行USB设备的操作。通过示例代码,我们演示了如何与Arduino开发板进行USB串口通信,实现LED控制的功能。
USB串口通信在各种嵌入式设备、外部传感器等场景中都有着广泛的应用,通过合理的协议设计和通信方式选择,可以实现稳定和高效的数据交互。