IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> USB CDC虚拟串口复合设备 -> 正文阅读

[嵌入式]USB CDC虚拟串口复合设备

CDC包含一个控制接口和一个数据接口

1、控制接口

????????必要的有CM功能描述符和接口绑定描述符(IAD/Union)

在我电脑上测试控制接口的中断端点也可以不需要,及控制接口端点数量可以为0

1.1、ACM功能描述符:

? ? ? ? 在虚拟串口中,控制接口需要处理ACM 功能描述符。如下是一个ACM描述符,描述了虚拟串口的一些类特定请求,比如可以设置和获取的串口的波特率、停止位等等。

?参考:STM32 之 USB 虚拟串口_rannar的博客-CSDN博客_stm32 虚拟串口

bFunctionLength          : 0x04 (4 bytes)
bDescriptorType          : 0x24 (Interface)
bDescriptorSubType       : 0x02 (Abstract Control Management Functional Descriptor)
bmCapabilities           : 0x0F
 D7..4:                  : 0x00 (Reserved)
 D3   :                  : 0x01 (supports the notification Network_Connection)
 D2   :                  : 0x01 (supports the request Send_Break)
 D1   :                  : 0x01 (supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State)
 D0   :                  : 0x01 (supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature)
Data (HexDump)           : 04 24 02 0F                                       .$..

?1.2、IAD和Union描述符

IAD 与 Union 类似,Union 是旧版本下实现多个接口对应一个功能的功能描述符,而 IAD 是 USB 协会后来针对多个接口对应 一个功能的情况而扩展的,旧的主机可能只支持 Union 方式,但 IAD 并不会影响旧版本主机对设备的识别,因为旧版本主机 会通过 Union 来识别哪些接口是联合在一起的,对于 IAD 则跳过忽略;而新版主机则可以通过 IAD 来识别,跳过忽略老的 Union,因此两者可以完美兼容,互不影响。因而主机端可以精确地装载对应的驱动。

?两者功能相似,互不影响,分别针对新老协议。在我电脑上配置成多个CDC虚拟串口时,需要给定IAD才能正常出现多个串口(有Union并无区别)。

? ? ? bFirstInterface??第一个接口的序号,CDC的控制接口编号? ? ?
? ? ? bInterfaceCount?本CDC的接口数量,固定为2 (控制接口+数据接口)。数据接口必须紧跟控制接口。

????????bMasterInterface????????Communication class interface 控制接口的编号
????????bSlaveInterface0????????Data Class Interface? 数据接口的编号? (对比IAD 可以接口可以不连续)

2、 数据接口

????????简单的就包括一个接口描述符+两个断点描述符即可。

?
  //数据接口
        /*Data class interface descriptor*/
        0x09,                          /* bLength: Endpoint Descriptor size */
        USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
        0x01,                          /* bInterfaceNumber: Number of Interface */
        0x00,                          /* bAlternateSetting: Alternate setting */
        0x02,                          /* bNumEndpoints: Two endpoints used */
        0x0A,                          /* bInterfaceClass: CDC */
        0x00,                          /* bInterfaceSubClass: */
        0x00,                          /* bInterfaceProtocol: */
        0x00,                          /* iInterface: */
        /*Endpoint 1 Descriptor*/
        0x07,                         /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
        0x01,                         /* bEndpointAddress: (OUT1) */
        0x02,                         /* bmAttributes: Bulk */
        VIRTUAL_COM_PORT_DATA_SIZE,   /* wMaxPacketSize: */
        0x00,
        0x00, /* bInterval: ignore for Bulk transfer */
        /*Endpoint 1 Descriptor*/
        0x07,                         /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
        0x81,                         /* bEndpointAddress: (IN1) */
        0x02,                         /* bmAttributes: Bulk */
        VIRTUAL_COM_PORT_DATA_SIZE,   /* wMaxPacketSize: */
        0x00,
        0x00, /* bInterval */

?

3、多虚拟串口

3.1、设备描述符说明

设备描述附中就描述了设备类型,但作为复合设备,显然一个设备描述符肯定是不可以的。

  • bDeviceClass : 类型代码(由USB指定)。当它的值是0时,表示所有接口在配置描述符里,并且所有接口是独立的。当它的值是1到FEH时,表示不同的接口关联的。当它的值是FFH时,它是厂商自己定义的.

针对符合设备,bDeviceClass默认给0即可。

0x12,                       /*bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
0x00,                       /*bcdUSB */
0x02,
0x00, // 0x00, /*bDeviceClass*/
0x0,  // 0x00, /*bDeviceSubClass*/
0x0,  // 0x00, /*bDeviceProtocol*/
0x40, /*bMaxPacketSize40*/
0x77, /*idVendor ( )*/
0x86,
0x50, /*idProduct =  */
0x58,
0x00, /*bcdDevice rel. 2.00*/
0x02,
1,   /*Index of string descriptor describing manufacturer */
2,   /*Index of string descriptor describing  product*/
3,   /*Index of string descriptor describing the device serial number */
0x01 /*bNumConfigurations*/

3.2、配置描述符

知道了控制接口的功能后,就知道增加CDC设备需要修改的内容了,为了增加兼容性,IAD和Union描述符都加上吧。

uint8_t Custom_ConfigDescriptor[] = // 
    {
        0x09,                              /* bLength: Configuration Descriptor size */
        USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
        0,                                 // sizeof(CustomHID_ConfigDescriptor), 动态设置
        /* wTotalLength: Bytes returned */
        0x00,
        4,    /* bNumInterfaces: 1 interface 总的接口数量*/
        0x01, /* bConfigurationValue: Configuration value */
        0x00, /* iConfiguration: Index of string descriptor describing
                                         the configuration*/
        0xC0, /* bmAttributes: Self powered */
        0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */

#if 1         //虚拟串口 1
              //  IAD  Interface Association Descriptor //IAD描述符需要添加
        0x08, // bLength: Interface Descriptor size
        0x0B, // bDescriptorType: IAD
        0x00, // bFirstInterface                      //第一个控制接口的序号 控制接口0
        0x02, // bInterfaceCount                      //本IDA的接口数量 默认2
        0x02, // bFunctionClass: CDC                  //表明该IAD是一个CDC设备
        0x02, // bFunctionSubClass                    //默认
        0x01, // bFunctionProtocol                    //控制协议等其他我也不懂,默认就行
        0x02, // iFunction
        /*Interface Descriptor 控制接口*/
        0x09,                          /* bLength: Interface Descriptor size */
        USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
        /* Interface descriptor type */
        0x00, /* bInterfaceNumber: Number of Interface  */
        0x00, /* bAlternateSetting: Alternate setting */
        0x00, /* bNumEndpoints: One endpoints used */
        0x02, /* bInterfaceClass: Communication Interface Class */
        0x02, /* bInterfaceSubClass: Abstract Control Model */
        0x01, /* bInterfaceProtocol: Common AT commands */
        0x00, /* iInterface: */
              //    /*Header Functional Descriptor 非必须项*/
              //    0x05,   /* bLength: Endpoint Descriptor size */
              //    0x24,   /* bDescriptorType: CS_INTERFACE */
              //    0x00,   /* bDescriptorSubtype: Header Func Desc */
              //    0x10,   /* bcdCDC: spec release number */
              //    0x01,
              //    /*Call Management Functional Descriptor*/
              //    0x05,   /* bFunctionLength */
              //    0x24,   /* bDescriptorType: CS_INTERFACE */
              //    0x01,   /* bDescriptorSubtype: Call Management Func Desc */
              //    0x00,   /* bmCapabilities: D0+D1 */
              //    0x01,   /* bDataInterface: 1 */
        /*ACM Functional Descriptor 必须项*/
        0x04, /* bFunctionLength */
        0x24, /* bDescriptorType: CS_INTERFACE */
        0x02, /* bDescriptorSubtype: Abstract Control Management desc */
        0x0F, /* bmCapabilities  */
        /*Union Functional Descriptor 建议加上*/
        0x05, /* bFunctionLength */
        0x24, /* bDescriptorType: CS_INTERFACE */
        0x06, /* bDescriptorSubtype: Union func desc */
        0x00, /* bMasterInterface: Communication class interface 控制接口0*/
        0x01, /* bSlaveInterface0: Data Class Interface 数据接口1*/
              //    /*Endpoint 2 Descriptor 非必须项目 当前接口端点数量设置为0*/
              //    0x07,   /* bLength: Endpoint Descriptor size */
              //    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
              //    0x8A,   /* bEndpointAddress: (INx)  无效端口*/
              //    0x03,   /* bmAttributes: Interrupt */
              //    8,      /* wMaxPacketSize: */
              //    0x00,
              //    0xFF,   /* bInterval: */

        /*Data class interface descriptor  数据接口*/
        0x09,                          /* bLength: Endpoint Descriptor size */
        USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
        0x01,                          /* bInterfaceNumber: Number of Interface */
        0x00,                          /* bAlternateSetting: Alternate setting */
        0x02,                          /* bNumEndpoints: Two endpoints used */
        0x0A,                          /* bInterfaceClass: CDC */
        0x00,                          /* bInterfaceSubClass: */
        0x00,                          /* bInterfaceProtocol: */
        0x00,                          /* iInterface: */
        /*Endpoint 3 Descriptor*/
        0x07,                         /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
        0x01,                         /* bEndpointAddress: (OUT1) */
        0x02,                         /* bmAttributes: Bulk */
        VIRTUAL_COM_PORT_DATA_SIZE,   /* wMaxPacketSize: */
        0x00,
        0x00, /* bInterval: ignore for Bulk transfer */
        /*Endpoint 1 Descriptor*/
        0x07,                         /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
        0x81,                         /* bEndpointAddress: (IN1) */
        0x02,                         /* bmAttributes: Bulk */
        VIRTUAL_COM_PORT_DATA_SIZE,   /* wMaxPacketSize: */
        0x00,
        0x00, /* bInterval */
#endif

#if 1 虚拟串口 2

        /*---------------------------------------------------------------------------*/
        // IAD  Interface Association Descriptor
        0x08, // bLength: Interface Descriptor size
        0x0B, // bDescriptorType: IAD
        0x02, // bFirstInterface    控制接口2
        0x02, // bInterfaceCount    默认2
        0x02, // bFunctionClass: CDC
        0x02, // bFunctionSubClass
        0x01, // bFunctionProtocol
        0x02, // iFunction

        /*Interface Descriptor*/
        0x09,                          /* bLength: Interface Descriptor size */
        USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
        /* Interface descriptor type */
        0x02, /* bInterfaceNumber: Number of Interface */
        0x00, /* bAlternateSetting: Alternate setting */
        0x00, /* bNumEndpoints: One endpoints used */
        0x02, /* bInterfaceClass: Communication Interface Class */
        0x02, /* bInterfaceSubClass: Abstract Control Model */
        0x01, /* bInterfaceProtocol: Common AT commands */
        0x00, /* iInterface: */
              //    /*Header Functional Descriptor*/
              //    0x05,   /* bLength: Endpoint Descriptor size */
              //    0x24,   /* bDescriptorType: CS_INTERFACE */
              //    0x00,   /* bDescriptorSubtype: Header Func Desc */
              //    0x10,   /* bcdCDC: spec release number */
              //    0x01,
              //    /*Call Management Functional Descriptor*/
              //    0x05,   /* bFunctionLength */
              //    0x24,   /* bDescriptorType: CS_INTERFACE */
              //    0x01,   /* bDescriptorSubtype: Call Management Func Desc */
              //    0x00,   /* bmCapabilities: D0+D1 */
              //    0x01,   /* bDataInterface: 1 */
        /*ACM Functional Descriptor*/
        0x04, /* bFunctionLength */
        0x24, /* bDescriptorType: CS_INTERFACE */
        0x02, /* bDescriptorSubtype: Abstract Control Management desc */
        0x0F, /* bmCapabilities */
        /*Union Functional Descriptor*/
        0x05, /* bFunctionLength */
        0x24, /* bDescriptorType: CS_INTERFACE */
        0x06, /* bDescriptorSubtype: Union func desc */
        0x02, /* bMasterInterface: Communication class interface 控制接口2*/
        0x03, /* bSlaveInterface0: Data Class Interface 数据接口3 */
              //    /*Endpoint 2 Descriptor*/
              //    0x07,   /* bLength: Endpoint Descriptor size */
              //    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
              //    0x8B,   /* bEndpointAddress: (INx)  无效端口*/
              //    0x03,   /* bmAttributes: Interrupt */
              //    8,      /* wMaxPacketSize: */
              //    0x00,
              //    0xFF,   /* bInterval: */

        //数据接口
        /*Data class interface descriptor*/
        0x09,                          /* bLength: Endpoint Descriptor size */
        USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
        0x03,                          /* bInterfaceNumber: Number of Interface */
        0x00,                          /* bAlternateSetting: Alternate setting */
        0x02,                          /* bNumEndpoints: Two endpoints used */
        0x0A,                          /* bInterfaceClass: CDC */
        0x00,                          /* bInterfaceSubClass: */
        0x00,                          /* bInterfaceProtocol: */
        0x00,                          /* iInterface: */
        /*Endpoint 3 Descriptor*/
        0x07,                         /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
        0x02,                         /* bEndpointAddress: (OUT1) */
        0x02,                         /* bmAttributes: Bulk */
        VIRTUAL_COM_PORT_DATA_SIZE,   /* wMaxPacketSize: */
        0x00,
        0x00, /* bInterval: ignore for Bulk transfer */
        /*Endpoint 1 Descriptor*/
        0x07,                         /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
        0x82,                         /* bEndpointAddress: (IN1) */
        0x02,                         /* bmAttributes: Bulk */
        VIRTUAL_COM_PORT_DATA_SIZE,   /* wMaxPacketSize: */
        0x00,
        0x00, /* bInterval */
#endif
};     /* CustomHID_ConfigDescriptor */

另外还需实现虚拟串口类特定请求

        case GET_LINE_CODING://虚拟串口专用 获取串口通讯参数
            CopyRoutine = Virtual_Com_Port_GetLineCoding;
            break;
        case SET_LINE_CODING://虚拟串口专用 设置串口通讯参数
            CopyRoutine = Virtual_Com_Port_SetLineCoding;
            Request = SET_LINE_CODING;
            break;
        case SET_COMM_FEATURE://虚拟串口专用 
        {
            return USB_SUCCESS;
        }
        case SET_CONTROL_LINE_STATE://虚拟串口专用
        {
            return USB_SUCCESS;
        }

然后设备就出现了

?当然,还可以更多。。。

所以就可以自己做一个USB转6路TTL,大数据量压力测试,就放在后面做吧。

STM32-CDC6路串口.zip-嵌入式文档类资源-CSDN下载枚举6路虚拟串口,端口打开关闭正常,未实现串口部分更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/ai5945fei/46935702

4、端口存储和占用问题

WIn10系统会记录每次分配给设备的端口,保证下一次设备接入还是同样的端口。这个功能在自助终端设备上很重要。

?但是也会过多的占用我们经常用的靠前的编号,只需要在注册表?

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\COM Name Arbiter

把 ComDB 键删,系统会根据实际情况,重新生成这个键的。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:31:43  更:2021-11-23 12:31:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:48:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码