加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 1. 概述
    • 2. 例程
    • 3.USB 枚舉(Enumeration)
    • 4. 數(shù)據(jù)傳輸
    • 5. 一個(gè)重要又容易被忽視的問題
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

單片機(jī)外圍模塊漫談之五,USB開發(fā),這個(gè)錯(cuò)誤你犯了嗎?

2020/12/24
152
閱讀需 11 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

1. 概述

我們已經(jīng)對(duì) USB 硬件和數(shù)據(jù)的四種傳輸類型有了一個(gè)基本的了解。

控制傳輸(Control Transfers)

批量傳輸(Bulk Data Transfers)

中斷傳輸(Interrupt Data Transfers)

同步傳輸(Isochronous Data Transfers)

下面我們通過一個(gè)例子看一下 USB 的具體工作過程。在此我們用一個(gè)比較實(shí)用的例子,就是把我們的板子用 USB 連接至 PC,然后在 PC 端出現(xiàn)一個(gè)模擬串口,通過串口助手打開這個(gè)串口,然后實(shí)現(xiàn)數(shù)據(jù)的雙向傳輸。最后我們聊一下很多工程師都會(huì)忽視的 USB 認(rèn)證問題。

2. 例程

我們打開 ST 的 Cube 庫中的 CDC 例程:

STM32Cube_FW_F1_V1.8.0ProjectsSTM3210C_EVALApplicationsUSB_DeviceCDC_StandaloneMDK-ARMProject.uvprojx

這個(gè)例程用到 USB 的同時(shí)還會(huì)用到 USART,USB 從 PC 端收到數(shù)據(jù)后會(huì)轉(zhuǎn)發(fā)到 USART,從 USART 接收到消息會(huì)上傳至 PC。我們可以把 USART 的 TX 和 RX 短接,這樣從 PC 端下發(fā)的數(shù)據(jù)會(huì)原樣回傳給 PC 端。

這個(gè)例程使用的硬件是 STM3210C-EVAL,原理圖可以在 stmcu.org.cn 找到。如果我們使用的是其它板子,就需要在這個(gè)工程基礎(chǔ)上做一些改動(dòng)。比如現(xiàn)在我們使用 STM32F105RBT6,8M 晶振,串口用 PTA2,PTA3,那么我們的要做如下修改:

首先,修改使用的 MCU

然后修改時(shí)鐘初始化部分。下圖為 STM32F105 時(shí)鐘模塊示意圖。USB 工作需要 48MHz 的時(shí)鐘。

(STM32F105xx Datasheet)

如果板子的晶振是 8M,那么參數(shù)需要做如下配置:

(OSC IN = 8M)

PREDIV1SRC? =? 0b0, HSE oscillator clock selected as PREDIV1 clock entry

PREDIV1 = 0b0, PREDIV1 input clock not divided

PLLSRC = 0b1, Clock from PREDIV1 selected as PLL input clock

PLLMUL = 0b0111, PLL input clock x 9

(PLLCLK = 72M)

SW = 0b10, PLL selected as system clock

PLLVCO = 2*PLLCLK? = 144M

USBPRE = 0, PLL clock is divided by 1.5 (or PLLVCO/3)

USB Clock =? = PLLCLK/1.5 = 72M/1.5 = 48M

例程中的對(duì)應(yīng)代碼修改:

最后修改使用的串口引腳

stm32f1xx_hal_msp.c

//AFIOCOMx_REMAP(0);??? // Remap USART2 to PTD5/6

usbd_cdc_interface.h

/* Definition for USARTx Pins */

//#define USARTx_TX_PIN? ? ?? GPIO_PIN_5

//#define USARTx_TX_GPIO_PORT? ?GPIOD

//#define USARTx_RX_PIN? ? ? ?GPIO_PIN_6

//#define USARTx_RX_GPIO_PORT? ?GPIOD

#define USARTx_TX_PIN? ? ? ? GPIO_PIN_2

#define USARTx_TX_GPIO_PORT? ? GPIOA

#define USARTx_RX_PIN? ? ? ? GPIO_PIN_3

#define USARTx_RX_GPIO_PORT? ? GPIOA

終于可以編譯運(yùn)行了,用 USB 線把板子連到 PC 的 USB 口,記得把板子的 PTA2和 PTA3引腳短接起來。在設(shè)備管理器我們看到多出來一個(gè)串口,看它的屬性會(huì)看到它的 VID,PID 跟我們程序中設(shè)置的一致。

用串口助手打開此串口,發(fā)送字符串,會(huì)看到返回同樣的字符串。

下面我們來看一下具體的工作過程。

3.USB 枚舉(Enumeration)

當(dāng)我們給設(shè)備上電,程序控制芯片內(nèi)集成的上拉電阻連接至 USBDP 時(shí),USB 主機(jī)(PC 端)會(huì)檢測(cè)到這一變化并向設(shè)備供電。此時(shí)設(shè)備處于 Powered 狀態(tài)。

主機(jī)等待 100ms 設(shè)備穩(wěn)定后復(fù)位并使能此端口,此時(shí)設(shè)備可以從 Vbus 獲取不超過 100mA 的電流,其默認(rèn)地址是 0,處于 Default 狀態(tài)。

主機(jī)通過 0 地址向該設(shè)備發(fā)送 Get_Descriptor 標(biāo)準(zhǔn)請(qǐng)求,獲取設(shè)備的描述符。主機(jī)再次復(fù)位該 PORT,并發(fā)送標(biāo)準(zhǔn)請(qǐng)求 Set_Address 給設(shè)備分配一個(gè)地址,之后的通信都是用此地址,設(shè)備進(jìn)入 Address 狀態(tài)。

主機(jī)通過新地址向設(shè)備再次發(fā)送 Get_Descriptor 標(biāo)準(zhǔn)請(qǐng)求,獲取設(shè)備描述符。發(fā)送 Get_Configuration 請(qǐng)求,獲取配置描述符。一個(gè)設(shè)備可以有多個(gè)配置,主機(jī)選擇合適配置,通過 Set_Configuration 請(qǐng)求對(duì)設(shè)備而進(jìn)行配置,設(shè)備進(jìn)入 Configured 狀態(tài)。

USB 的枚舉過程是標(biāo)準(zhǔn)的,所以庫里也有對(duì)應(yīng)的標(biāo)準(zhǔn)處理代碼。我們可以不用關(guān)心。好了,現(xiàn)在可以開始數(shù)據(jù)的雙向傳輸了。

4. 數(shù)據(jù)傳輸

我們已經(jīng)了解所有 USB 傳輸都是由 USB 主機(jī)(Host)發(fā)起的,作為 USB 設(shè)備只能是被動(dòng)的等待。當(dāng) Host 下發(fā)請(qǐng)求時(shí)會(huì)在設(shè)備中產(chǎn)生各種中斷,設(shè)備完成各種中斷的處理就行了。其中需要特別關(guān)注的有兩個(gè):

OEPINT(Output Endpoint Int),表明主機(jī)下發(fā)了數(shù)據(jù)。

IEPINT(Output Endpoint Int)。表明主機(jī)請(qǐng)求設(shè)備上傳數(shù)據(jù)。

那么用戶在代碼里如何收發(fā) USB 數(shù)據(jù)的呢?

我們?cè)?usbd_cdc_interface.c 里關(guān)注下面這些就夠了:

uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; //USB 下發(fā)數(shù)據(jù)緩沖區(qū)

uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; // 需要發(fā)給 USB 上位機(jī)的數(shù)據(jù)緩沖區(qū)

下面這個(gè)函數(shù)是用戶用來處理接收緩沖區(qū)數(shù)據(jù)的,在初始化時(shí)需要傳遞給 USB 驅(qū)動(dòng),然后驅(qū)動(dòng)收到 USB 下發(fā)的數(shù)據(jù)后會(huì)回調(diào)此函數(shù)。在例程中此函數(shù)把接收數(shù)據(jù)轉(zhuǎn)發(fā)給了 USART2。當(dāng)然你也可以什么都不做。

static int8_t CDC_Itf_Receive(uint8_t * Buf, uint32_t * Len);

那么如果有數(shù)據(jù)需要發(fā)給上位機(jī)呢?我們可以用下面這個(gè)函數(shù):

USBD_CDC_TransmitPacket(&USBD_Device);

注意此數(shù)據(jù)是先放入 IN 端點(diǎn),然后等待 IEPINT 中斷發(fā)生時(shí)才被取走發(fā)送。

5. 一個(gè)重要又容易被忽視的問題

至此好像萬事大吉了。

等等,如果產(chǎn)品這樣發(fā)出去,你可能給公司惹麻煩了!

還有一個(gè)很重要的問題我們千萬不要忽視,就是 VID 和 PID,既廠商識(shí)別符(Vendor ID)和產(chǎn)品識(shí)別符(Product ID)。我們例程中使用的是 VID 0x0483, PID 0x5740。這個(gè) VID 是專門分配給 ST 的,雖然我們用這個(gè)號(hào)程序也能運(yùn)行,但是不符合規(guī)范的。我們的可以在 usb.org/developers 網(wǎng)站查到當(dāng)前為所有 USB 廠商分配的 VID。如果我們要開發(fā) USB 設(shè)備,還要向 USB 組織申請(qǐng)自己的 VID,之后還要做微軟徽標(biāo)認(rèn)證,就可以暢行無阻了。

參考資料:

UM1734 STM32Cube USB device library

USB Specification 2.0

Universal Serial Bus Class Definitions for Communications Devices 1.2

STM32F105xx Datasheet

STM32F105xx RM

關(guān)注公眾號(hào),掃碼加入嵌入式交流群:

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
H11L1SR2M 1 Fairchild Semiconductor Corporation Logic IC Output Optocoupler, 1-Element, 7500V Isolation, 1MBps, SURFACE MOUNT, DIP-6
$1.01 查看
MOC3043M 1 Fairchild Semiconductor Corporation Triac Output Optocoupler With Zero CRSVR, 1-Element, 7500V Isolation, DIP-6
$1.02 查看
LCC110STR 1 IXYS Corporation Transistor Output SSR, 1-Channel, 3750V Isolation, ROHS COMPLIANT, SURFACE MOUNT PACKAGE-8
$4.44 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

TopSemic,讓芯片使用更簡(jiǎn)單。 專注分享:嵌入式,單片機(jī),STM32,ARM,RTOS,Linux, 軟硬件,半導(dǎo)體,電子技術(shù)等相關(guān)內(nèi)容。