之前一直找不到适合WIN7下的Tiny6410的USB下载软件,正好这几天开始学习USB,所以打算自己写一个专门用于Tiny6410的WIN7下的USB下载软件。
发现了libusb这个库可以用作无驱USB开发,就是说根本不需要了解Window驱动开发的知识就可以开发USB设备驱动,只需要了解一下USB的相关协议即可。Windows下我几乎不用VS来写程序,或者说我不懂MFC吧,呵呵,所示我用Qt来做界面。好了,进入正题。
首先下载libusb-win32,下载地址:http://sourceforge.net/projects/libusb-win32/files/,注意选择下载的文件是libusb-win32-bin-1.2.6.0.zip,这不是源码,而是一些已经编译好的库。解压之,里面有这么一些文件(夹):
下面简单介绍一下里面的东西是怎么用的。
(1)bin文件夹。里面最重要的是inf-wizard.exe这个程序,当你的USB设备插到电脑上而没有找到驱动程序时就可以通过这个程序来安装通用的USB驱动。双击它,下一步,在里面找到你的USB设备,选中后下一步,最后会弹出一个对话框让你保存它生成驱动程序。这样就有了驱动程序,但还没有安装,可以通过设备管理器来安装,安装成功后就可以通过libusb来编写程序来访问你的USB设备了。
(2)examples文件夹。里面有两个例程,一个简单的,一个复杂的,参考里面的bulk.c例程就好了。
(3)include文件夹。编写程序时需要用到,一般放在你的工程目录下。
(4)lib文件夹。里面是一些已经编译好的库,有borland版本的,有VC++版本的,有x64位版本的,最重要的是还有gcc版本,这里用到的就是gcc版本的,该版本可以在Qt上使用。
下面开始介绍怎么在Qt下使用该库。
1. 新建一个Qt工程
2. 把gcc版本的库文件libusb.a复制到工程目录下(可以放在其他目录),在.pro文件中追加如下一行(路径根据自己的情况修改):
LIBS+="F:/Qt/pratise/libusb-test/libusb/libusb.a"
这样就可以在链接时找到所需的函数。
3. 把上面所说的include文件夹下lusb0_usb.h文件复制到工程目录下。
4. 编写一个测试文件,我这里写的比较简单,程序的功能是只列出我的USB设备,如下:
1 #include "testlibusb.h"
2 #include "lusb0_usb.h"
3
4 USB::USB()
5 {
6 //usb_set_debug(250);
7 usb_init(); /* initialize the library */
8 usb_find_busses(); /* find all busses */
9 usb_find_devices(); /* find all connected devices */
10
11 my_usb_get_device_list();
12
13 resize(320, 240);
14 }
15
16
17 void USB::my_usb_get_device_list(void)
18 {
19 struct usb_bus *bus;
20 struct usb_device *dev;
21
22 for (bus = usb_get_busses(); bus; bus = bus->next) {
23 for (dev = bus->devices; dev; dev = dev->next) {
24 /* for specified device
25 if (dev->descriptor.idVendor == MY_VID
26 && dev->descriptor.idProduct == MY_PID)
27 {
28 return usb_open(dev);
29 }
30 */
31
32 qDebug("VID:VID = %x:%x\n", dev->descriptor.idVendor, dev->descriptor.idProduct);
33
34 }
35 }
36
37 }
好了,运行程序,效果:
最后一行打印出来的正是Tiny6410的USB设备号。
注意:
这只能列出安装了inf-wizard.exe生成的驱动程序的USB设备。一开始的时候我没接上Tiny6410,程序没输出,插上一个U盘,还是没输出,以为是程序或者这个库有问题,纠结了一会,后来灵光一闪,插上开发板试试吧,果然成功了,程序运行结果就如上面所示。
继续学习USB,过2天USB开发板到了就开始实战。
Qt下libusb-win32的使用(一)打印设备描述符
主要是在前一篇的基础上,学习libusb-win32的API使用。程序很简单,就是打印指定USB设备的设备描述符(当然其他描述符也是可以的)。
1 #include "testlibusb.h"
2
3
4 #define MY_VID 0x5345
5 #define MY_PID 0x1234
6
7
8 USB::USB()
9 {
10 usb_init(); /* initialize the library */
11 //usb_set_debug(255);
12 usb_find_busses(); /* find all busses */
13 usb_find_devices(); /* find all connected devices */
14
15 if (!(udev = open_dev())) {
16 qDebug("error opening device: %s", usb_strerror());
17 exit(1);
18 } else
19 qDebug("open success: device %04X:%04X opened", MY_VID, MY_PID);
20
21 printf_device_descriptor(&dev->descriptor);
22 usb_close(udev);
23
24 //my_usb_get_device_list();
25 resize(320, 240);
26 }
27
28 usb_dev_handle *USB::open_dev(void)
29 {
30 struct usb_bus *bus;
31 //struct usb_device *dev;
32
33 for(bus = usb_get_busses(); bus; bus = bus->next) {
34 for(dev = bus->devices; dev; dev = dev->next) {
35 if((dev->descriptor.idVendor == MY_VID) && (dev->descriptor.idProduct == MY_PID)) {
36 return usb_open(dev);
37 }
38 }
39 }
40 return 0;
41 }
42
43 void USB::printf_device_descriptor(usb_device_descriptor *desc)
44 {
45 qDebug("bLength: %u", desc->bLength);
46 qDebug("bDescriptorType: %02Xh", desc->bDescriptorType);
47 qDebug("bcdUSB: %04Xh", desc->bcdUSB);
48 qDebug("bDeviceClass: %02Xh", desc->bDeviceClass);
49 qDebug("bDeviceSubClass: %02Xh", desc->bDeviceSubClass);
50 qDebug("bDeviceProtocol: %02Xh", desc->bDeviceProtocol);
51 qDebug("bMaxPacketSize0: %02Xh", desc->bMaxPacketSize0);
52 qDebug("idVendor: %04Xh", desc->idVendor);
53 qDebug("idProduct: %04Xh", desc->idProduct);
54 qDebug("bcdDevice: %04Xh", desc->bcdDevice);
55 qDebug("iManufacturer: %u", desc->iManufacturer);
56 qDebug("iProduct: %u", desc->iProduct);
57 qDebug("iSerialNumber: %u", desc->iSerialNumber);
58 qDebug("bNumConfigurations: %u", desc->bNumConfigurations);
59 }
这里我指定的USB设备是Tiny6410开发板。运行效果如下:
下一步就是上位机与开发板进行数据互传。
Qt下libusb-win32的使用(二)批量读写操作
一、概述
学习libusb-win32的使用。使用批量传输方式与USB开发板进行数据读、写操作。上位机使用Qt做界面, 使用USB开发板的端点2作为批量传输端点。
二、实现
代码比较简单,直接给出,如下:
1 #include "testlibusb.h"
2
3 //for Tiny6410
4 //#define MY_VID 0x5345
5 //#define MY_PID 0x1234
6
7 //for 51 USB Board
8 #define MY_VID 0x8888
9 #define MY_PID 0x0001
10
11 // Device configuration and interface id.
12 #define MY_CONFIG 1
13 #define MY_INTF 0
14
15 // Device endpoint 2
16 #define EP_IN 0x82
17 #define EP_OUT 0x02
18
19 // Device of bytes to transfer.
20 #define BUF_SIZE 64
21
22 //#define DEBUG_GUI
23
24
25
26 USB::USB()
27 {
28 #ifndef DEBUG_GUI
29
30 usb_init(); /* initialize the library */
31 //usb_set_debug(255);
32 usb_find_busses(); /* find all busses */
33 usb_find_devices(); /* find all connected devices */
34
35 if (!(udev = open_dev())) {
36 qDebug("error opening device: %s", usb_strerror());
37 exit(1);
38 } else
39 qDebug("open success: device %04X:%04X opened", MY_VID, MY_PID);
40
41 printf_device_descriptor(&dev->descriptor);
42 my_init_usbdev();
43 #endif
44
45 textEdit = new QTextEdit(this);
46 textEdit->setGeometry(50,20,230,40);
47
48 sendButton = new QPushButton(this);
49 sendButton->setText("send");
50 sendButton->setGeometry(130,80,60,40);
51 connect(sendButton,SIGNAL(clicked()),this,SLOT(send_slot()));
52
53 readButton = new QPushButton(this);
54 readButton->setText("read");
55 readButton->setGeometry(130,140,60,40);
56 connect(readButton,SIGNAL(clicked()),this,SLOT(read_slot()));
57
58 recvLabel = new QLabel(this);
59 recvLabel->setText("recv data:");
60 recvLabel->setGeometry(20,180,280,40);
61
62 //my_usb_get_device_list();
63 resize(320, 240);
64 }
65
66 //关闭程序时被调用
67 USB::~USB()
68 {
69 #ifndef DEBUG_GUI
70 qDebug("close usb device.");
71 usb_close(udev);
72 #endif
73 }
74
75 //打开指定VID、PID的USB设备
76 usb_dev_handle *USB::open_dev(void)
77 {
78 struct usb_bus *bus;
79
80 for(bus = usb_get_busses(); bus; bus = bus->next) {
81 for(dev = bus->devices; dev; dev = dev->next) {
82 if((dev->descriptor.idVendor == MY_VID) && (dev->descriptor.idProduct == MY_PID)) {
83 return usb_open(dev);
84 }
85 }
86 }
87 return 0;
88 }
89
90 //打印USB设备描述符
91 void USB::printf_device_descriptor(usb_device_descriptor *desc)
92 {
93 qDebug("bLength: %u", desc->bLength);
94 qDebug("bDescriptorType: %02Xh", desc->bDescriptorType);
95 qDebug("bcdUSB: %04Xh", desc->bcdUSB);
96 qDebug("bDeviceClass: %02Xh", desc->bDeviceClass);
97 qDebug("bDeviceSubClass: %02Xh", desc->bDeviceSubClass);
98 qDebug("bDeviceProtocol: %02Xh", desc->bDeviceProtocol);
99 qDebug("bMaxPacketSize0: %02Xh", desc->bMaxPacketSize0);
100 qDebug("idVendor: %04Xh", desc->idVendor);
101 qDebug("idProduct: %04Xh", desc->idProduct);
102 qDebug("bcdDevice: %04Xh", desc->bcdDevice);
103 qDebug("iManufacturer: %u", desc->iManufacturer);
104 qDebug("iProduct: %u", desc->iProduct);
105 qDebug("iSerialNumber: %u", desc->iSerialNumber);
106 qDebug("bNumConfigurations: %u", desc->bNumConfigurations);
107 }
108
109 //指定USB设备的配置和接口
110 void USB::my_init_usbdev()
111 {
112 //libusb规定下面这两个函数必须要被调用
113 if (usb_set_configuration(udev, MY_CONFIG) < 0) {
114 qDebug("error setting config #%d: %s", MY_CONFIG, usb_strerror());
115 exit(1);
116 }
117 if (usb_claim_interface(udev, MY_INTF) < 0) {
118 qDebug("error claiming interface #%d:\n%s", MY_INTF, usb_strerror());
119 exit(1);
120 }
121 }
122
123 //发送按钮响应函数
124 void USB::send_slot()
125 {
126 int ret, num;
127 QString s = textEdit->toPlainText();
128 QByteArray a = s.toLatin1();
129 char *tmp = a.data();
130
131 num = s.length();
132 //qDebug()<<"text: "<<tmp<<"length: "<<num;
133 //批量写(同步)
134 ret = usb_bulk_write(udev, EP_OUT, tmp, num, 5000);
135 if (ret < 0) {
136 qDebug("error writing: %s", usb_strerror());
137 exit(1);
138 }
139 }
140
141 //读按钮响应函数
142 void USB::read_slot()
143 {
144 int ret;
145 char readdata[BUF_SIZE];
146
147 //批量读(同步)
148 ret = usb_bulk_read(udev, EP_IN, readdata, sizeof(readdata), 5000);
149 if (ret < 0) {
150 qDebug("error reading:%s", usb_strerror());
151 exit(1);
152 }
153 readdata[ret] = '\0';
154 //将接收到的数据显示在Label上
155 recvLabel->setText("recv: " + QLatin1String(readdata));
156 }
三、结果
运行上位机程序,在编辑框输入一些字符(数字),然后点击“send”按钮将数据发送给USB设备,点击“read”按钮将USB设备接收到的数据读回到上位机并显示在界面上,效果如下: