一、概述
????無論是新手還是大佬,基于STM32單片機的開發,使用STM32CubeMX都是可以極大提升開發效率的,并且其界面化的開發,也大大降低了新手對STM32單片機的開發門檻。
????本文主要講述STM32芯片USB功能的配置及其相關知識。
二、軟件說明
????STM32CubeMX是ST官方出的一款針對ST的MCU/MPU跨平臺的圖形化工具,支持在Linux、MacOS、Window系統下開發,其對接的底層接口是HAL庫,另外習慣于寄存器開發的同學們,也可以使用LL庫。STM32CubeMX除了集成MCU/MPU的硬件抽象層,另外還集成了像RTOS,文件系統,USB,網絡,顯示,嵌入式AI等中間件,這樣開發者就能夠很輕松的完成MCU/MPU的底層驅動的配置,留出更多精力開發上層功能邏輯,能夠更進一步提高了嵌入式開發效率。
????演示版本 6.1.0
三、USB功能簡介
-
頂部模塊: - Analog transceiver:模擬收發器,通過 DP 和 DM 引腳實現物理層信號的收發,是 USB 與外部連接的接口。
-
綠色區域(USB 時鐘 48MHz 驅動): - Suspend timer:掛起定時器,用于管理 USB 的掛起狀態。 - RX - TX、Control S.I.E.:負責數據的接收(RX)與發送(TX),以及控制相關操作。 - Clock recovery:時鐘恢復模塊,從輸入信號中恢復時鐘。 - Endpoint selection:端點選擇模塊,用于選擇不同的 USB 端點。 - 這些模塊連接到 Control registers and logic(控制寄存器及邏輯)和 Interrupt registers and logic(中斷寄存器及邏輯),實現配置與中斷管理;同時連接到多個 Endpoint registers(端點寄存器),用于存儲端點相關數據。 - Packet buffer interface:數據包緩沖區接口,負責與下方的緩沖區模塊交互。
-
灰色區域(PCLK 驅動,通過 APB1 總線通信): - Arbiter:仲裁器,管理總線訪問優先級。 - Packet buffer memory:數據包緩沖存儲器,存儲 USB 數據。 - Register mapper:寄存器映射,將端點寄存器映射到系統地址空間。 - Interrupt mapper:中斷映射,將 USB 中斷路由到 NVIC(嵌套向量中斷控制器)。 - APB1 wrapper:APB1 總線封裝,通過 APB1_bus 與系統連接,PCLK1 提供時鐘。 整體上,該框圖展示了 USB 外設從物理信號收發、時鐘處理、數據傳輸到系統接口(APB1)的完整流程,以及寄存器配置、中斷管理等功能模塊的協作關系。
四、USB配置及代碼實現
- STM32CubeMX配置
????這是USB設備類選擇的下拉菜單,因為我們要實現一個U盤的功能,所以這里我們選擇Mass Storage Class(簡稱MSC)
。
Disable:禁用,表示不使用任何設備類功能。
Audio Device Class:音頻設備類,用于音頻相關設備,如聲卡、耳機等音頻輸入輸出設備。
Communication Device Class (Virtual Port Com):通信設備類(虛擬串口),用于實現虛擬串口通信功能,方便設備與計算機進行數據傳輸,常應用于一些需要串口通信模擬的場景。
Download Firmware Update Class (DFU):下載固件更新類,用于設備固件的更新操作,允許設備在運行過程中通過特定方式更新自身固件。
Human Interface Device Class (HID):人機接口設備類,像鍵盤、鼠標、游戲手柄等直接與用戶交互的設備屬于此類。
Custom Human Interface Device Class (HID):自定義人機接口設備類,是在標準 HID 基礎上,根據特定需求進行定制開發的人機交互設備類別。
Mass Storage Class:大容量存儲類,用于 U 盤、移動硬盤等存儲設備,使設備能像存儲介質一樣被計算機識別和讀寫數據。
????這部分是 USB 設備相關的參數設置,分為 Basic Parameters(基本參數) 和 Class Parameters(類參數) 兩部分,這些參數共同配置了 USB 設備的基本屬性、調試行為以及大容量存儲類的緩沖區設置,確保設備在特定場景下正常工作。
-
Basic Parameters
USBD_MAX_NUM_INTERFACES:表示 USB 設備支持的最大接口數量,圖中設置為 1。接口用于區分設備的不同功能(如一個設備僅實現單一功能時,接口數為 1)。
USBD_MAX_NUM_CONFIGURATION:最大配置數量,設為 1。USB 設備配置代表不同工作模式,此處表示僅有一種工作模式。
USBD_MAX_STR_DESC_SIZE:USB 描述符字符串的最大長度,為 512 bytes,用于定義設備名稱等描述信息的最大長度。
USBD_SELF_POWERED:設備自供電狀態,顯示 Enabled,即設備采用自供電方式,而非依賴 USB 主機供電。
USBD_DEBUG_LEVEL:調試級別為 0: No debug message,表示調試時不輸出任何調試信息。 -
Class Parameters
MSC_MEDIA_PACKET:針對大容量存儲類(Mass Storage Class, MSC),定義媒體輸入 / 輸出緩沖區大小為 512 bytes,用于數據傳輸時的緩沖處理。
????這部分是 USB 設備描述符相關的配置信息,分為 Device Descriptor(設備描述符) 和 Device Descriptor FS(全速設備描述符) 兩部分,這些描述符信息是 USB 設備在與主機通信時,用于向主機聲明自身屬性和功能的關鍵參數,確保設備能被正確識別和驅動,這部分不需要修改,了解下其作用即可。
- Device Descriptor
VID (Vendor Identifier):廠商標識符,值為 1155,用于唯一標識設備的生產廠商。
LANGID_STRING (Language Identifier):語言標識符,值為 English(United States),表示設備使用的語言為美國英語。
MANUFACTURER_STRING (Manufacturer Identifier):制造商標識符,值為 STMicroelectronics,表明設備由意法半導體制造。 - Device Descriptor FS
PID (Product Identifier):產品標識符,值為 22314,用于唯一標識該廠商下的具體產品。
PRODUCT_STRING (Product Identifier):產品描述字符串,值為 STM32 Mass Storage,說明這是一個基于 STM32 的大容量存儲設備(如 U 盤、移動存儲等)。
CONFIGURATION_STRING (Configuration Identifier):配置描述字符串,值為 MSC Config,表示設備的配置與大容量存儲類(Mass Storage Class, MSC)相關。
INTERFACE_STRING (Interface Identifier):接口描述字符串,值為 MSC Interface,表明設備使用的接口屬于大容量存儲類接口,用于實現數據的存儲讀寫功能。
????完整配置如下,USB 協議規定時鐘誤差需≤±0.25%,而STM32F103的內部 RC 振蕩器(HSI,8MHz)精度僅 ±1%,無法滿足要求,所以這時必須使用外部晶振。時鐘按CubeMX自己計算的即可,一般是用48MHz。
- 相關接口實現
????完成以上配置后生成工程,為實現電腦對U盤的讀寫功能,這里還需要實現usbd_storage_if.c
文件下的STORAGE_Read_FS
和STORAGE_Write_FS
接口,以完成電腦識別USB后對單片機內部Flash的操作,同時可以修改一下STORAGE_GetCapacity_FS
接口,用來給電腦識別U盤設備的容量大小。如果需要使用外部Flash,則在此處實現外部Flash的讀寫操作。
/** @defgroup USBD_STORAGE_Private_Defines* @brief Private defines.* @{*/#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 44//0x10000
#define STORAGE_BLK_SIZ 0x400//0x200/* USER CODE BEGIN PRIVATE_DEFINES */
#define FLASH_START_ADDR 0x08005000
/* USER CODE END PRIVATE_DEFINES *//*** @brief .* @param lun: .* @param block_num: .* @param block_size: .* @retval USBD_OK if all operations are OK else USBD_FAIL*/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{/* USER CODE BEGIN 3 */*block_num = STORAGE_BLK_NBR;*block_size = STORAGE_BLK_SIZ;return (USBD_OK);/* USER CODE END 3 */
}/*** @brief .* @param lun: .* @retval USBD_OK if all operations are OK else USBD_FAIL*/
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{/* USER CODE BEGIN 6 */if (lun == 0){memcpy(buf, (uint8_t *)(FLASH_START_ADDR + blk_addr * FLASH_PAGE_SIZE), blk_len * FLASH_PAGE_SIZE);}return (USBD_OK);/* USER CODE END 6 */
}/*** @brief .* @param lun: .* @retval USBD_OK if all operations are OK else USBD_FAIL*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{/* USER CODE BEGIN 7 */if (lun == 0){FLASH_EraseInitTypeDef f;uint32_t err = 0;uint16_t i;/* Flash解鎖 */HAL_FLASH_Unlock();f.TypeErase = FLASH_TYPEERASE_PAGES;f.PageAddress = FLASH_START_ADDR + blk_addr * FLASH_PAGE_SIZE;f.NbPages = blk_len;f.Banks = FLASH_BANK_1;/* Flash擦除 */HAL_FLASHEx_Erase(&f, &err);for (i = 0; i < blk_len * FLASH_PAGE_SIZE; i += 4){/* Flash寫入 */HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_START_ADDR + blk_addr * FLASH_PAGE_SIZE + i, *(uint32_t *)(&buf[i]));}/* Flash鎖 */HAL_FLASH_Lock();}return (USBD_OK);/* USER CODE END 7 */
}
- 效果演示
五、注意事項
1、如果是自己畫的板子,注意D+口(DP)需要上拉個1.5k的電阻到3.3V。
六、相關鏈接
對于剛入門的小伙伴可以先看下STM32CubeMX的基礎使用及Keil的基礎使用。
【工具使用】STM32CubeMX-基礎使用篇
【工具使用】Keil5軟件使用-基礎使用篇
【工具使用】STM32CubeMX-片內Flash讀寫操作