主機環(huán)境:Windows 7 SP1
開發(fā)環(huán)境:MDK5.14
目標板:STM32F103C8T6
開發(fā)庫:STM32F1Cube庫和STM32_USB_Device_Library
現(xiàn)在我們來分析VCP例程的最后一個文件USB設備類的usbd_cdc文件,該文件跟CDC類緊密相關,看下其頭文件的一些定義:
/** @defgroup usbd_cdc_Exported_Defines
* @{
*/
#define CDC_IN_EP 0x81 /* EP1 for data IN */
#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
#define CDC_DATA_HS_MAX_PACKET_SIZE 512 /* Endpoint IN & OUT Packet size */
#define CDC_DATA_FS_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */
#define CDC_CMD_PACKET_SIZE 8 /* Control Endpoint Packet size */
#define USB_CDC_CONFIG_DESC_SIZ 67
#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
這些宏定義指明了CDC類使用的端點,以及最大包大小,對于STM32F103C8T6來說最大包大小是是64字節(jié),其中命令控制端點最大包大小為8字節(jié)。在頭文件中還有一個CDC類的結構聲明,如下:
typedef struct
{
uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;
__IO uint32_t TxState;
__IO uint32_t RxState;
}
USBD_CDC_HandleTypeDef;
該句柄管理著CDC類的數(shù)據(jù)信息,接著我們來查看usbd_cdc.c文件,該文件需要配合CDC1.20以及PSTN1.20協(xié)議文檔來查看,在usbd_cdc,c中有我們CDC類的具體實現(xiàn),如下:
/* CDC interface class callbacks structure */
USBD_ClassTypeDef USBD_CDC =
{
USBD_CDC_Init,
USBD_CDC_DeInit,
USBD_CDC_Setup,
NULL, /* EP0_TxSent, */
USBD_CDC_EP0_RxReady,
USBD_CDC_DataIn,
USBD_CDC_DataOut,
NULL,
NULL,
NULL,
USBD_CDC_GetHSCfgDesc,
USBD_CDC_GetFSCfgDesc,
USBD_CDC_GetOtherSpeedCfgDesc,
USBD_CDC_GetDeviceQualifierDescriptor,
};
其中EP0_TxSent、SOF、IsoINIncomplete、ISOOUTIncomplete為空。該文件中函數(shù)比較多,先從簡單的分析,首先看下注冊接口的函數(shù),如下:
/**
* @brief USBD_CDC_RegisterInterface
* @param pdev: device instance
* @param fops: CD Interface callback
* @retval status
*/
uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev,
USBD_CDC_ItfTypeDef *fops)
{
uint8_t ret = USBD_FAIL;
if(fops != NULL)
{
pdev->pUserData= fops;
ret = USBD_OK;
}
return ret;
}
注冊接口很簡單,即把CDC接口指針鏈接到USB句柄中的UserData即可。接著是在CDC接口文件中提到的兩個設置緩存區(qū)的函數(shù),如下:
/**
* @brief USBD_CDC_SetTxBuffer
* @param pdev: device instance
* @param pbuff: Tx Buffer
* @retval status
*/
uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev,
uint8_t *pbuff,
uint16_t length)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
hcdc->TxBuffer = pbuff;
hcdc->TxLength = length;
return USBD_OK;
}
/**
* @brief USBD_CDC_SetRxBuffer
* @param pdev: device instance
* @param pbuff: Rx Buffer
* @retval status
*/
uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev,
uint8_t *pbuff)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
hcdc->RxBuffer = pbuff;
return USBD_OK;
}
給CDC句柄的相應字段賦值即可。再有兩個是CDC接口文件中提到的數(shù)據(jù)發(fā)送和接收函數(shù),如下:
/**
* @brief USBD_CDC_DataOut
* Data received on non-control Out endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
if(pdev->pClassData != NULL)
{
if(hcdc->TxState == 0)
{
/* Tx Transfer in progress */
hcdc->TxState = 1;
/* Transmit next packet */
USBD_LL_Transmit(pdev,
CDC_IN_EP,
hcdc->TxBuffer,
hcdc->TxLength);
return USBD_OK;
}
else
{
return USBD_BUSY;
}
}
else
{
return USBD_FAIL;
}
}
/**
* @brief USBD_CDC_ReceivePacket
* prepare OUT Endpoint for reception
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
/* Suspend or Resume USB Out process */
if(pdev->pClassData != NULL)
{
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev,
CDC_OUT_EP,
hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);
}
else
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev,
CDC_OUT_EP,
hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
}
return USBD_OK;
}
else
{
return USBD_FAIL;
}
}
發(fā)送函數(shù)很簡單,檢測到發(fā)送狀態(tài)處于空閑時則執(zhí)行發(fā)送操作,并設置發(fā)送狀態(tài)有BUSY,這里這里使用的發(fā)送端點是0x81,不是端點0。而且數(shù)據(jù)的發(fā)送和發(fā)送數(shù)據(jù)的緩存區(qū)設置二者是成對使用的。接收函數(shù)也比較簡單只是區(qū)分了高速和全速模式下的最大包大小不同,這里使用的端點同樣不是端點0而是端點0x001。CDC類接口使用的函數(shù)補充完畢,現(xiàn)在來看CDC類各個函數(shù),依然從簡單的開始幾個描述符的獲取,這個有四個描述符的獲取,如下:
/**
* @brief USBD_CDC_GetFSCfgDesc
* Return configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_CDC_CfgFSDesc);
return USBD_CDC_CfgFSDesc;
}
/**
* @brief USBD_CDC_GetHSCfgDesc
* Return configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_CDC_CfgHSDesc);
return USBD_CDC_CfgHSDesc;
}
/**
* @brief USBD_CDC_GetCfgDesc
* Return configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_CDC_OtherSpeedCfgDesc);
return USBD_CDC_OtherSpeedCfgDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
上一篇:直接通過寄存器地址操作控制LED燈(STM32_01)
下一篇:STM32 USB學習筆記8
推薦閱讀最新更新時間:2025-06-17 00:25





設計資源 培訓 開發(fā)板 精華推薦
- Microchip 升級數(shù)字信號控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領先的新器件
- 意法半導體STM32MP23x:突破成本限制的工業(yè)AI應用核心
- 意法半導體推出用于匹配遠距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設置字重-ESP32篇
- 使用樹莓派進行 ESP32 Jtag 調試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- ChaN老師的耳機放大器設計
- AL9901EV2,基于帶有集成 MOSFET 的 AL9901 通用高壓 LED 驅動器的評估板
- 使用 Analog Devices 的 LT1085CM-3.6 的參考設計
- 基于STM32的數(shù)字示波器設計(原理圖、源程序等)
- OP295GPZ低功耗RTD放大器的典型應用
- 使用具有 PowerPath 和 2A 輸入限制的 LTC4162IUFD-L42M 9V 至 35V、2 節(jié)、3.2A 充電器的典型應用
- LT6654AMPS6-3.3、16 位 ADC 電壓基準的典型應用
- LTC4367CMS8 用于滯后調節(jié)的過壓電源控制器的典型應用
- XR75100 40V同步降壓COT控制器典型應用
- ZVS感應加熱
- 正向 DCDC 巧改負壓?GM2406/GM24061反向操作指南!
- 『新品發(fā)布』共模半導體重磅發(fā)布40V、4A/6A低EMI車規(guī)級同步降壓穩(wěn)壓器 GM2406
- Bourns 推出專為光伏應用設計 POWrFuse? 大功率電力保險絲系列,具備 1500 VDC 額定值
- 納芯微推出車規(guī)級自動雙向型電平轉換器NCAS0104和NCAB0104
- 瑞薩電子推出全新GaN FET,增強高密度功率轉換能力, 適用于AI數(shù)據(jù)中心、工業(yè)及電源系統(tǒng)應用
- 芯對話 | 芯佰微CBM8605/CBM8606/CBM8608運算放大器 精密信號鏈的核心解決方案
- 物聯(lián)網(wǎng)技術促進能量收集創(chuàng)新應用落地
- Proximus Global旗下公司BICS與Epic Malta合作,為2G/3G網(wǎng)絡退役后保障旅行者漫游連接
- 大聯(lián)大世平集團推出以NXP產(chǎn)品為核心的HVBMS BJB方案
- 適用于高速應用的先進全局快門圖像傳感器