最近有小伙伴反應(yīng)USB中的 usb_examples/usb_device_cdc_vcom 例程(USB虛擬串口VCOM)中的一些使用問題,今天集中來(lái)說(shuō)說(shuō)使用example的必知要點(diǎn)~
實(shí)驗(yàn)平臺(tái)和軟件版本說(shuō)明
本篇文章的實(shí)驗(yàn)平臺(tái)為:SDK_2_5_0_LPC54605J512oardslpcxpresso54608usb_examplesusb_device_cdc_vcom但實(shí)際上本篇文章適用于NXP大部分的硬件平臺(tái),因?yàn)閡sb_device_cdc_vcom(以下簡(jiǎn)稱vcom)這部分例程代碼和硬件關(guān)系并不大,屬于USB Stack之上的應(yīng)用部分,另外這部分代碼在SDK的各個(gè)版本上變化也不是很大,所以如果您使用的新版本的SDK,本篇文章也同樣適用。
目標(biāo)讀者
關(guān)于vcom的一些基礎(chǔ)環(huán)境搭建/編譯下載等基礎(chǔ)問題這篇文章不再贅述,具體可以參考example文件夾下的readme.pdf. 這里假設(shè)讀者:
有一定的USB基礎(chǔ)知識(shí)
已經(jīng)成功跑過(guò)這個(gè)vcom例程,大概瀏覽過(guò)源代碼,并且準(zhǔn)備使用vcom的代碼作為參考開發(fā)自己的項(xiàng)目產(chǎn)品
重要概念解釋
首先一個(gè)最基本的概念:USB所有傳輸都是主機(jī)發(fā)起的,從機(jī)只是被動(dòng)的響應(yīng)主機(jī)發(fā)來(lái)的請(qǐng)求
USB OUT 傳輸: 即 USB Host(如PC)向USB Device(如MCU)下發(fā)數(shù)據(jù), 對(duì)應(yīng)vcom 例程中事件kUSB_DeviceCdcEventRecvResponse. 這個(gè)很好理解:對(duì)于vcom例子,就是虛擬串口上有數(shù)據(jù)發(fā)到了MCU(比如PC端有一個(gè)上位機(jī)軟件,打開了虛擬串口,并且向虛擬串口寫入數(shù)據(jù))。每當(dāng)MCU收到數(shù)據(jù),都會(huì)進(jìn)入kUSB_DeviceCdcEventRecvResponse.在kUSB_DeviceCdcEventRecvResponse事件中,需要MCU這邊盡快的調(diào)用USB_DeviceCdcAcmRecv API將USB中的數(shù)據(jù)讀取出來(lái),然后USB Stack會(huì)和USB硬件一起準(zhǔn)備好下次USB OUT事件接收工作。(類似串口的DMA接收機(jī)制)
從下圖的CallStack可以看出,kUSB_DeviceCdcEventRecvResponse本質(zhì)就是BulkOut中斷回調(diào)上來(lái)的:
USB IN傳輸:即USB Host(PC) 向USB Device(如MCU)索要數(shù)據(jù), 比OUT傳輸稍微難理解一些:在vcom這個(gè)例程中,由于vcom屬于buck傳輸。每當(dāng)從機(jī)響應(yīng)上一個(gè)IN token之后,就會(huì)進(jìn)入kUSB_DeviceCdcEventSendResponse 事件,從下圖的CallStack也可以看到, kUSB_DeviceCdcEventSendResponse事件本質(zhì)就是 USB Buck In 中斷回調(diào)上來(lái)的:
所以每當(dāng)進(jìn)入到kUSB_DeviceCdcEventSendResponse的時(shí)候,都說(shuō)明USB IN傳輸已經(jīng)完成(或取消)。那么從機(jī)如何向主機(jī)發(fā)送數(shù)據(jù)呢?調(diào)用USB_DeviceCdcAcmSend 這個(gè)API。但是調(diào)用這個(gè)API你需要注意,每次調(diào)用這個(gè)API,你都需要等待發(fā)送完成事件(kUSB_DeviceCdcEventSendResponse) 或超時(shí)(第一次除外)。在任何時(shí)候,你都不能在代碼里連續(xù)調(diào)用USB_DeviceCdcAcmSend 多次。這個(gè)機(jī)制類似于串口DMA發(fā)送,即:每次調(diào)用串口DMA發(fā)送的時(shí)候,你都要確保上一次串口DMA發(fā)送已經(jīng)完成。 總結(jié)如下:
實(shí)際上,vcom例程實(shí)現(xiàn)的東西很簡(jiǎn)單,就是自發(fā)自收(echo),把虛擬串口接到的數(shù)據(jù)再原封不動(dòng)的發(fā)回而已。所涉及的數(shù)據(jù)傳輸過(guò)程中的事件也只有:kUSB_DeviceCdcEventSendResponse 和kUSB_DeviceCdcEventRecvResponse. 其他的USB Class回調(diào)事件實(shí)際上多半是有關(guān)一些配置,控制 (波特率,打開,關(guān)閉虛擬串口)等,這部分內(nèi)容暫不展開,需自學(xué)。
usb_device_cdc_vcom的問題 這個(gè)例程不太方便的地方就是代碼里把發(fā)送和接收是耦合在一起的,對(duì)于新手且對(duì)USB不熟悉的用戶,都不知道怎么解耦。實(shí)際應(yīng)用中,串口的發(fā)送和接收應(yīng)該是獨(dú)立的,沒有太大關(guān)系的,但是很可惜,這個(gè)example設(shè)計(jì)的時(shí)候硬生生的把發(fā)送和接收”粘”在一起,讓新手不太容易剝離開。
這里給出一個(gè)簡(jiǎn)單的改造方案,把VCOM的發(fā)送和接收拆開:
1. 首先對(duì)于USB_IN: 注釋掉之前的 USB_DeviceCDCAcmRecv部分,USB IN 傳輸和USB OUT之間沒有必然關(guān)系。另外在kUSB_DeviceCdcEventSendResponse中,定義一個(gè)標(biāo)志is_cdc_in_compelte (類比于串口的發(fā)送完成中斷,或者DMA發(fā)送完成中斷):
2. 對(duì)于USB OUT: 將之前的代碼替換為下圖,在收到Host下發(fā)的數(shù)據(jù)后,第一時(shí)間調(diào)用USB_DeviceCDCAcmRecv,把數(shù)據(jù)接下來(lái),然后通過(guò)一個(gè)消息隊(duì)列(你可以用你自己實(shí)現(xiàn)的一個(gè)消息隊(duì)列) 發(fā)送給應(yīng)用層。不要在DeviceCdcEventSendResponse中做過(guò)多的應(yīng)用層處理:
3. 其他的有關(guān)原demo中的一些變量,比如s_recvSize, s_sendSize 之類的,刪掉處理。在while(1)主循環(huán)中,處理USB中斷回調(diào)發(fā)出來(lái)的消息隊(duì)列:
通過(guò)解耦VCOM的Tx(發(fā)送)與Rx(接收),代碼不僅變得清晰簡(jiǎn)潔,還提升了模塊間的獨(dú)立性和可維護(hù)性。這種設(shè)計(jì)促進(jìn)了代碼的復(fù)用性和可擴(kuò)展性,為未來(lái)的功能升級(jí)或定制開發(fā)奠定了堅(jiān)實(shí)基礎(chǔ)。無(wú)論是對(duì)于初次接觸的開發(fā)者還是資深工程師,都能從中受益,享受更流暢的編程體驗(yàn)。希望本期分享對(duì)大家有所幫助!
恩智浦致力于打造安全的連接和基礎(chǔ)設(shè)施解決方案,為智慧生活保駕護(hù)航。
-
NXP
+關(guān)注
關(guān)注
60文章
1243瀏覽量
181459 -
usb
+關(guān)注
關(guān)注
60文章
7771瀏覽量
262351 -
虛擬串口
+關(guān)注
關(guān)注
3文章
60瀏覽量
13839 -
VCOM
+關(guān)注
關(guān)注
0文章
15瀏覽量
15449 -
指南針
+關(guān)注
關(guān)注
2文章
17瀏覽量
10836
原文標(biāo)題:關(guān)鍵指南針-NXP USB CDC_VCOM虛擬串口例程
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論