日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

USB CDC从理论到实践

發布時間:2023/12/29 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 USB CDC从理论到实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文摘自ST官網的“USB CDC類入門培訓”。整理的內容是我能夠看得懂的,認為比較實用的,記錄下來,以便以后查閱,同時也把原文檔中的筆誤給更正了一下。若要看更詳細的可以去ST技術文檔中查看,鏈接為:
http://bbs.21ic.com/forum.php?mod=viewthread&tid=726814&page=1&extra=#pid4225064

1 USB CDC類基礎理論知識介紹

1.1 USB CDC類、USB2.0標準與PSTN之間的關系

CDC(Communication Device Class)類是USB2.0標準下的一個子類,定義了通信相關設備的抽象集合。它與USB2.0標準以及其下的子類的相互關系如下圖所示:

如上圖,USB2.0標準下定義了很多子類,有音頻類,CDC類,HID,打印,大容量存儲類,HUB,智能卡等等,這些在usb.org官網上有具體的定義,這里主要介紹通信類CDC。

1.2 從一個具體的CDC類通信數據說起


如上圖,USB CDC類的通信部分主要包含三部分:枚舉過程、虛擬串口操作和數據通信。其中虛擬串口操作部分并不一定強制需要,因為若跳過這些虛擬串口的操作,實際上USB依然是可以通信的,這也就是為什么上圖中,在操作虛擬串口之前會有兩條數據通信的數據。之所以會有虛擬串口操作,主要是我們通常使用PC作為Host端,在PC端使用一個串口工具來與其進行通信,PC端的對應驅動將其虛擬成一個普通串口,這樣一來,可以方便PC端軟件通過操作串口的方式來與其進行通信,但實際上,Host端與Device端物理上是通過USB總線來進行通信的,與串口沒有關系,這一虛擬化過程,起決定性作用的是對應驅動,包含如何將每一條具體的虛擬串口操作對應到實際上的USB操作。需要注意的是,Host端與Device端的USB通信速率并不受所謂的串口波特率影響,它就是標準的USB2.0全速(12Mbps)速度,實際速率取決于總線的實際使用率、驅動訪問USB外設有效速率(兩邊)以及外部環境對通信本身造成的干擾率等因素組成。

1.3 CDC類設備枚舉過程

CDC類設備與其他標準USB設備枚舉過程的并沒有什么特殊的地方。在設備描述符內可以使用DeviceClass=0x00, SubClass=0x00, Protocol=0x00 表示此類信息在接口描述符內給出;或者也可以使用0x02,0x00,0x00;來表明該設備為CDC類設備。或者使用0xef, 0x02,0x01表示當前為復合設備。
CDC類設備在枚舉過程中最主要的信息存儲在配置描述符內:

如上圖所示,CDC類的配置描述符一般包含兩個接口:一個控制接口(Interface 0),另外一個是數據接口(Interface 1), 除此之外,還有一個虛線指向的IAD(Interface Association Description),表示這個是可選的,得根據實際情況來確定其是否真實存在。
在ST給出的CDC例程中,主要是使用SetLineCoding指令來設置和修改虛擬串口的波特率,使用GetLineCoding來獲取當前波特率,使用SetControlLineState來打開或關閉串口,這種操作是在Host端CDC驅動來具體映射實現的, Device端收到控制指令可以處理也可以不處理,用CubeMx自動生成的CDC類代碼對接收到的任何控制指令到沒有做任何處理,如果需要的話,用戶可按應用的需要來處理。

2 CDC類軟件框架介紹

2.1 CDC軟件框架簡介


如上圖所示,黃色USB Device Core部分為USB設備庫文件,屬于中間件,它為USB協議棧的核心源文件,一般不需要修改:

USB Device Core中,Log/debug為打印/調試開關;
core為USB設備核心;
USB request中定義了枚舉過程中各種標準請求的處理;
I/O request為底層針對USB通信接口的封裝。

黃色USB Device Class部分為USB類文件,也屬于中間件,USB設備庫,目前ST DEMO中支持的類有HID, Customer HID, CDC, MSC, DFU, Audio, ST提供了這些類的源碼框架,其他的Class或者是復合設備需要自己根據實際需求情況進行擴展或定制。如果用戶需求只是需要一個標準類,比如CDC通信,那么最好就使用現成的代碼,不需要做任何修改就可以實現這個CDC類通信的功能。
藍色USB Device HAL Driver為HAL庫部分,是對USB外設接口的封裝,屬于底層驅動,不需要修改,它分為PCD和LL Driver,PCD處于LL Driver之上。
洋紅色USB Device Configuration為USB配置封裝,位于USB底層HAL層驅動與中間件USB協議棧之間,一方面向上層(USB設備庫)提供各種操作調用接口,另一方面,向底層USB驅動提供各種回調接口。正是由于它的存在,使得USB協議棧(USB設備庫)與底層硬件完全分離,從而使USB設備庫具有更加兼容所有STM32的通用性。USB Device Configuration為開放給用戶的源文件,用戶可以根據自己的某些特殊需要進行修改,也可以使用默認的源文件,假如沒有任何特殊要求的話,我們使用默認即可。
Application為應用層,USB Device Class有可能將自己對應該的操作接口封裝在一個操作數據結構中,由應用來具體實現這些操作,在系統初始化時,由應用將已經定義好的操作接口注冊到對應的USB類中,比如usbd_cdc_if, 就這樣,使得應用層的應用代碼與屬于中間件層的USB協議棧分離。同時,USB協議棧會將一些字符串描述符放到APP中,當USB初始化時將這些已經定義好的字符串通過指針初始化到USB協議棧中,以便后續需要時獲取。

2.2 工程源碼文件與軟件框架的對應關系

2.3 USBD內核與USBD_CDC的關系

2.1節中,提到過ST官方Cube庫中提供的官方USB協議棧,主要是包含了USBD內核與USB各種類。USBD內核一般是固定的,用戶一般不需要修改,但USBD類,如果用戶需要修改或者擴展,比如復合設備或者用戶自定義設備,還有就是,ST目前官方提供的USB設備類的DEMO程序并沒有囊括所有USB類,因此,若用戶需要實現這些官方提供DEMO之外的USB類時,則用戶需要根據自己的需要來定制化自己的USB類。
ST提供的USB協議棧中已經有USBD內核,且這個內核源文件一般是不需要修改的,我們需要自定義這么一個USB類,我們首先得知道要自定義的USB類是如何與USBD內核打交道的。
USB協議棧將所有USB類都抽象成一個數據結構:USBD_ClassTypeDef,其定義如下所示:

這個結構體是一個抽象類,定義了一些虛擬函數,比如初始化,反初始化,類請求指令處理函數,端點0發送完成,端點0接收處理,數據發送完成,數據接收處理,SOF中斷處理,同步傳輸發送未完成,同步傳輸接收未完成處理等等;用戶在實現自己具體的USB類的時候需要將它實例化,USBD_ClassTypeDef結構體是USBD內核提供給外部定義一個USB設備類的窗口,而USB類文件(如usbd_cdc.c)實際就是實現這個結構體具體實例化的過程。最后將這個具體實例化的對象注冊到USBD內核的同時, USBD內核與USBD類也進行了關聯。

可以這么說,USBD內核與USBD類之間的紐帶就是USBD_ClassType這個結構體
下面我們來看看ST提供的CDC DEMO中具體CDC類:

這個就是具體一個CDC類實例化的對象,上層應用通過USBD_RegisterClass函數,將此對象注冊到usbd內核 :

它主要在usbd_cdc.c源文件中實現它的各個成員函數,當然,usbd_cdc.c源文件中,除了這些CDC類成員函數的具體實現之外,還包含其他一些對上層提供的接口,比如發送USBD_CDC_TransmitPacket, USBD_CDC_RegisterInterface,上層應用通過調用USBD_CDC_TransmitPacket來發送數據,通過USBD_CDC_RegisterInterface來注冊操作接口,這也是我們接下來將要講述的內容。

2.4 USBD_CDC與USBD_CDC_If的關系

講完了USBD內核與USBD_CDC的關系,接下來講USBD_CDC與上層應用是如何對接的。為了將USBD_CDC與上層應用層完全分離出來,類似USBD內核與USBD_CDC類完全分離一般,USBD_CDC類對上層同樣提供一個抽象的數據操作接口USBD_CDC_If結構體:

如上所示,如何處理來自Host端發送過來的控制指令和數據,完全是由應用層來決定,具體實現是應用層將此抽象的操作接口具體實例化,并注冊到USBD_CDC類對象中:

如上圖所示,通過引入USBD_CDC_If這么一個數據結構,就實現了USBD_CDC類與應用層的完全分離。USBD_CDC_If的具體實例化對象如下:

源文件usbd_cdc_if.c就是實現這些成員函數的過程,除此之外,還包含發送接口。最后應用層通過調用USBD_CDC_RegisterInterface函數將此操作接口注冊到USBD_CDC類中 :

2.5 應用接口

初始化 :

如上圖所示 :
初始化分4步:
1> 初始化USBD內核
2> 給USBD內核注冊USBD_CDC類
3> 給USBD_CDC類注冊USBD_CDC_If接口
4> 正式啟動USBD

  • 發送數據:
    uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
  • 接收回調處理:
    static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len);
  • 接收控制指令處理 :
    static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);

3 實踐動手部分

3.1 實驗環境及STM32F072-Discovery板簡介

硬件準備:

  • STM32F072 Discovery板一塊
  • Mini USB線兩根
  • PC一臺

軟件準備:

  • IAR V6.7.0 或者以上版本
  • STM32CubeF0 V1.7.0
  • STM32CubeMX V4.19
  • SSCOM串口工具
  • VCP虛擬串口驅動

3.2 使用STM32CubeMx制作CDC工程


使用內部48M的HSI48 RC作為時鐘源



最終生成的代碼工程與USB CDC類軟件框架的對應關系:

3.3 添加測試代碼

為了更好的驗證通信,我們需要添加點測試代碼:

在接收回調中,我們將接收到的數據轉給HandleReceiveData函數處理:

而在HandleReceiveData函數中我們將收到的數據原樣返回給Host端,這樣一來,Host端的串口工具將發送什么就將收到什么。

另一方面,我們定義了一全局變量StartFlag,它用來標志是否循環從Device端向Host端主動發送數據,其值由外部按鍵控制。然后在Main函數內的while(1)循環內添加如下測試代碼:

只要StartFlag標志為1,在枚舉結束后則不斷向Host端發送數據。

3.4 驗證結果

在編譯完并將代碼燒錄進MCU后,我們首先驗證PC端通過串口工具發送數據的情況:

如上圖所示,串口工具發送63個字節到Device端后,能夠接收到從Device端返回到的一模一樣的數據,這說明發送與接收都是正常的。

在按下用戶按鍵后,串口工具能夠無限收到來自Device端的數據。

收發同時進行也是正常的。至此,USB CDC設備端的收發驗證均正常。

3.5 注意事項

  • STM32CubeMx默認生成的工程在發送64整數倍數據的時候PC端收不到,這個問題可以參考以下兩個鏈接:
    http://blog.csdn.net/flydream0/article/details/53205286
    http://bbs.21ic.com/icview-1708972-1-1.html

  • CDC device端若無限向PC端發送數據,若PC端沒有及時讀走數據,導致PC端接收緩存爆滿,此時PC端回復NACK,此時會導致發送返回BUSY。

總結

以上是生活随笔為你收集整理的USB CDC从理论到实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。