一、STM32F070 USB基礎知識瞭解:
STM32F070 USB採用USB 2.0規範,時鐘頻率爲48MHZ,有一個專用的USB數據存儲區,大小爲1024字節;支持16個單向傳輸端點、8個雙向傳輸端點
USB外設模塊構成圖:
USB物理接口模塊:
USB_DM、USB_DP —— 數據正、負信號
Analog Transceiver —— 模擬收發器
Embedded pull-up resister —— 可控嵌入負載電阻
Battery Charging Detection(BCD) —— 電池充電檢測
USB_NOE —— 允許輸出信號,可用於驅動LED或提供通信信息
Serial Interface Engine(SIE)串行接口引擎:
這個模塊主要用於同步模式識別、CRC/PID的生成和檢驗、SOF/reset信號的生成、產生中斷信號等
Timer定時器模塊:
生成起始幀的鎖定時鐘脈衝以及檢測阻塞
USB連接到到APB總線的APB接口模塊構成有:Packet Memory、Arbiter(仲裁器,解決衝突訪問APB的問題)、Register Mapper(寄存器映射器)、APB封裝器(將USB外設映射到APB的地址空間)、中斷映射
二、STM32Cube USB中間件文件瞭解:
在STM32CubeMX中選擇USB中間件,點擊生成代碼就會自動加載USB的庫文件,查看STM32_USB_Device_Library文件夾可見,USB庫文件分爲兩類:一類是Class即設備類文件;一類是Core即內核文件。內核文件和設備類文件分別如下兩圖所示:
usbd_core.c /h —— 處理USB通信和狀態機的函數
usbd_ctlreq.c/h —— 處理USB事務結果
usbd_conf_template.c/h —— 底層接口文件的模板文件,用戶對其進行修改包含在應用文件中
usbd_ioreq.c/h —— 包含了USB規範列出的請求實現
三、使用STM32Cube MX配置USB
配置RCC時鐘,激活HSE時鐘源,作爲USB時鐘的輸入,選擇USB類爲HID設備類
Configuration頁面進行USB的相關設置、描述符設置,這裏配置USB爲用戶自定義的HID設備,生成的MDK代碼文件如下所示,建議先用工具生成報告描述符再根據它的長度進行配置
分析描述符
首先是USB設備標準描述符,Cube MX 已經根據配置自動生成了
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
0x00, /*bcdUSB */
0x02,
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
接下來是修改HID報告描述符,STM32HAL爲用戶提供了一個USB設備HID接口類的文件,即usbd_custom_hid_if.c/h,以便用戶自行配置HID報告描述符,要修改的數組是CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE],建議使用 HID descriptor tool工具生成報告符。這裏要注意的是報告描述符大小USBD_CUSTOM_HID_REPORT_DESC_SIZE,一定要與實際生成的報告描述符大小(使用HID descriptor tool可查看)相對應,否則會導致HID設備配置失敗。
HID_Usage()等數值我在usbd_custom_hid_if.h中有定義
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
/* USER CODE BEGIN 0 */
HID_UsagePageVendor(0xa0),
HID_Usage(0xa5),
HID_Collection(0x01),
HID_Usage(0xa6),
/* input */
HID_Usage(0xa7),
HID_LogicalMin(0x00),
HID_LogicalMax(0xFF),
HID_ReportSize(8),
HID_ReportCount(64),
HID_Input(HID_Data | HID_Variable | HID_Absolute),
/* output */
HID_Usage(0xa9),
HID_LogicalMin(0x00),
HID_LogicalMax(0xff),
HID_ReportSize(8),
HID_ReportCount(64),
HID_Output(HID_Data | HID_Variable | HID_Absolute),
/* USER CODE END 0 */
0xC0 /* END_COLLECTION */
};
到這裏爲止,下載程序後PC機就可以識別出HID設備了
發送數據:
使用USBD_CUSTOM_HID_SendReport,這個函數在usbd_customhid.c中定義,在while循環中調用這個函數
uint8_t USBD_CUSTOM_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)pdev->pClassData;
if (pdev->dev_state == USBD_STATE_CONFIGURED )
{
if(hhid->state == CUSTOM_HID_IDLE)
{
hhid->state = CUSTOM_HID_BUSY;
USBD_LL_Transmit (pdev,
CUSTOM_HID_EPIN_ADDR,
report,
len);
}
}
return USBD_OK;
}
/* USER CODE BEGIN WHILE */
while (1)
{
USB_Status = USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,InReport,64);
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER C
關於端點最大傳輸包大小和HID報告描述符中的ReportCount,在usbd_customhid.c中有如下定義
#define CUSTOM_HID_EPIN_ADDR 0x81
#define CUSTOM_HID_EPIN_SIZE 0x02
#define CUSTOM_HID_EPOUT_ADDR 0x01
#define CUSTOM_HID_EPOUT_SIZE 0x02
這裏定義中斷傳輸端點的最大傳輸包大小爲2,但其實實際傳輸時仍然可以傳輸64個數據,原因是在HID報告描述符中有對Input和Output的傳輸數據包大小做定義,實際傳輸大小應該以這個爲標準,即每次傳輸最大數據量爲64個數據,每個數據8位。不過建議將CUSTOM_HID_EPIN_SIZE/CUSTOM_HID_EPOUT_SIZE修改成和報告符中定義的大小一致。
HID_ReportSize(8),
HID_ReportCount(64),
接收數據:
接收數據則對CUSTOM_HID_OutEvent_FS函數進行修改,以便處理接收到的數據(未完)