28.USB-虛擬串口實驗
28.1實驗內(nèi)容
通過本實驗主要學(xué)習(xí)以下內(nèi)容:
CDC虛擬串口協(xié)議原理及使用
CDC虛擬串口通信操作
28.2實驗原理
USB的CDC類是USB通信設(shè)備類(Communication Device Class)的簡稱。CDC類是USB組織定義的一類專門給各種通信設(shè)備使用的USB子類。該設(shè)備類采用批量傳輸。
本例程中實現(xiàn)了CDC設(shè)備類的相關(guān)請求,包括SET_LINE_CODING、GET_LINE_CODING、SET_CONTROL_LINE_STATE等。后續(xù)將會在代碼解析章節(jié)進行介紹。
有關(guān)CDC協(xié)議可以通過以下USB官網(wǎng)下載或者通過紅楓派開發(fā)板配套資料獲取。
大家可以在學(xué)習(xí)的過程中結(jié)合歷程代碼和協(xié)議進行理解。
28.3硬件設(shè)計
USB虛擬鍵盤實驗章節(jié)已介紹。
28.4代碼解析
本例程主要實現(xiàn)USB虛擬串口的效果,在PC端可以通過串口調(diào)試助手或者設(shè)備管理器查到虛擬串口設(shè)備,并可實現(xiàn)通過該虛擬串口進行通信的現(xiàn)象。
本例程主函數(shù)如下,該函數(shù)架構(gòu)與虛擬鍵盤例程相似,當USBD設(shè)備初始化且枚舉完成后,USB設(shè)備首先通過cdc_acm_check_ready()函數(shù)check是否準備數(shù)據(jù)發(fā)送,如果不需要發(fā)送就調(diào)用cdc_acm_data_receive()函數(shù)接收上位機發(fā)送的數(shù)據(jù),如果需要發(fā)送就調(diào)用cdc_acm_data_send()將接收到的數(shù)據(jù)發(fā)送給主機,主機再回顯到串口調(diào)試助手的接收顯示界面中。
C int main(void) { /* system clocks configuration */ rcu_config(); /* GPIO configuration */ gpio_config(); /* USB device configuration */ usbd_init(&usbd_cdc, &cdc_desc, &cdc_class); /* NVIC configuration */ nvic_config(); /* enabled USB pull-up */ usbd_connect(&usbd_cdc); while (USBD_CONFIGURED != usbd_cdc.cur_status) { /* wait for standard USB enumeration is finished */ } while (1) { if (0U == cdc_acm_check_ready(&usbd_cdc)) { cdc_acm_data_receive(&usbd_cdc); } else { cdc_acm_data_send(&usbd_cdc); } } } |
下面為大家介紹下虛擬串口設(shè)備所使用的設(shè)備及配置描述符。
設(shè)備描述符如下所示,其中bDevcieClass為0x02,表明當前設(shè)備為CDC設(shè)備類。
C usb_desc_dev cdc_dev_desc = { .header = { .bLength = USB_DEV_DESC_LEN, .bDescriptorType = USB_DESCTYPE_DEV, }, .bcdUSB = 0x0200U, .bDeviceClass = USB_CLASS_CDC, .bDeviceSubClass = 0x00U, .bDeviceProtocol = 0x00U, .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, .idVendor = USBD_VID, .idProduct = USBD_PID, .bcdDevice = 0x0100U, .iManufacturer = STR_IDX_MFC, .iProduct = STR_IDX_PRODUCT, .iSerialNumber = STR_IDX_SERIAL, .bNumberConfigurations = USBD_CFG_MAX_NUM, }; |
配置描述符如下所示,由配置描述符可知,該USB虛擬串口設(shè)備包含兩個接口:CMD命令接口和data數(shù)據(jù)接口。CMD命令接口包含一個IN端點,用于傳輸命令,該端點采用中斷傳輸方式,輪詢間隔為10ms,最大包長為8字節(jié)。data數(shù)據(jù)接口包含一個OUT端點和一個IN端點,這兩個端點均采用批量傳輸方式,最大包長為64字節(jié)。另外,該配置描述符中包含了一些類特殊接口描述符,具體請讀者參閱CDC類標準協(xié)議。
C usb_cdc_desc_config_set cdc_config_desc = { .config = { .header = { .bLength = sizeof(usb_desc_config), .bDescriptorType = USB_DESCTYPE_CONFIG, }, .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, .bNumInterfaces = 0x02U, .bConfigurationValue = 0x01U, .iConfiguration = 0x00U, .bmAttributes = 0x80U, .bMaxPower = 0x32U }, .cmd_itf = { .header = { .bLength = sizeof(usb_desc_itf), .bDescriptorType = USB_DESCTYPE_ITF }, .bInterfaceNumber = 0x00U, .bAlternateSetting = 0x00U, .bNumEndpoints = 0x01U, .bInterfaceClass = USB_CLASS_CDC, .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, .iInterface = 0x00U }, .cdc_header = { .header = { .bLength = sizeof(usb_desc_header_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE }, .bDescriptorSubtype = 0x00U, .bcdCDC = 0x0110U }, .cdc_call_managment = { .header = { .bLength = sizeof(usb_desc_call_managment_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE }, .bDescriptorSubtype = 0x01U, .bmCapabilities = 0x00U, .bDataInterface = 0x01U }, .cdc_acm = { .header = { .bLength = sizeof(usb_desc_acm_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE }, .bDescriptorSubtype = 0x02U, .bmCapabilities = 0x02U, }, .cdc_union = { .header = { .bLength = sizeof(usb_desc_union_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE }, .bDescriptorSubtype = 0x06U, .bMasterInterface = 0x00U, .bSlaveInterface0 = 0x01U, }, .cdc_cmd_endpoint = { .header = { .bLength = sizeof(usb_desc_ep), .bDescriptorType = USB_DESCTYPE_EP, }, .bEndpointAddress = CDC_CMD_EP, .bmAttributes = USB_EP_ATTR_INT, .wMaxPacketSize = CDC_ACM_CMD_PACKET_SIZE, .bInterval = 0x0AU }, .cdc_data_interface = { .header = { .bLength = sizeof(usb_desc_itf), .bDescriptorType = USB_DESCTYPE_ITF, }, .bInterfaceNumber = 0x01U, .bAlternateSetting = 0x00U, .bNumEndpoints = 0x02U, .bInterfaceClass = USB_CLASS_DATA, .bInterfaceSubClass = 0x00U, .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, .iInterface = 0x00U }, .cdc_out_endpoint = { .header = { .bLength = sizeof(usb_desc_ep), .bDescriptorType = USB_DESCTYPE_EP, }, .bEndpointAddress = CDC_OUT_EP, .bmAttributes = USB_EP_ATTR_BULK, .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, .bInterval = 0x00U }, .cdc_in_endpoint = { .header = { .bLength = sizeof(usb_desc_ep), .bDescriptorType = USB_DESCTYPE_EP }, .bEndpointAddress = CDC_IN_EP, .bmAttributes = USB_EP_ATTR_BULK, .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, .bInterval = 0x00U } }; |
為了實現(xiàn)CDC設(shè)備類,設(shè)備需要支持一些設(shè)備類專用請求,這些類專用請求的處理在cdc_acm_req_handler()函數(shù)中,該函數(shù)的定義如下所示,其中SET_LINE_CODING命令用于響應(yīng)主機向設(shè)備發(fā)送設(shè)備配置,包括波特率、停止位、字符位數(shù)等,收到的數(shù)據(jù)保存在noti_bu內(nèi)。GET_LINE_CODING命令用于主機請求設(shè)備當前的波特率、停止位、奇偶校驗位和字符位數(shù),但在本例程中,主機并未請求該命令,所以設(shè)備所設(shè)置的串口數(shù)據(jù)并沒有作用,主機可以選擇任意波特率與設(shè)備進行通信。其他的命令在本例程中并未進行處理,讀者可以參考標準CDC類協(xié)議。
C static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req) { uint8_t status = REQ_NOTSUPP, noti_buf[10] = {0U}; usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; acm_notification *notif = (void *)noti_buf; switch (req->bRequest) { case SEND_ENCAPSULATED_COMMAND: break; case GET_ENCAPSULATED_RESPONSE: break; case SET_COMM_FEATURE: break; case GET_COMM_FEATURE: break; case CLEAR_COMM_FEATURE: break; case SET_LINE_CODING: /* set the value of the current command to be processed */ udev->class_core->req_cmd = req->bRequest; usb_transc_config(&udev->transc_out[0U], (uint8_t *)&cdc->line_coding, req->wLength, 0U); status = REQ_SUPP; break; case GET_LINE_CODING: usb_transc_config(&udev->transc_in[0U], (uint8_t *)&cdc->line_coding, 7U, 0U); status = REQ_SUPP; break; case SET_CONTROL_LINE_STATE: notif->bmRequestType = 0xA1U; notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; notif->wIndex = 0U; notif->wValue = 0U; notif->wLength = 2U; noti_buf[8] = (uint8_t)req->wValue & 3U; noti_buf[9] = 0U; status = REQ_SUPP; break; case SEND_BREAK: break; default: break; } return status; } |
下面為大家介紹USBD虛擬串口設(shè)備數(shù)據(jù)的收發(fā)。
數(shù)據(jù)接收通過cdc_acm_data_receive()函數(shù)實現(xiàn),該函數(shù)的程序如下所示。在該函數(shù)中,首先將packet_receive標志位設(shè)置為0,表明接下來將進行接收數(shù)據(jù),當接收完成時,在cdc_acm_data_out()函數(shù)中,將packet_receive標志位置1,表明數(shù)據(jù)接收完成。usbd_ep_recev()用于配置接收操作,利用CDC_OUT_EP端點,將接收到的數(shù)據(jù)放置在cdc->data用戶緩沖區(qū)中。
C void cdc_acm_data_receive(usb_dev *udev) { usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; cdc->packet_receive = 0U; cdc->pre_packet_send = 0U; usbd_ep_recev(udev, CDC_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_RX_LEN); } static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num) { usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; cdc->packet_receive = 1U; cdc->receive_length = udev->transc_out[ep_num].xfer_count; } |
數(shù)據(jù)發(fā)送通過cdc_acm_data_send()函數(shù)實現(xiàn),該函數(shù)的程序如下所示。在該函數(shù)中,首先將packet_sent標志位設(shè)置為0,表明接下來將進行發(fā)送數(shù)據(jù),當數(shù)據(jù)發(fā)送完成時,在cdc_acm_data_in()函數(shù)中,將packet_sent標志位設(shè)置為1,表明數(shù)據(jù)發(fā)送完成。usbd_ep_send()用于配置發(fā)送操作,利用CDC_IN_EP端點,將以cdc->data地址為起始data_len長度的數(shù)據(jù)發(fā)送給主機。
C void cdc_acm_data_send (usb_dev *udev) { usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; uint32_t data_len = cdc->receive_length; if ((0U != data_len) && (1U == cdc->packet_sent)) { cdc->packet_sent = 0U; usbd_ep_send(udev, CDC_IN_EP, (uint8_t*)(cdc->data), (uint16_t)data_len); cdc->receive_length = 0U; } } static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num) { usb_transc *transc = &udev->transc_in[ep_num]; usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; if (transc->xfer_count == transc->max_len) { usbd_ep_send(udev, EP_ID(ep_num), NULL, 0U); } else { cdc->packet_sent = 1U; cdc->pre_packet_send = 1U; } } |
28.5實驗結(jié)果
將本例程燒錄到紅楓派開發(fā)板中,并通過TypeC數(shù)據(jù)線連接USB通信接口和PC,在WIN7上虛擬串口需要安裝驅(qū)動,在WIN8 WIN10以及后續(xù)版本的系統(tǒng)上不需要安裝驅(qū)動。
下面介紹WIN7系統(tǒng)的驅(qū)動安裝過程。
在WIN7系統(tǒng)上,將Tyep C數(shù)據(jù)線連接到PC后,將會在設(shè)備管理器中發(fā)現(xiàn)一個未知設(shè)備,通過以下連接可以下載官方提供的虛擬串口驅(qū)動:https://www.gd32mcu.com/download/down/document_id/44/path_type/1
下載驅(qū)動并進行安裝,之后將會在設(shè)備管理器中發(fā)現(xiàn)虛擬串口設(shè)備已經(jīng)識別。
之后即可通過串口調(diào)試助手與MCU進行CDC通信,在串口調(diào)試助手中打開對應(yīng)虛擬串口的端口,然后輸入任意字符,進行發(fā)送,將會在接收窗口中看到MCU返回的接收數(shù)據(jù),具體現(xiàn)象如下所示。
上一篇:【GD32H757Z海棠派開發(fā)板使用手冊】第十五講 TFT-8080電阻屏屏觸摸實驗
下一篇:【GD32F303紅楓派開發(fā)板使用手冊】第二十一講 I2C-EEPROM讀寫實驗
推薦閱讀最新更新時間:2025-06-29 20:37





設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- Microchip 升級數(shù)字信號控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- LTC3806 反激式控制器改善了多輸出應(yīng)用的交叉調(diào)節(jié)
- BTS 723 GW智能高端電源開關(guān)典型應(yīng)用電路
- 具有正電源的 LT3091HDE 500mA LED 驅(qū)動器的典型應(yīng)用
- SG3525A驅(qū)動功率場效應(yīng)管用于脈寬調(diào)制器控制電路的典型應(yīng)用
- LTC2945IMS-1 隔離式寬范圍 I2C 功率監(jiān)視器的典型應(yīng)用
- 用于 LED 照明的 DC 到 DC 單路輸出電源
- STEVAL-ILL015V2,基于 LED2472G 和 STM32 HB LED 驅(qū)動器的評估板,具有診斷功能
- 使用 ROHM Semiconductor 的 BD45471 的參考設(shè)計
- MAP9004,使用 MAP9004 高壓交流 LED 驅(qū)動器的典型應(yīng)用電路,用于 4 通道復(fù)合解決方案
- LTC3100,具有電壓排序功能的單節(jié)電池雙輸出轉(zhuǎn)換器
- 關(guān)于ST-Link下載STM32程序的使用
- 驍龍8 Gen 1首款屏下攝像手機,聯(lián)想moto edge X30
- 半導(dǎo)體設(shè)備精密零部件供應(yīng)商,先鋒半導(dǎo)體獲得數(shù)億元股權(quán)融資
- 傳言谷歌將在Q4推出折疊屏手機
- 初學(xué)stm32-通用定時器的使用
- 三菱plc的電磁干擾的主要來源和途徑
- STM32的DMA基本原理及實現(xiàn)過程
- SylixOS的BSP開發(fā)實例之S3C2416 【第三篇】S3C2416 寄存器描述
- 技術(shù)貼:校準泰克數(shù)字示波器的步驟
- MSP430 G2553 LaunchPad設(shè)置GPIO
- PCIe M.2接口測試的現(xiàn)狀、挑戰(zhàn)與泰克解決方案
- ABB在中國推出面向電子制造業(yè)的兩大全新機器人系列
- ABB在中國推出PoWa協(xié)作機器人系列
- 西門子 NX 新增 AI 助手等多項功能
- 貿(mào)澤即日起開售適用于數(shù)據(jù)中心和網(wǎng)絡(luò)應(yīng)用的 全新TE Connectivity QSFP 112G SMT連接器
- ABB推出三大全新機器人系列,強化中國機器人市場領(lǐng)導(dǎo)地位
- 新思科技關(guān)于美國解除近期對華出口限制的聲明
- Wolfspeed 1700 V MOSFET 技術(shù),助力重塑輔助電源系統(tǒng)的耐用性和成本
- 英飛凌大中華區(qū) 2025 生態(tài)創(chuàng)新峰會,究竟探討了哪些創(chuàng)新與生態(tài)合作?
- Microchip攜手Nippon Chemi-Con和NetVision 打造日本汽車市場首個ASA-ML攝像頭開發(fā)生態(tài)系統(tǒng)
- 英特爾助推物聯(lián)網(wǎng)創(chuàng)新應(yīng)用落地,2020 EdgeX中國挑戰(zhàn)賽打響
- Nordic低功耗藍牙SoC無線跟蹤器產(chǎn)品讓你不在丟三落四
- 推動SOC全生命周期管理設(shè)計,西門子收購UltraSoC
- BionicFlower仿生花:仿生機器花朵
- 人造羽毛讓仿生飛燕在空中成群飛舞
- 5G助力智能巡檢機器人,開啟新的大安防時代
- 擎朗智能獲融資 專注于發(fā)展無人配送機器人
- 英特爾賦能服務(wù)機器人 將持續(xù)發(fā)揮端到端的技術(shù)實力
- 大疆跨界教育機器人 支持自定義UI
- 電動汽車市場機會丨半導(dǎo)體襯底為汽車應(yīng)用賦能