** 什么是 CDC 設(shè)備**
CDC 類是 USB 通信設(shè)備類 (Communication Device Class)的簡稱。由 USB 組織定義的專門給各種通信設(shè)備使用的 USB 子類。
通常,CDC類由兩個(gè)接口子類組成:
通信接口類 (Communication Interface Class)
主要用于主機(jī)對(duì)設(shè)備進(jìn)行管理和控制,它包含一個(gè)控制類型的端點(diǎn)和一個(gè)可選的中斷類型端點(diǎn)。
該控制類型端點(diǎn) 0 一般用作請求,可以用于配置 USB 設(shè)備枚舉虛擬串口的波特率、數(shù)據(jù)類型的設(shè)置,比如數(shù)據(jù)長度、停止位等。在虛擬串口應(yīng)用中,該操作并不一定需要具體實(shí)現(xiàn)。因?yàn)橹鳈C(jī)與設(shè)備在物理上通過 USB 總線進(jìn)行通信,與串口并沒有關(guān)系,在虛擬化過程中,起決定性作用的是串口驅(qū)動(dòng),該驅(qū)動(dòng)將每一條具體的虛擬串口操作對(duì)應(yīng)到實(shí)際上的USB操作。同時(shí),主機(jī)與設(shè)備之間的 USB 通信速率依然是標(biāo)準(zhǔn)的 USB2.0 Full-Speed(12Mbps)速度,并不受所謂的串口波特率影響,實(shí)際的速率取決于總線的實(shí)際使用率、驅(qū)動(dòng)訪問 USB 外設(shè)的有效速率(兩邊)以及外部環(huán)境對(duì)通信本身造成的干擾率等因素。
該中斷類型端點(diǎn)可以用于異步事件通知,設(shè)備端可以通過該端點(diǎn)向主機(jī)發(fā)送內(nèi)部時(shí)間等,如串口狀態(tài)變化事件等。篇幅受限,本文不進(jìn)行實(shí)現(xiàn)。
數(shù)據(jù)接口類 (Data Interface Class)
主要用于主機(jī)和設(shè)備之間進(jìn)行數(shù)據(jù)傳輸,包含輸入(IN)端點(diǎn)和輸出(OUT)端點(diǎn)。
- 輸入(IN)端點(diǎn):
用于從設(shè)備向主機(jī)發(fā)送數(shù)據(jù)。 - 輸出(OUT)端點(diǎn):
用于主機(jī)向從設(shè)備發(fā)送數(shù)據(jù)。
** 多路虛擬串口的具體實(shí)現(xiàn)**
多路虛擬串口功能可以通過組合設(shè)備(Composite Device)進(jìn)行實(shí)現(xiàn)。組合設(shè)備是指具有多個(gè)接口,且接口間相互獨(dú)立的USB設(shè)備。一個(gè)USB組合設(shè)備只有一個(gè)設(shè)備地址。在開發(fā)過程中,可以將不同的功能與不同的接口對(duì)應(yīng),來開發(fā)多功能的USB設(shè)備,描述符層次結(jié)構(gòu)更清晰,出錯(cuò)容易排查。
設(shè)備描述符
設(shè)備描述符(Device Descriptor)是在設(shè)備連接時(shí)主機(jī)讀取的第一個(gè)描述符,說明了 USB 設(shè)備的通用信息,提供關(guān)于設(shè)備、設(shè)備的配置以及任何設(shè)備所歸屬類的信息。主機(jī)在取得設(shè)備描述符后,就可以繼續(xù)去獲取設(shè)備的配置、接口和端點(diǎn)描述符等信息。
USB 設(shè)備只有一個(gè)設(shè)備描述符。在設(shè)備描述符中,可以使用 bDeviceClass = 0x00, bDeviceSubClass = 0x00, dDeviceProtocol = 0x00 表示此類信息在接口描述符內(nèi)給出;也可以使用【0xEF,0x02,0x01】表示當(dāng)前為組合設(shè)備。下圖為主機(jī)請求設(shè)備描述符,設(shè)備返回設(shè)備描述符報(bào)文:
配置描述符
配置描述符(Configuration Descriptor)說明了一個(gè)特定配置的相關(guān)信息。當(dāng)主機(jī)請求配置描述符時(shí),返回的是所有相關(guān)的接口和端點(diǎn)描述符。
一個(gè)USB設(shè)備有一個(gè)或多個(gè)配置描述符。配置描述符描述了配置所提供的接口數(shù)量。每個(gè)接口可以獨(dú)立操作。每種配置有一個(gè)或多個(gè)接口,而且每個(gè)接口有零個(gè)或多個(gè)端點(diǎn)。在一個(gè)配置中,接口不會(huì)共享一個(gè)端點(diǎn),除非端點(diǎn)被相同接口的備用設(shè)置使用。沒有這一限制、屬于不同配置的接口可以共享端點(diǎn)。
配置描述符規(guī)定了設(shè)備的特征和能力。一般單個(gè)配置已經(jīng)足夠了,但在驅(qū)動(dòng)程序的支持下,帶有多應(yīng)用或多電源選擇的設(shè)備可支持多重配置。且每次只有一個(gè)配置被激活。每個(gè)配置需要一個(gè)配置描述符,其中含有關(guān)于設(shè)備電源使用及所支持接口數(shù)的信息。每個(gè)配置描述符都有附屬描述符(subordinate descriptor),包括一個(gè)或多個(gè)接口描述符(Interface Descriptor)以及可選的端點(diǎn)描述符(Endpoint Descriptor)。
配置描述符如下:
接口描述符
下圖所示為標(biāo)準(zhǔn)的接口描述符定義。
單個(gè)CDC類的描述符需要兩個(gè)接口:通信接口描述符和數(shù)據(jù)接口描述符。這兩個(gè)接口需要接口關(guān)聯(lián)描述符(Interface Association Descriptor)進(jìn)行綁定。
接口關(guān)聯(lián)描述符
IAD 接口關(guān)聯(lián)描述符提供了一種功能:即把實(shí)現(xiàn)單個(gè)功能的多個(gè) Interface 打包在一起。通過接口關(guān)聯(lián)描述符打包在一起的若干 Interface 是同一個(gè)功能設(shè)備的 Interface,PC端只需要加載同一個(gè)驅(qū)動(dòng)即可。
通信(控制)接口描述符
該接口描述符需要包含功能描述符(Header,Call Management, ACM)、端點(diǎn)描述符。
** 功能描述符**
Header 功能描述符
Call Management 功能描述符
ACM
Union 功能描述符
數(shù)據(jù)接口描述符
端點(diǎn)描述符
下圖所示為標(biāo)準(zhǔn)的端點(diǎn)描述符定義。
本文中分配的端點(diǎn)如下:
代碼:
/* CDC 端點(diǎn)1 */
#define EPNUM_CDC_0_NOTIF 0x81
#define EPNUM_CDC_0_OUT 0x02
#define EPNUM_CDC_0_IN 0x82
/* CDC 端點(diǎn)2 */
#define EPNUM_CDC_1_NOTIF 0x83
#define EPNUM_CDC_1_OUT 0x04
#define EPNUM_CDC_1_IN 0x84
/* CDC 端點(diǎn)3 */
#define EPNUM_CDC_2_NOTIF 0x85
#define EPNUM_CDC_2_OUT 0x06
#define EPNUM_CDC_2_IN 0x86
配置描述符 / 接口描述符 / 端點(diǎn)描述符
uint8_t const desc_fs_configuration[] =
{
/* Config number, interface count, string index, total length, attribute, power in mA */
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
/* 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. */
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
/* 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. */
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
/* 3nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. */
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_2, 4, EPNUM_CDC_2_NOTIF, 8, EPNUM_CDC_2_OUT, EPNUM_CDC_2_IN, 64),
};
字符串描述符
char const* string_desc_arr [] =
{
(const char[]){0x09, 0x04}, // 0: Supported language: English (0x0409)
"MindMotion", // 1: Manufacturer
"MM32-3VCP", // 2: Product
"20221229", // 3: Serials
"CDC Virtual COM", // 4: CDC Interface
};
CDC Task 接口
在該接口函數(shù)中,本文主要實(shí)現(xiàn)了各個(gè)串口的回環(huán)功能,即在任務(wù)處理中發(fā)送當(dāng)前端點(diǎn)的接收字符。
void cdc_task(void)
{
uint8_t itf;
for (itf = 0; itf < CFG_TUD_CDC; itf++)
{
// connected() check for DTR bit
// Most but not all terminal client set this when making connection
// if ( tud_cdc_n_connected(itf) )
if ( tud_cdc_n_available(itf) )
{
uint8_t buf[64];
uint32_t count = tud_cdc_n_read(itf, buf, sizeof(buf));
echo_serial_port(itf, buf, count);
}
}
}
** 基本測試**
如上,我們就完成三路虛擬串口的CDC功能,將程序下載到MCU中,插上USB線,然后在電腦的設(shè)備管理器的端口欄就可以找到對(duì)應(yīng)的USB CDC枚舉模擬串口設(shè)備。
成功枚舉,我們繼續(xù)在Windows 和 Linux 環(huán)境下測試一下通信:
測試成功。本文分享到此結(jié)束,謝謝!
-
控制器
+關(guān)注
關(guān)注
112文章
16103瀏覽量
177073 -
USB通信
+關(guān)注
關(guān)注
0文章
22瀏覽量
10900 -
虛擬串口
+關(guān)注
關(guān)注
3文章
60瀏覽量
13855 -
MCU芯片
+關(guān)注
關(guān)注
3文章
246瀏覽量
11355
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論