完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在上一节我们介绍了 MM32 MCU 的 HID 功能,对于HID 来说,虽然免驱,但是速度相对慢,有没有更好的选择呢?当然有,那就是WinUSB ,速度更快,对于现在的 PC 来说,基本上都是 Win10 ,WinUSB 在 Win10 免驱,此节我们就介绍如何使用 MM32 MCU的 WinUSB 功能。 WinUSB 设备是一种通用串行总线 (USB) 设备,其固件定义了某些 Microsoft 操作系统 (OS) 特征描述符,这些描述符将兼容 ID 报告为 "WINUSB"。 WinUSB 设备的用途是让 Windows 将 Winu***.sys 作为设备的功能驱动程序载入,而无需自定义 INF 文件。对于 WinUSB 设备,你无须为设备分发 INF 文件,对最终用户而言,这大大简化了驱动程序安装过程。相反,如果你需要提供自定义 INF,则不应将设备定义为 WinUSB 设备和在 INF 中指定设备的硬件 ID。 通常USB自定义设备都需要用户自己开发驱动,为了免去USB驱动开发,减少用户开发时间,微软花了不少心思,在Win8 或更高版本的Windows 系统中,集成了WinUSB 的WCID设备,从而WinUSB 作为微软提供的一个USB设备的通用驱动程序提供给用户,通过使用这个驱动,用户不再需要编写内核层的驱动程序就能够访问到USB设备。WCID是USB驱动一种新的匹配机制,在2012年左右引入的,通常USB设备都是通过VID和PID来进行匹配的,然而使用了WCID之后,USB设备不再通过VID和PID来匹配驱动,而是通过一个叫做兼容ID(Windows Compatible ID)来匹配,这样用户就不用为每一个VID和PID不同的设备编写INF文件了。当然我们要注意到,这里所说的免驱动包含两层含义:一层是用户不需要编写驱动程序,系统自带了驱动程序,只需写一个INF文件,比如USB串口;另一层则是不需要编写INF文件,系统会根据设备类型来安装驱动,这需要操作系统的支持。对于WinUSB设备来说,在Win8之前不用编写驱动程序,但是需要编写INF文件,匹配设备。在Win8之后,如果设备支持WCID,连INF也不用编写。 图1 WinUSB配置 下面将介绍如何在设备中增加对WCID的支持,让在能在Win8之后的系统上实在真正免驱即插即用。 首先我们得要有一个能够使用起来的自定义设备,在这个设备的设备描述符中,USB版本号设置为2.00,在这个设备的基础之上进行如下的修改: 修改一:响应ID为0xEE的字符描述符请求,字符描述的内容为: { 0x12, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'M', 0x00, /* wcChar0 */ 'S', 0x00, /* wcChar1 */ 'F', 0x00, /* wcChar2 */ 'T', 0x00, /* wcChar3 */ '1', 0x00, /* wcChar4 */ '0', 0x00, /* wcChar5 */ '0', 0x00, /* wcChar6 */ 0x17, /* bVendorCode */ 0x00, /* bReserved */ } 修改一:是为了让我们的自定设备被识别为WCID设备。 修改二:响应请求号为0x17并且index为4的厂商自定义请求,返回内容为: { 0x28, 0x00, 0x00, 0x00, /* dwLength */ 0x00, 0x01, /* bcdVersion */ 0x04, 0x00, /* wIndex */ 0x01, /* bCount */ 0,0,0,0,0,0,0, /* Reserved */ /* WCID Function */ 0x00, /* bFirstInterfaceNumber */ 0x01, /* bReserved */ /* CID */ 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* sub CID */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0,0,0, /* Reserved */ } 修改二是为了向Windows系统上报我们USB设备的WCID值,因为我们需要的是WinUSB的驱动程序,所以我们上报的内容信息就是WinUSB驱动的WCID:“WINUSB”。在修改上述内容完成后,将MM32 MCU的USB插入电脑,会发现设备能够自动安装上WinUSB驱动程序,然后显示如下所示: 图2 WinUSB驱动程序 本次我们采用MM32L373 miniboard作为测试开发板。为了方便大家使用MM32 MCU的WinUSB功能,我们已经封装好全部代码,用户不需要自己配置以上的那些描述符等参数,只需要了解MM32 MCU WinUSB的VID和PID以及如何处理WinUSB的数据接收和发送即可。 对于MM32 MCU的WinUSB功能来说,在使用WinUSB功能之前先调用USB初始化函数来初始化USB协议栈。 int main(void) { // USB Device Initialization and connect u***d_init(); u***d_connect(__TRUE); while (!u***d_configured()) // Wait for USB Device to configure { } while (1) { } } 然后就是WinUSB数据收发处理函数,USB数据处理函数如下: static U8 *ptrDataIn; static U16 DataInReceLen; static Bulk_queue Bulk_Cmd_queue; static volatile uint8_t USB_ResponseIdle; void u***d_bulk_init(void) { ptrDataIn = USBD_Bulk_BulkOutBuf; DataInReceLen = 0; Bulk_queue_init(&Bulk_Cmd_queue); USB_ResponseIdle = 1; } /* * USB Device Bulk In Endpoint Event Callback * Parameters: event: not used (just for compatibility) * Return Value: None */ void USBD_BULK_EP_BULKIN_Event(U32 event) { uint8_t * ***uf = 0; int slen; if(Bulk_queue_get_send_buf(&Bulk_Cmd_queue, &***uf, &slen)){ USBD_WriteEP(u***d_bulk_ep_bulkin | 0x80, ***uf, slen); } else { USB_ResponseIdle = 1; } } /* * USB Device Bulk Out Endpoint Event Callback * Parameters: event: not used (just for compatibility) * Return Value: None */ void USBD_BULK_EP_BULKOUT_Event(U32 event) { U16 bytes_rece; uint8_t * rbuf; bytes_rec = USBD_ReadEP(u***d_bulk_ep_bulkout, ptrDataIn, USBD_Bulk_BulkBufSize - DataInReceLen); ptrDataIn += bytes_rece; DataInReceLen += bytes_rece; if ((DataInReceLen >= USBD_Bulk_BulkBufSize) || (bytes_rece < u***d_bulk_maxpacketsize[USBD_HighSpeed])) { if(Bulk_queue_execute_buf(&Bulk_Cmd_queue,USBD_Bulk_BulkOutBuf, DataInReceLen, &rbuf)) { //Trigger the BULKIn for the reply if (USB_ResponseIdle) { USBD_BULK_EP_BULKIN_Event(0); USB_ResponseIdle = 0; } } //revert the input pointers DataInReceLen = 0; ptrDataIn = USBD_Bulk_BulkOutBuf; } } /* * USB Device Bulk In/Out Endpoint Event Callback * Parameters: event: USB Device Event * USBD_EVT_OUT: Output Event * USBD_EVT_IN: Input Event * Return Value: None */ void USBD_BULK_EP_BULK_Event(U32 event) { if (event & USBD_EVT_OUT) { USBD_BULK_EP_BULKOUT_Event(0); } if (event & USBD_EVT_IN) { USBD_BULK_EP_BULKIN_Event(0); } } void Bulk_queue_init(Bulk_queue *queue) { queue->recv_idx = 0; queue->send_idx = 0; queue->free_count = FREE_COUNT_INIT; queue->send_count = SEND_COUNT_INIT; } BOOL Bulk_queue_get_send_buf(Bulk_queue *queue, uint8_t **buf, int *len) { if (queue->send_count) { queue->send_count--; *buf = queue->USB_Request[queue->send_idx]; *len = queue->resp_size[queue->send_idx]; queue->send_idx = (queue->send_idx + 1) % Bulk_PACKET_COUNT; queue->free_count++; return (__TRUE); } return (__FALSE); } BOOL Bulk_queue_execute_buf(Bulk_queue *queue, const uint8_t *reqbuf, int len, uint8_t **retbuf) { uint32_t rsize; if (queue->free_count > 0) { if (len > Bulk_PACKET_SIZE) { len = Bulk_PACKET_SIZE; } queue->free_count--; memcpy(queue->USB_Request[queue->recv_idx], reqbuf, len); rsize = Bulk_ExecuteCommand(reqbuf, queue->USB_Request[queue->recv_idx]); queue->resp_size[queue->recv_idx] = rsize & 0xFFFF; //get the response size *retbuf = queue->USB_Request[queue->recv_idx]; queue->recv_idx = (queue->recv_idx + 1) % Bulk_PACKET_COUNT; queue->send_count++; return (__TRUE); } return (__FALSE); } 如上,我们只需要实现修改如下Bulk_ExecuteCommand即可处理我们收到的收据,并且填入我们发送数据出去队列即可发送出去。 为了验证MM32 MCU WinUSB功能,使用如下测试工具测试通信情况。 |
|
相关推荐
1 个讨论
|
|
只有小组成员才能发言,加入小组>>
2248个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11676 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5922 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
10953 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4571 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4297 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
964浏览 1评论
792浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 06:31 , Processed in 0.661929 second(s), Total 64, Slave 49 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号