STM32 USB音频麦克风实现

  • 调试工具
  • 资料书籍
  • 音频描述符中的简称及分类
  • 接口描述符
  • STM32配置
    • 实现部分
    • 如何使用
    • 测试正弦音频
  • 测试工程
  • USB缓冲区设置
  • H7的HAL库USB问题
  • 参考引用

最近项目进入收尾阶段,USB Microphone 部分代码不是我所实现,接口较为松散,所以决定优化这部分代码,啃一啃USB部分知识点,一两天肯定不能完全了解清晰,毕竟万能USB,其协议必然是复杂的,所以就先从音频麦克风的实现开始。

其实是币圈大跌,努力搬砖中…

调试工具

usbtreeview(一款方便查看USB设备相关信息的免安装绿色工具)
Audacity (音频频谱查看工具,可查看麦克风设备列表,进行音频录制)

资料书籍

<<圈圈教你玩USB 第二版>>

音频描述符中的简称及分类

详细:https://blog.csdn.net/qq_40088639/article/details/122720314

  • AC:Audio Control
  • AS:Audio Stream

拓扑图如下:

控制接口下,默认为端点0

接口描述符

查看位置:usbd_xxx.h,xxx代表某个功能如:audio
在这个文件中可以找到这个USB功能类的相关描述符定义

  • Terminal 以设备为视角看待

    • Terminal 的输入输出成对出现
  • endpoint 以HOST为视角看待

下图为一个speeaker即扬声器 USB拓扑
endpoint 以HOST为视角看待,即主机的输出口 endpoint1 的音频数据流,转入了设备端的输入口Terminal IN

那么麦克风的配置

usbd_audio.c

iConfiguration iTerminal iInterfaceiChannelNames其数值,都是在说明本描述符的字符串说明符,所在索引号,若为0则没有字符串说明(没有文字说明)

  • wTerminalType

    • 音频流:0x0101
    • 麦克风:0x0201
    • 电话线:0x0501
    • 手持电话筒的输入麦克风:0x0401

如果麦克风数据需要通过USB上传至PC那么:

麦克风数据 --》(USB设备)MCU -》(USB主机)PC

麦克风数据 --》 terminal IN -》terminal OUT -》 Endpoint IN

STM32配置

打开USB设备功能 FS( Full Speed 全速设备)

配置USB Audio库,配置音频的采样率

PID修改参考:http://www.linux-usb.org/usb.ids
搜索0483找到STMicroelectronics
一般CubeMX会自动打开USB的全局中断,生成代码后,自己最好确认一下(位于usbd_config.c)。

以下usbd_audio.c和对应头文件可直接替换,自动生成的。
修改usbd_audio.c文件

/********************************************************************************* @file    usbd_audio.c* @author  MCD Application Team* @brief   This file provides the Audio core functions.** @verbatim**          ===================================================================*                                AUDIO Class  Description*          ===================================================================*           This driver manages the Audio Class 1.0 following the "USB Device Class Definition for*           Audio Devices V1.0 Mar 18, 98".*           This driver implements the following aspects of the specification:*             - Device descriptor management*             - Configuration descriptor management*             - Standard AC Interface Descriptor management*             - 1 Audio Streaming Interface (with single channel, PCM, Stereo mode)*             - 1 Audio Streaming Endpoint*             - 1 Audio Terminal Input (1 channel)*             - Audio Class-Specific AC Interfaces*             - Audio Class-Specific AS Interfaces*             - AudioControl Requests: only SET_CUR and GET_CUR requests are supported (for Mute)*             - Audio Feature Unit (limited to Mute control)*             - Audio Synchronization type: Asynchronous*             - Single fixed audio sampling rate (configurable in usbd_conf.h file)*          The current audio class version supports the following audio features:*             - Pulse Coded Modulation (PCM) format*             - sampling rate: 48KHz.*             - Bit resolution: 16*             - Number of channels: 2*             - No volume control*             - Mute/Unmute capability*             - Asynchronous Endpoints** @note     In HS mode and when the DMA is used, all variables and data structures*           dealing with the DMA during the transaction process should be 32-bit aligned.***  @endverbatim******************************************************************************** @attention** <h2><center>&copy; Copyright (c) 2015 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                      www.st.com/SLA0044********************************************************************************//* BSPDependencies
- "stm32xxxxx_{eval}{discovery}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
- "stm32xxxxx_{eval}{discovery}_audio.c"
EndBSPDependencies *//* Includes ------------------------------------------------------------------*/
#include "usbd_audio.h"
#include "usbd_ctlreq.h"/** @addtogroup STM32_USB_DEVICE_LIBRARY* @{*//** @defgroup USBD_AUDIO* @brief usbd core module* @{*//** @defgroup USBD_AUDIO_Private_TypesDefinitions* @{*/
/*** @}*//** @defgroup USBD_AUDIO_Private_Defines* @{*/
/*** @}*//** @defgroup USBD_AUDIO_Private_Macros* @{*/
#define AUDIO_SAMPLE_FREQ(frq)         (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))#define AUDIO_PACKET_SZE(frq)          (uint8_t)(((frq * 2U * 2U)/1000U) & 0xFFU), \(uint8_t)((((frq * 2U * 2U)/1000U) >> 8) & 0xFFU)/*** @}*//** @defgroup USBD_AUDIO_Private_FunctionPrototypes* @{*/
static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,USBD_SetupReqTypedef *req);static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length);
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length);
static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev);static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);/*** @}*//** @defgroup USBD_AUDIO_Private_Variables* @{*/USBD_ClassTypeDef USBD_AUDIO =
{USBD_AUDIO_Init,USBD_AUDIO_DeInit,USBD_AUDIO_Setup,USBD_AUDIO_EP0_TxReady,USBD_AUDIO_EP0_RxReady,USBD_AUDIO_DataIn,USBD_AUDIO_DataOut,USBD_AUDIO_SOF,USBD_AUDIO_IsoINIncomplete,USBD_AUDIO_IsoOutIncomplete,USBD_AUDIO_GetCfgDesc,USBD_AUDIO_GetCfgDesc,USBD_AUDIO_GetCfgDesc,USBD_AUDIO_GetDeviceQualifierDesc,
};/* USB AUDIO device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_CfgDesc[USB_AUDIO_CONFIG_DESC_SIZ] __ALIGN_END =
{/* Configuration 1 */0x09,                                 /* bLength */USB_DESC_TYPE_CONFIGURATION,          /* bDescriptorType */LOBYTE(USB_AUDIO_CONFIG_DESC_SIZ),    /* wTotalLength  109 bytes*/HIBYTE(USB_AUDIO_CONFIG_DESC_SIZ),0x02,                                 /* bNumInterfaces */0x01,                                 /* bConfigurationValue */0x00,                                 /* iConfiguration */
#if (USBD_SELF_POWERED == 1U)0xC0,                                 /* bmAttributes: Bus Powered according to user configuration */
#else0x80,                                 /* bmAttributes: Bus Powered according to user configuration */
#endifUSBD_MAX_POWER,                       /* bMaxPower = 100 mA *//* 09 byte*//* USB Microphone Standard interface descriptor */AUDIO_INTERFACE_DESC_SIZE,            /* bLength */USB_DESC_TYPE_INTERFACE,              /* bDescriptorType */0x00,                                 /* bInterfaceNumber */0x00,                                 /* bAlternateSetting */0x00,                                 /* bNumEndpoints */USB_DEVICE_CLASS_AUDIO,               /* bInterfaceClass */AUDIO_SUBCLASS_AUDIOCONTROL,          /* bInterfaceSubClass */AUDIO_PROTOCOL_UNDEFINED,             /* bInterfaceProtocol */0x00,                                 /* iInterface *//* 09 byte*//* USB Microphone Class-specific AC Interface Descriptor */AUDIO_INTERFACE_DESC_SIZE,            /* bLength */AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */AUDIO_CONTROL_HEADER,                 /* bDescriptorSubtype */0x00,          /* 1.00 */             /* bcdADC */0x01,0x27,                                 /* wTotalLength = 39*/0x00,0x01,                                 /* bInCollection */0x01,                                 /* baInterfaceNr *//* 09 byte*//* USB Microphone Input Terminal Descriptor */AUDIO_INPUT_TERMINAL_DESC_SIZE,       /* bLength */AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */AUDIO_CONTROL_INPUT_TERMINAL,         /* bDescriptorSubtype */AUDIO_PORT_INPUT_TERMINAL_ID_1,       /* bTerminalID */ AUDIO_PORT_MICRO_PHONE_TERMINAL_L,    /* wTerminalType AUDIO_TERMINAL_USB_Microphone   0x0201 */AUDIO_PORT_MICRO_PHONE_TERMINAL_H,0x00,                                 /* bAssocTerminal */AUDIO_PORT_CHANNEL_NUMS,              /* bNrChannels */AUDIO_PORT_CHANNEL_CONFIG_L,          /* wChannelConfig 0x0000  Mono or L+R or L or R*/AUDIO_PORT_CHANNEL_CONFIG_H,0x00,                                 /* iChannelNames */0x00,                                 /* iTerminal *//* 12 byte*//* USB Microphone Audio Feature Unit Descriptor */0x09,                                 /* bLength */AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */AUDIO_CONTROL_FEATURE_UNIT,           /* bDescriptorSubtype */AUDIO_PORT_INPUT_CTL_ID_2,            /* bUnitID */AUDIO_PORT_INPUT_TERMINAL_ID_1,       /* bSourceID */0x01,                                 /* bControlSize */AUDIO_CONTROL_MUTE,                   /* bmaControls(0) */0,                                    /* bmaControls(1) */0x00,                                 /* iTerminal *//* 09 byte*//*USB Microphone Output Terminal Descriptor */0x09,      /* bLength */AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */AUDIO_CONTROL_OUTPUT_TERMINAL,        /* bDescriptorSubtype */AUDIO_PORT_OUTPUT_TERMINAL_ID_3,      /* bTerminalID */AUDIO_PORT_STREAM_TERMINAL_TYPE_L,    /* wTerminalType  音频流0x0101*/AUDIO_PORT_STREAM_TERMINAL_TYPE_H,0x00,                                 /* bAssocTerminal */AUDIO_PORT_INPUT_CTL_ID_2,            /* bSourceID */0x00,                                 /* iTerminal *//* 09 byte*//* USB Microphone Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth *//* Interface 1, Alternate Setting 0                                             */AUDIO_INTERFACE_DESC_SIZE,            /* bLength */USB_DESC_TYPE_INTERFACE,              /* bDescriptorType */0x01,                                 /* bInterfaceNumber */0x00,                                 /* bAlternateSetting */0x00,                                 /* bNumEndpoints */USB_DEVICE_CLASS_AUDIO,               /* bInterfaceClass */AUDIO_SUBCLASS_AUDIOSTREAMING,        /* bInterfaceSubClass */AUDIO_PROTOCOL_UNDEFINED,             /* bInterfaceProtocol */0x00,                                 /* iInterface *//* 09 byte*//* USB Microphone Standard AS Interface Descriptor - Audio Streaming Operational *//* Interface 1, Alternate Setting 1                                           */AUDIO_INTERFACE_DESC_SIZE,            /* bLength */USB_DESC_TYPE_INTERFACE,              /* bDescriptorType */0x01,                                 /* bInterfaceNumber */0x01,                                 /* bAlternateSetting */0x01,                                 /* bNumEndpoints */USB_DEVICE_CLASS_AUDIO,               /* bInterfaceClass */AUDIO_SUBCLASS_AUDIOSTREAMING,        /* bInterfaceSubClass */AUDIO_PROTOCOL_UNDEFINED,             /* bInterfaceProtocol */0x00,                                 /* iInterface *//* 09 byte*//* USB Microphone Audio Streaming Interface Descriptor */AUDIO_STREAMING_INTERFACE_DESC_SIZE,  /* bLength */AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */AUDIO_STREAMING_GENERAL,              /* bDescriptorSubtype */AUDIO_PORT_OUTPUT_TERMINAL_ID_3,      /* bTerminalLink */0x01,                                 /* bDelay */0x01,                                 /* wFormatTag AUDIO_FORMAT_PCM  0x0001 */0x00,/* 07 byte*//* USB Microphone Audio Type III Format Interface Descriptor */0x0B,                                 /* bLength */AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */AUDIO_STREAMING_FORMAT_TYPE,          /* bDescriptorSubtype */AUDIO_FORMAT_TYPE_I,                  /* bFormatType */AUDIO_PORT_CHANNEL_NUMS,              /* bNrChannels */0x02,                                 /* bSubFrameSize :  2 Bytes per frame (16bits) */16,                                   /* bBitResolution (16-bits per sample) */0x01,                                 /* bSamFreqType only one frequency supported */AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ),   /* Audio sampling frequency coded on 3 bytes *//* 11 byte*//* Endpoint 1 - Standard Descriptor */AUDIO_STANDARD_ENDPOINT_DESC_SIZE,    /* bLength */USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType */AUDIO_PORT_IN_EP_DIR_ID,              /* bEndpointAddress 1 in endpoint */USBD_EP_TYPE_ISOC,                    /* bmAttributes */AUDIO_PORT_PACKET_SZE(USBD_AUDIO_FREQ),/* wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */AUDIO_PORT_FS_BINTERVAL,              /* bInterval */0x00,                                 /* bRefresh */0x00,                                 /* bSynchAddress *//* 09 byte*//* Endpoint - Audio Streaming Descriptor*/AUDIO_STREAMING_ENDPOINT_DESC_SIZE,   /* bLength */AUDIO_ENDPOINT_DESCRIPTOR_TYPE,       /* bDescriptorType */AUDIO_ENDPOINT_GENERAL,               /* bDescriptor */0x00,                                 /* bmAttributes */0x00,                                 /* bLockDelayUnits */0x00,                                 /* wLockDelay */0x00,/* 07 byte*/
} ;/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{USB_LEN_DEV_QUALIFIER_DESC,USB_DESC_TYPE_DEVICE_QUALIFIER,0x00,0x02,0x00,0x00,0x00,0x40,0x01,0x00,
};/*** @}*//** @defgroup USBD_AUDIO_Private_Functions* @{*//*** @brief  USBD_AUDIO_Init*         Initialize the AUDIO interface* @param  pdev: device instance* @param  cfgidx: Configuration index* @retval status*/
static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{return USB_Audio_Port_EP_IN_Init(pdev, cfgidx);
}/*** @brief  USBD_AUDIO_Init*         DeInitialize the AUDIO layer* @param  pdev: device instance* @param  cfgidx: Configuration index* @retval status*/
static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{UNUSED(cfgidx);/* Open EP OUT */(void)USBD_LL_CloseEP(pdev, AUDIO_OUT_EP);pdev->ep_out[AUDIO_OUT_EP & 0xFU].is_used = 0U;pdev->ep_out[AUDIO_OUT_EP & 0xFU].bInterval = 0U;/* DeInit  physical Interface components */if (pdev->pClassData != NULL){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->DeInit(0U);(void)USBD_free(pdev->pClassData);pdev->pClassData = NULL;}return (uint8_t)USBD_OK;
}/*** @brief  USBD_AUDIO_Setup*         Handle the AUDIO specific requests* @param  pdev: instance* @param  req: usb requests* @retval status*/
static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,USBD_SetupReqTypedef *req)
{USBD_AUDIO_HandleTypeDef *haudio;uint16_t len;uint8_t *pbuf;uint16_t status_info = 0U;USBD_StatusTypeDef ret = USBD_OK;haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;if (haudio == NULL){return (uint8_t)USBD_FAIL;}switch (req->bmRequest & USB_REQ_TYPE_MASK){case USB_REQ_TYPE_CLASS:switch (req->bRequest){case AUDIO_REQ_GET_CUR:AUDIO_REQ_GetCurrent(pdev, req);break;case AUDIO_REQ_SET_CUR:AUDIO_REQ_SetCurrent(pdev, req);break;default:USBD_CtlError(pdev, req);ret = USBD_FAIL;break;}break;case USB_REQ_TYPE_STANDARD:switch (req->bRequest){case USB_REQ_GET_STATUS:if (pdev->dev_state == USBD_STATE_CONFIGURED){(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);}else{USBD_CtlError(pdev, req);ret = USBD_FAIL;}break;case USB_REQ_GET_DESCRIPTOR:if ((req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE){pbuf = USBD_AUDIO_CfgDesc + 18;len = MIN(USB_AUDIO_DESC_SIZ, req->wLength);(void)USBD_CtlSendData(pdev, pbuf, len);}break;case USB_REQ_GET_INTERFACE:if (pdev->dev_state == USBD_STATE_CONFIGURED){(void)USBD_CtlSendData(pdev, (uint8_t *)&haudio->alt_setting, 1U);}else{USBD_CtlError(pdev, req);ret = USBD_FAIL;}break;case USB_REQ_SET_INTERFACE:if (pdev->dev_state == USBD_STATE_CONFIGURED){if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES){haudio->alt_setting = (uint8_t)(req->wValue);}else{/* Call the error management function (command will be NAKed */USBD_CtlError(pdev, req);ret = USBD_FAIL;}}else{USBD_CtlError(pdev, req);ret = USBD_FAIL;}break;case USB_REQ_CLEAR_FEATURE:break;default:USBD_CtlError(pdev, req);ret = USBD_FAIL;break;}break;default:USBD_CtlError(pdev, req);ret = USBD_FAIL;break;}return (uint8_t)ret;
}/*** @brief  USBD_AUDIO_GetCfgDesc*         return configuration descriptor* @param  speed : current device speed* @param  length : pointer data length* @retval pointer to descriptor buffer*/
static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length)
{*length = (uint16_t)sizeof(USBD_AUDIO_CfgDesc);return USBD_AUDIO_CfgDesc;
}/*** @brief  USBD_AUDIO_DataIn*         handle data IN Stage* @param  pdev: device instance* @param  epnum: endpoint index* @retval status*/
static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{return USB_Audio_Port_DataIn(pdev, epnum);
}/*** @brief  USBD_AUDIO_EP0_RxReady*         handle EP0 Rx Ready event* @param  pdev: device instance* @retval status*/
static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev)
{USBD_AUDIO_HandleTypeDef *haudio;haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;if (haudio == NULL){return (uint8_t)USBD_FAIL;}if (haudio->control.cmd == AUDIO_REQ_SET_CUR){/* In this driver, to simplify code, only SET_CUR request is managed */if (haudio->control.unit == AUDIO_OUT_STREAMING_CTRL){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->MuteCtl(haudio->control.data[0]);haudio->control.cmd = 0U;haudio->control.len = 0U;}}return (uint8_t)USBD_OK;
}
/*** @brief  USBD_AUDIO_EP0_TxReady*         handle EP0 TRx Ready event* @param  pdev: device instance* @retval status*/
static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev)
{UNUSED(pdev);/* Only OUT control data are processed */return (uint8_t)USBD_OK;
}
/*** @brief  USBD_AUDIO_SOF*         handle SOF event* @param  pdev: device instance* @retval status*/
static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev)
{UNUSED(pdev);return (uint8_t)USBD_OK;
}/*** @brief  USBD_AUDIO_SOF*         handle SOF event* @param  pdev: device instance* @retval status*/
void USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset)
{USBD_AUDIO_HandleTypeDef *haudio;uint32_t BufferSize = AUDIO_TOTAL_BUF_SIZE / 2U;if (pdev->pClassData == NULL){return;}haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;haudio->offset = offset;if (haudio->rd_enable == 1U){haudio->rd_ptr += (uint16_t)BufferSize;if (haudio->rd_ptr == AUDIO_TOTAL_BUF_SIZE){/* roll back */haudio->rd_ptr = 0U;}}if (haudio->rd_ptr > haudio->wr_ptr){if ((haudio->rd_ptr - haudio->wr_ptr) < AUDIO_OUT_PACKET){BufferSize += 4U;}else{if ((haudio->rd_ptr - haudio->wr_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET)){BufferSize -= 4U;}}}else{if ((haudio->wr_ptr - haudio->rd_ptr) < AUDIO_OUT_PACKET){BufferSize -= 4U;}else{if ((haudio->wr_ptr - haudio->rd_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET)){BufferSize += 4U;}}}if (haudio->offset == AUDIO_OFFSET_FULL){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->AudioCmd(&haudio->buffer[0],BufferSize, AUDIO_CMD_PLAY);haudio->offset = AUDIO_OFFSET_NONE;}
}/*** @brief  USBD_AUDIO_IsoINIncomplete*         handle data ISO IN Incomplete event* @param  pdev: device instance* @param  epnum: endpoint index* @retval status*/
static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{UNUSED(pdev);UNUSED(epnum);return (uint8_t)USBD_OK;
}
/*** @brief  USBD_AUDIO_IsoOutIncomplete*         handle data ISO OUT Incomplete event* @param  pdev: device instance* @param  epnum: endpoint index* @retval status*/
static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{UNUSED(pdev);UNUSED(epnum);return (uint8_t)USBD_OK;
}
/*** @brief  USBD_AUDIO_DataOut*         handle data OUT Stage* @param  pdev: device instance* @param  epnum: endpoint index* @retval status*/
static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{uint16_t PacketSize;USBD_AUDIO_HandleTypeDef *haudio;haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;if (haudio == NULL){return (uint8_t)USBD_FAIL;}if (epnum == AUDIO_OUT_EP){/* Get received data packet length */PacketSize = (uint16_t)USBD_LL_GetRxDataSize(pdev, epnum);/* Packet received Callback */((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->PeriodicTC(&haudio->buffer[haudio->wr_ptr],PacketSize, AUDIO_OUT_TC);/* Increment the Buffer pointer or roll it back when all buffers are full */haudio->wr_ptr += PacketSize;if (haudio->wr_ptr == AUDIO_TOTAL_BUF_SIZE){/* All buffers are full: roll back */haudio->wr_ptr = 0U;if (haudio->offset == AUDIO_OFFSET_UNKNOWN){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->AudioCmd(&haudio->buffer[0],AUDIO_TOTAL_BUF_SIZE / 2U,AUDIO_CMD_START);haudio->offset = AUDIO_OFFSET_NONE;}}if (haudio->rd_enable == 0U){if (haudio->wr_ptr == (AUDIO_TOTAL_BUF_SIZE / 2U)){haudio->rd_enable = 1U;}}/* Prepare Out endpoint to receive next audio packet */(void)USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP,&haudio->buffer[haudio->wr_ptr],AUDIO_OUT_PACKET);}return (uint8_t)USBD_OK;
}/*** @brief  AUDIO_Req_GetCurrent*         Handles the GET_CUR Audio control request.* @param  pdev: instance* @param  req: setup class request* @retval status*/
static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{USBD_AUDIO_HandleTypeDef *haudio;haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;if (haudio == NULL){return;}(void)USBD_memset(haudio->control.data, 0, 64U);/* Send the current mute state */(void)USBD_CtlSendData(pdev, haudio->control.data, req->wLength);
}/*** @brief  AUDIO_Req_SetCurrent*         Handles the SET_CUR Audio control request.* @param  pdev: instance* @param  req: setup class request* @retval status*/
static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{USBD_AUDIO_HandleTypeDef *haudio;haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;if (haudio == NULL){return;}if (req->wLength != 0U){/* Prepare the reception of the buffer over EP0 */(void)USBD_CtlPrepareRx(pdev, haudio->control.data, req->wLength);haudio->control.cmd = AUDIO_REQ_SET_CUR;     /* Set the request value */haudio->control.len = (uint8_t)req->wLength; /* Set the request data length */haudio->control.unit = HIBYTE(req->wIndex);  /* Set the request target unit */}
}/*** @brief  DeviceQualifierDescriptor*         return Device Qualifier descriptor* @param  length : pointer data length* @retval pointer to descriptor buffer*/
static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length)
{*length = (uint16_t)sizeof(USBD_AUDIO_DeviceQualifierDesc);return USBD_AUDIO_DeviceQualifierDesc;
}/*** @brief  USBD_AUDIO_RegisterInterface* @param  fops: Audio interface callback* @retval status*/
uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,USBD_AUDIO_ItfTypeDef *fops)
{if (fops == NULL){return (uint8_t)USBD_FAIL;}pdev->pUserData = fops;return (uint8_t)USBD_OK;
}
/*** @}*//*** @}*//*** @}*//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

usbd_audio.h
其内主要修改了 缓冲区大小,包含了接口头文件

/********************************************************************************* @file    usbd_audio.h* @author  MCD Application Team* @brief   header file for the usbd_audio.c file.******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2015 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                      www.st.com/SLA0044********************************************************************************//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_AUDIO_H
#define __USB_AUDIO_H#ifdef __cplusplus
extern "C" {#endif/* Includes ------------------------------------------------------------------*/
#include  "usbd_ioreq.h"
#include "USB_Audio_Port.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY* @{*//** @defgroup USBD_AUDIO* @brief This file is the Header file for usbd_audio.c* @{*//** @defgroup USBD_AUDIO_Exported_Defines* @{*/
#ifndef USBD_AUDIO_FREQ
/* AUDIO Class Config */
#define USBD_AUDIO_FREQ                               48000U
#endif /* USBD_AUDIO_FREQ */#ifndef USBD_MAX_NUM_INTERFACES
#define USBD_MAX_NUM_INTERFACES                       1U
#endif /* USBD_AUDIO_FREQ */#ifndef AUDIO_HS_BINTERVAL
#define AUDIO_HS_BINTERVAL                            0x01U
#endif /* AUDIO_HS_BINTERVAL */#ifndef AUDIO_FS_BINTERVAL
#define AUDIO_FS_BINTERVAL                            0x01U
#endif /* AUDIO_FS_BINTERVAL */#define AUDIO_OUT_EP                                  0x01U
#define USB_AUDIO_CONFIG_DESC_SIZ                     0x6DU
#define AUDIO_INTERFACE_DESC_SIZE                     0x09U
#define USB_AUDIO_DESC_SIZ                            0x09U
#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE             0x09U
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE            0x07U#define AUDIO_DESCRIPTOR_TYPE                         0x21U
#define USB_DEVICE_CLASS_AUDIO                        0x01U
#define AUDIO_SUBCLASS_AUDIOCONTROL                   0x01U
#define AUDIO_SUBCLASS_AUDIOSTREAMING                 0x02U
#define AUDIO_PROTOCOL_UNDEFINED                      0x00U
#define AUDIO_STREAMING_GENERAL                       0x01U
#define AUDIO_STREAMING_FORMAT_TYPE                   0x02U/* Audio Descriptor Types */
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE               0x24U
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE                0x25U/* Audio Control Interface Descriptor Subtypes */
#define AUDIO_CONTROL_HEADER                          0x01U
#define AUDIO_CONTROL_INPUT_TERMINAL                  0x02U
#define AUDIO_CONTROL_OUTPUT_TERMINAL                 0x03U
#define AUDIO_CONTROL_FEATURE_UNIT                    0x06U#define AUDIO_INPUT_TERMINAL_DESC_SIZE                0x0CU
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE               0x09U
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE           0x07U#define AUDIO_CONTROL_MUTE                            0x0001U#define AUDIO_FORMAT_TYPE_I                           0x01U
#define AUDIO_FORMAT_TYPE_III                         0x03U#define AUDIO_ENDPOINT_GENERAL                        0x01U#define AUDIO_REQ_GET_CUR                             0x81U
#define AUDIO_REQ_SET_CUR                             0x01U#define AUDIO_OUT_STREAMING_CTRL                      0x02U#define AUDIO_OUT_TC                                  0x01U
#define AUDIO_IN_TC                                   0x02U#define AUDIO_OUT_PACKET                              AUDIO_PORT_OUT_SIZE
#define AUDIO_DEFAULT_VOLUME                          70U/* Number of sub-packets in the audio transfer buffer. You can modify this value but always make surethat it is an even number and higher than 3 */
#define AUDIO_OUT_PACKET_NUM                          80U
/* Total size of the audio transfer buffer */
#define AUDIO_TOTAL_BUF_SIZE                          AUDIO_PORT_BUF_SIZE/* Audio Commands enumeration */
typedef enum
{AUDIO_CMD_START = 1,AUDIO_CMD_PLAY,AUDIO_CMD_STOP,
} AUDIO_CMD_TypeDef;typedef enum
{AUDIO_OFFSET_NONE = 0,AUDIO_OFFSET_HALF,AUDIO_OFFSET_FULL,AUDIO_OFFSET_UNKNOWN,
} AUDIO_OffsetTypeDef;
/*** @}*//** @defgroup USBD_CORE_Exported_TypesDefinitions* @{*/
typedef struct
{uint8_t cmd;uint8_t data[USB_MAX_EP0_SIZE];uint8_t len;uint8_t unit;
} USBD_AUDIO_ControlTypeDef;typedef struct
{uint32_t alt_setting;uint8_t buffer[AUDIO_TOTAL_BUF_SIZE];AUDIO_OffsetTypeDef offset;uint8_t rd_enable;uint16_t rd_ptr;uint16_t wr_ptr;USBD_AUDIO_ControlTypeDef control;
} USBD_AUDIO_HandleTypeDef;typedef struct
{int8_t (*Init)(uint32_t AudioFreq, uint32_t Volume, uint32_t options);int8_t (*DeInit)(uint32_t options);int8_t (*AudioCmd)(uint8_t *pbuf, uint32_t size, uint8_t cmd);int8_t (*VolumeCtl)(uint8_t vol);int8_t (*MuteCtl)(uint8_t cmd);int8_t (*PeriodicTC)(uint8_t *pbuf, uint32_t size, uint8_t cmd);int8_t (*GetState)(void);
} USBD_AUDIO_ItfTypeDef;
/*** @}*//** @defgroup USBD_CORE_Exported_Macros* @{*//*** @}*//** @defgroup USBD_CORE_Exported_Variables* @{*/extern USBD_ClassTypeDef USBD_AUDIO;
#define USBD_AUDIO_CLASS &USBD_AUDIO
/*** @}*//** @defgroup USB_CORE_Exported_Functions* @{*/
uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,USBD_AUDIO_ItfTypeDef *fops);void USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset);
/*** @}*/#ifdef __cplusplus
}
#endif#endif  /* __USB_AUDIO_H */
/*** @}*//*** @}*//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

实现部分

其内需要环形缓冲区,源码获取:https://blog.csdn.net/weixin_42892101/article/details/104886937

USB_Audio_Port.c

/***  @file USB_Audio_Port.c**  @date 2021-06-01**  @author aron566**  @copyright Copyright (c) 2021 aron566 <aron566@163.com>.**  @brief USB音频类接口,对外提供音频更新及输出接口**  @details 1、开启对应FS中断,中断处理和初始化位于usbd_conf.c*           2、16k采样,双声道,10ms出320点数据*           3、1ms间隔发送,10ms发送10次,每次发送320/10 = 32点数据 数据大小64字节(16bit*32)*           4、接收来自MIC数据,10ms来一次每次双通道160点*2*  @version V1.0*/
/** Includes -----------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "USB_Audio_Port.h"
#include "main.h"
#include <arm_math.h>
#include "usbd_audio.h"
/** Use C compiler -----------------------------------------------------------*/
#ifdef __cplusplus ///<use C compiler
extern "C" {#endif
/** Private typedef ----------------------------------------------------------*/
/** Private macros -----------------------------------------------------------*/
#define USB_RX_BUF_SIZE_MAX       1024 /**< 接收缓冲区设置1024*2Bytes*/#define USB_PORT_AUDIO_OUT_PACKET AUDIO_PORT_OUT_SIZE    /**< 一次发送大小字节数*/
#define USB_PORT_AUDIO_BUF_SIZE   AUDIO_TOTAL_BUF_SIZE
#define USB_PORT_AUDIO_IN_EP      AUDIO_PORT_IN_EP_DIR_ID
#define USB_PORT_AUDIO_OUT_EP     AUDIO_PORT_OUT_EP_DIR_ID
/** Private constants --------------------------------------------------------*/
/** Public variables ---------------------------------------------------------*/
/** Private variables --------------------------------------------------------*/
/*音频缓冲区*/
static CQ_handleTypeDef USB_Audio_Data_Handle;
static int16_t USB_Audio_Receive_Buf[STEREO_FRAME_SIZE] = {0};
static uint16_t USB_Audio_Send_Buf[USB_RX_BUF_SIZE_MAX];
/** Private function prototypes ----------------------------------------------*//** Private user code --------------------------------------------------------*//** Private application code -------------------------------------------------*/
/*******************************************************************************
*
*       Static code
*
********************************************************************************
*/
/********************************************************************* @brief   USB音频接口初始化* @param   [in]None.* @return  None.* @author  aron566* @version V1.0* @date    2021-06-02*******************************************************************/
static void USB_Audio_Port_Init(void)
{/*初始化接收音频缓冲区*/CQ_16_init(&USB_Audio_Data_Handle, USB_Audio_Send_Buf, USB_RX_BUF_SIZE_MAX);
}/********************************************************************* @brief   向USB缓冲区数据加入数据* @param   [in]Data 待加入数据.* @param   [in]Size 待加入数据长度Size个16Bit.* @return  None.* @author  aron566* @version V1.0* @date    2021-06-04*******************************************************************/
static inline void USB_Audio_Port_Put_Audio_Data(const int16_t *Data, uint32_t Size)
{CQ_16putData(&USB_Audio_Data_Handle, (const uint16_t *)Data, Size);
}/** Public application code --------------------------------------------------*/
/*******************************************************************************
*
*       Public code
*
********************************************************************************
*//********************************************************************* @brief   USB缓冲区数据接收来自HOST* @param   [in]pdev device instance* @param   [in]epnum 端点号* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
uint8_t USB_Audio_Port_DataOut(void *xpdev, uint8_t epnum)
{uint16_t PacketSize;USBD_AUDIO_HandleTypeDef *haudio;USBD_HandleTypeDef *pdev = (USBD_HandleTypeDef *)xpdev;haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;if (haudio == NULL){return (uint8_t)USBD_FAIL;}if (epnum == USB_PORT_AUDIO_OUT_EP){/* Get received data packet length */PacketSize = (uint16_t)USBD_LL_GetRxDataSize(pdev, epnum);/* Packet received Callback */((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->PeriodicTC(&haudio->buffer[haudio->wr_ptr],PacketSize, AUDIO_OUT_TC);/* Increment the Buffer pointer or roll it back when all buffers are full */haudio->wr_ptr += PacketSize;if (haudio->wr_ptr == AUDIO_TOTAL_BUF_SIZE){/* All buffers are full: roll back */haudio->wr_ptr = 0U;if (haudio->offset == AUDIO_OFFSET_UNKNOWN){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->AudioCmd(&haudio->buffer[0],AUDIO_TOTAL_BUF_SIZE / 2U,AUDIO_CMD_START);haudio->offset = AUDIO_OFFSET_NONE;}}if (haudio->rd_enable == 0U){if (haudio->wr_ptr == (AUDIO_TOTAL_BUF_SIZE / 2U)){haudio->rd_enable = 1U;}}/* Prepare Out endpoint to receive next audio packet */(void)USBD_LL_PrepareReceive(pdev, USB_PORT_AUDIO_OUT_EP,&haudio->buffer[haudio->wr_ptr],AUDIO_OUT_PACKET);}return (uint8_t)USBD_OK;
}/********************************************************************* @brief   USB缓冲区数据发送至HOST* @param   [in]pdev device instance* @param   [in]epnum 端点号* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
uint8_t USB_Audio_Port_DataIn(void *xpdev, uint8_t epnum)
{USBD_HandleTypeDef *pdev = (USBD_HandleTypeDef *)xpdev;USBD_AUDIO_HandleTypeDef *haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;USBD_LL_FlushEP(pdev, USB_PORT_AUDIO_IN_EP);if(CQ_getLength(&USB_Audio_Data_Handle) < USB_PORT_AUDIO_OUT_PACKET/2){return (uint8_t)USBD_BUSY;}CQ_16getData(&USB_Audio_Data_Handle, (uint16_t *)haudio->buffer, USB_PORT_AUDIO_OUT_PACKET/2);return USBD_LL_Transmit(pdev, USB_PORT_AUDIO_IN_EP, haudio->buffer, USB_PORT_AUDIO_OUT_PACKET);
}/********************************************************************* @brief   反初始化音频输出端点* @param   [in]pdev* @param   [in]cfgidx* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
uint8_t USB_Audio_Port_EP_OUT_DeInit(void *xpdev, uint8_t cfgidx)
{UNUSED(cfgidx);USBD_HandleTypeDef *pdev = (USBD_HandleTypeDef *)xpdev;/* Open EP OUT */(void)USBD_LL_CloseEP(pdev, USB_PORT_AUDIO_OUT_EP);pdev->ep_out[USB_PORT_AUDIO_OUT_EP & 0xFU].is_used = 0U;pdev->ep_out[USB_PORT_AUDIO_OUT_EP & 0xFU].bInterval = 0U;/* DeInit  physical Interface components */if (pdev->pClassData != NULL){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->DeInit(0U);(void)USBD_free(pdev->pClassData);pdev->pClassData = NULL;}return (uint8_t)USBD_OK;
}/********************************************************************* @brief   反初始化音频输入端点* @param   [in]pdev* @param   [in]cfgidx* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
uint8_t USB_Audio_Port_EP_IN_DeInit(void *xpdev, uint8_t cfgidx)
{UNUSED(cfgidx);USBD_HandleTypeDef *pdev = (USBD_HandleTypeDef *)xpdev;/* Open EP OUT */  USBD_LL_CloseEP(pdev, USB_PORT_AUDIO_IN_EP);/* DeInit  physical Interface components */if (pdev->pClassData != NULL){((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->DeInit(0U);(void)USBD_free(pdev->pClassData);pdev->pClassData = NULL;}return (uint8_t)USBD_OK;
}/********************************************************************* @brief   初始化为音频输出端点* @param   [in]pdev* @param   [in]cfgidx* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
uint8_t USB_Audio_Port_EP_OUT_Init(void *xpdev, uint8_t cfgidx)
{UNUSED(cfgidx);USBD_AUDIO_HandleTypeDef *haudio;USBD_HandleTypeDef *pdev = (USBD_HandleTypeDef *)xpdev;/* Allocate Audio structure */haudio = USBD_malloc(sizeof(USBD_AUDIO_HandleTypeDef));if (haudio == NULL){pdev->pClassData = NULL;return (uint8_t)USBD_EMEM;}pdev->pClassData = (void *)haudio;if (pdev->dev_speed == USBD_SPEED_HIGH){pdev->ep_out[USB_PORT_AUDIO_OUT_EP & 0xFU].bInterval = AUDIO_HS_BINTERVAL;}else   /* LOW and FULL-speed endpoints */{pdev->ep_out[USB_PORT_AUDIO_OUT_EP & 0xFU].bInterval = AUDIO_FS_BINTERVAL;}/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, USB_PORT_AUDIO_OUT_EP, USBD_EP_TYPE_ISOC, USB_PORT_AUDIO_OUT_PACKET);pdev->ep_out[USB_PORT_AUDIO_OUT_EP & 0xFU].is_used = 1U;haudio->alt_setting = 0U;haudio->offset = AUDIO_OFFSET_UNKNOWN;haudio->wr_ptr = 0U;haudio->rd_ptr = 0U;haudio->rd_enable = 0U;/* Initialize the Audio output Hardware layer */if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->Init(USBD_AUDIO_FREQ,AUDIO_DEFAULT_VOLUME,0U) != 0U){return (uint8_t)USBD_FAIL;}/* Prepare Out endpoint to receive 1st packet */(void)USBD_LL_PrepareReceive(pdev, USB_PORT_AUDIO_OUT_EP, haudio->buffer,AUDIO_OUT_PACKET);return (uint8_t)USBD_OK;
}/********************************************************************* @brief   初始化为音频输入端点* @param   [in]pdev* @param   [in]cfgidx* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
uint8_t USB_Audio_Port_EP_IN_Init(void *xpdev, uint8_t cfgidx)
{UNUSED(cfgidx);USBD_AUDIO_HandleTypeDef *haudio;USBD_HandleTypeDef *pdev = (USBD_HandleTypeDef *)xpdev;/*USB接口初始化*/USB_Audio_Port_Init();/* Allocate Audio structure */haudio = USBD_malloc(sizeof(USBD_AUDIO_HandleTypeDef));if (haudio == NULL){pdev->pClassData = NULL;return (uint8_t)USBD_EMEM;}pdev->pClassData = (void *)haudio;if (pdev->dev_speed == USBD_SPEED_HIGH){pdev->ep_in[USB_PORT_AUDIO_IN_EP & 0xFU].bInterval = AUDIO_HS_BINTERVAL;}else   /* LOW and FULL-speed endpoints */{pdev->ep_in[USB_PORT_AUDIO_IN_EP & 0xFU].bInterval = AUDIO_FS_BINTERVAL;}/* Open EP IN */(void)USBD_LL_OpenEP(pdev, USB_PORT_AUDIO_IN_EP, USBD_EP_TYPE_ISOC, USB_PORT_AUDIO_OUT_PACKET); pdev->ep_in[USB_PORT_AUDIO_IN_EP & 0xFU].is_used = 1U;haudio->alt_setting = 0U;haudio->offset = AUDIO_OFFSET_UNKNOWN;haudio->wr_ptr = 0U;haudio->rd_ptr = 0U;haudio->rd_enable = 0U;memset(haudio->buffer, 0, USB_PORT_AUDIO_BUF_SIZE);USBD_LL_Transmit(pdev, USB_PORT_AUDIO_IN_EP, haudio->buffer, USB_PORT_AUDIO_OUT_PACKET);return (uint8_t)USBD_OK;
}/********************************************************************* @brief   更新USB音频数据* @param   [in]Left_Audio 左通道数据* @param   [in]Right_Audio 右通道数据* @return  None.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
void USB_Audio_Port_Put_Data(const int16_t *Left_Audio, const int16_t *Right_Audio)
{/*更新USB音频数据*/int index = 0, i = 0;for(i = 0; i < STEREO_FRAME_SIZE; index++){USB_Audio_Receive_Buf[i++] = Left_Audio[index];/**< TO USB LEFT*/USB_Audio_Receive_Buf[i++] = Right_Audio[index];/**< TO USB RIGHT*/}USB_Audio_Port_Put_Audio_Data(USB_Audio_Receive_Buf, STEREO_FRAME_SIZE);
}/********************************************************************* @brief   是否可以更新音频数据* @param   [in]None.* @return  true 可以.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
bool USB_Audio_Port_Can_Update_Data(void)
{if(USB_Audio_Data_Handle.size - CQ_getLength(&USB_Audio_Data_Handle) >= STEREO_FRAME_SIZE){return true;}return false;
}#ifdef __cplusplus ///<end extern c
}
#endif
/******************************** End of file *********************************/

USB_Audio_Port.h
文件中主要定义了相关宏,用于配置USB 麦克风描述符,如通道数,一次发送包大小,采样率(CubeMX配置),最大缓冲区

/***  @file USB_Audio_Port.h**  @date 2021-06-01**  @author aron566**  @brief *  *  @version V1.0*/
#ifndef USB_AUDIO_PORT_H
#define USB_AUDIO_PORT_H
/** Includes -----------------------------------------------------------------*/
#include <stdint.h> /**< need definition of uint8_t */
#include <stddef.h> /**< need definition of NULL    */
#include <stdbool.h>/**< need definition of BOOL    */
#include <stdio.h>  /**< if need printf             */
#include <stdlib.h>
#include <string.h>
#include <limits.h> /**< need variable max value    */
/** Exported macros-----------------------------------------------------------*/
#define AUDIO_PORT_CHANNEL_NUMS               2U      /**< MIC音频通道数*/
#define MONO_CHANNEL_SEL                      2U      /**< 0使用L声道 1使用R声道 2配置MONO*/
#define AUDIO_PORT_USBD_AUDIO_FREQ            16000U  /**< 设置音频采样率*//*音频类终端类型定义*/
#define AUDIO_PORT_INPUT_TERMINAL_ID_1        0x01
#define AUDIO_PORT_OUTPUT_TERMINAL_ID_3       0x03
#define AUDIO_PORT_INPUT_CTL_ID_2             0x02#define AUDIO_PORT_SPEAKE_TERMINAL_TYPE_L     0x01U
#define AUDIO_PORT_SPEAKE_TERMINAL_TYPE_H     0x03U#define AUDIO_PORT_STREAM_TERMINAL_TYPE_L     0x01U
#define AUDIO_PORT_STREAM_TERMINAL_TYPE_H     0x01U#define AUDIO_PORT_MICRO_PHONE_TERMINAL_L     0x01U
#define AUDIO_PORT_MICRO_PHONE_TERMINAL_H     0x02U#define AUDIO_PORT_IN_EP_DIR_ID               0x81  /**< (Direction=IN EndpointID=1)*/
#define AUDIO_PORT_OUT_EP_DIR_ID              0x01  /**< (Direction=OUT EndpointID=1)*//*立体声配置*/
#if AUDIO_PORT_CHANNEL_NUMS == 2/*使用L+R声道*/#define AUDIO_PORT_CHANNEL_CONFIG_L  0x03U#define AUDIO_PORT_CHANNEL_CONFIG_H  0x00U
/*单声道配置*/
#elif AUDIO_PORT_CHANNEL_NUMS == 1#if MONO_CHANNEL_SEL == 0/*使用L声道*/#define AUDIO_PORT_CHANNEL_CONFIG_L  0x01U#define AUDIO_PORT_CHANNEL_CONFIG_H  0x00U#elif MONO_CHANNEL_SEL == 1/*使用R声道*/#define AUDIO_PORT_CHANNEL_CONFIG_L  0x02U#define AUDIO_PORT_CHANNEL_CONFIG_H  0x00U#elif MONO_CHANNEL_SEL == 2/*使用默认MONO声道*/#define AUDIO_PORT_CHANNEL_CONFIG_L  0x00U#define AUDIO_PORT_CHANNEL_CONFIG_H  0x00U    #endif
#endif/*轮询时间间隔*/
#define AUDIO_PORT_FS_BINTERVAL           1U     /**< 1ms一次轮询*/
/*音频传输大小设置*/
#define AUDIO_PORT_PACKET_SZE(frq)       (uint8_t)(((frq * 2U * 2U)/(1000U/AUDIO_PORT_FS_BINTERVAL)) & 0xFFU), \(uint8_t)((((frq * 2U * 2U)/(1000U/AUDIO_PORT_FS_BINTERVAL)) >> 8) & 0xFFU)#define AUDIO_PORT_OUT_SIZE               ((AUDIO_PORT_USBD_AUDIO_FREQ * 2U * 2U)/(1000U/AUDIO_PORT_FS_BINTERVAL))   /**< 音频发送大小Byte*/
#define AUDIO_PORT_BUF_SIZE               AUDIO_PORT_OUT_SIZE*4   /**< 音频缓冲区大小 大于3的偶数倍*/
/** Private includes ---------------------------------------------------------*//** Use C compiler -----------------------------------------------------------*/
#ifdef __cplusplus ///<use C compiler
extern "C" {#endif
/** Private defines ----------------------------------------------------------*//** Exported typedefines -----------------------------------------------------*//** Exported constants -------------------------------------------------------*//** Exported variables -------------------------------------------------------*/
/** Exported functions prototypes --------------------------------------------*/
/*是否可以更新音频数据*/
bool USB_Audio_Port_Can_Update_Data(void);
/*向USB缓冲区数据加入数据*/
void USB_Audio_Port_Put_Data(const int16_t *Left_Audio, const int16_t *Right_Audio);
/*初始化音频输出端点*/
uint8_t USB_Audio_Port_EP_IN_Init(void *xpdev, uint8_t cfgidx);
/*初始化音频输入端点*/
uint8_t USB_Audio_Port_EP_OUT_Init(void *xpdev, uint8_t cfgidx);
/*反初始化音频输出端点*/
uint8_t USB_Audio_Port_EP_IN_DeInit(void *xpdev, uint8_t cfgidx);
/*反初始化音频输入端点*/
uint8_t USB_Audio_Port_EP_OUT_DeInit(void *xpdev, uint8_t cfgidx);
/*USB缓冲区数据发送至HOST*/
uint8_t USB_Audio_Port_DataIn(void *xpdev, uint8_t epnum);
/*USB缓冲区数据接收来自HOST*/
uint8_t USB_Audio_Port_DataOut(void *xpdev, uint8_t epnum);#ifdef __cplusplus ///<end extern c
}
#endif
#endif
/******************************** End of file *********************************/

如何使用

1、用usb_audio.c和对应头文件替换你原先的文件
2、工程添加USB_Audio_Port.cUSB_Audio_Port.h,环形缓冲区
3、调用接口添加新音频到缓冲区即可 USB_Audio_Port_Put_Data

测试正弦音频

/********************************************************************* @brief   正弦生成* @param   [in]None.* @return  None.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
#define SIN_WAVE_SAMPLE_RATE    16000/**< 16K采样*/
#define SIN_WAVE_FQ             100/**< 100Hz正弦*/
#define SIN_WAVE_MAX_POINTS     SIN_WAVE_SAMPLE_RATE/SIN_WAVE_FQ
#define SIN_WAVE_DB_VAL         50.l
static int16_t Sin_Wave_PCM_Buf[SIN_WAVE_MAX_POINTS] = {0};
static void Sin_Audio_Init(void)
{  float Average_Range = (float)pow(10.L, (double)((double)SIN_WAVE_DB_VAL - 94.f) / 20.L)*32767.f;for(int i = 0; i < SIN_WAVE_MAX_POINTS; i++){Sin_Wave_PCM_Buf[i] = Average_Range * arm_sin_f32(2.f*3.14f * SIN_WAVE_FQ / SIN_WAVE_SAMPLE_RATE * i);}
}/********************************************************************* @brief   更新USB音频数据* @param   [in]pdev* @param   [in]cfgidx* @return  USBD_OK 正常.* @author  aron566* @version V1.0* @date    2021-06-01*******************************************************************/
void USB_Audio_Port_Put_Data(const int16_t *Left_Audio, const int16_t *Right_Audio)
{/*更新USB音频数据*/static int index = 0;for(int i = 0; i < STEREO_FRAME_SIZE;){USB_Audio_Receive_Buf[i++] = Sin_Wave_PCM_Buf[index];/**< TO USB LEFT*/USB_Audio_Receive_Buf[i++] = Sin_Wave_PCM_Buf[index];/**< TO USB RIGHT*/index = ((index+1)%(SIN_WAVE_MAX_POINTS));}USB_Audio_Port_Put_Audio_Data(USB_Audio_Receive_Buf, STEREO_FRAME_SIZE);
}

测试工程

github

USB缓冲区设置

参考这里1
参考这里2

H7的HAL库USB问题

此版本遇到不完整的传输会中断传输,这里需要注意下。

/********************************************************************************* @file    stm32h7xx_hal_pcd.c* @author  MCD Application Team* @brief   PCD HAL module driver.*          This file provides firmware functions to manage the following*          functionalities of the USB Peripheral Controller:*           + Initialization and de-initialization functions*           + IO operation functions*           + Peripheral Control functions*           + Peripheral State functions******************************************************************************** @attention** Copyright (c) 2017 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.*******************************************************************************@verbatim==============================================================================##### How to use this driver #####==============================================================================[..]The PCD HAL driver can be used as follows:(#) Declare a PCD_HandleTypeDef handle structure, for example:PCD_HandleTypeDef  hpcd;(#) Fill parameters of Init structure in HCD handle(#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)(#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:(##) Enable the PCD/USB Low Level interface clock using(+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();(+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)(##) Initialize the related GPIO clocks(##) Configure PCD pin-out(##) Configure PCD NVIC interrupt(#)Associate the Upper USB device stack to the HAL PCD Driver:(##) hpcd.pData = pdev;(#)Enable PCD transmission and reception:(##) HAL_PCD_Start();@endverbatim*******************************************************************************//* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"/** @addtogroup STM32H7xx_HAL_Driver* @{*//** @defgroup PCD PCD* @brief PCD HAL module driver* @{*/#ifdef HAL_PCD_MODULE_ENABLED#if defined (USB_OTG_FS) || defined (USB_OTG_HS)/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup PCD_Private_Macros PCD Private Macros* @{*/
#define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
#define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
/*** @}*//* Private functions prototypes ----------------------------------------------*/
/** @defgroup PCD_Private_Functions PCD Private Functions* @{*/
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
/*** @}*//* Exported functions --------------------------------------------------------*/
/** @defgroup PCD_Exported_Functions PCD Exported Functions* @{*//** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions*  @brief    Initialization and Configuration functions*
@verbatim===============================================================================##### Initialization and de-initialization functions #####===============================================================================[..]  This section provides functions allowing to:@endverbatim* @{*//*** @brief  Initializes the PCD according to the specified*         parameters in the PCD_InitTypeDef and initialize the associated handle.* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
{USB_OTG_GlobalTypeDef *USBx;uint8_t i;/* Check the PCD handle allocation */if (hpcd == NULL){return HAL_ERROR;}/* Check the parameters */assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));USBx = hpcd->Instance;if (hpcd->State == HAL_PCD_STATE_RESET){/* Allocate lock resource and initialize it */hpcd->Lock = HAL_UNLOCKED;#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->SOFCallback = HAL_PCD_SOFCallback;hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;hpcd->ResetCallback = HAL_PCD_ResetCallback;hpcd->SuspendCallback = HAL_PCD_SuspendCallback;hpcd->ResumeCallback = HAL_PCD_ResumeCallback;hpcd->ConnectCallback = HAL_PCD_ConnectCallback;hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;if (hpcd->MspInitCallback == NULL){hpcd->MspInitCallback = HAL_PCD_MspInit;}/* Init the low level hardware */hpcd->MspInitCallback(hpcd);
#else/* Init the low level hardware : GPIO, CLOCK, NVIC... */HAL_PCD_MspInit(hpcd);
#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */}hpcd->State = HAL_PCD_STATE_BUSY;/* Disable DMA mode for FS instance */if ((USBx->CID & (0x1U << 8)) == 0U){hpcd->Init.dma_enable = 0U;}/* Disable the Interrupts */__HAL_PCD_DISABLE(hpcd);/*Init the Core (common init.) */if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK){hpcd->State = HAL_PCD_STATE_ERROR;return HAL_ERROR;}/* Force Device Mode*/(void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);/* Init endpoints structures */for (i = 0U; i < hpcd->Init.dev_endpoints; i++){/* Init ep structure */hpcd->IN_ep[i].is_in = 1U;hpcd->IN_ep[i].num = i;hpcd->IN_ep[i].tx_fifo_num = i;/* Control until ep is activated */hpcd->IN_ep[i].type = EP_TYPE_CTRL;hpcd->IN_ep[i].maxpacket = 0U;hpcd->IN_ep[i].xfer_buff = 0U;hpcd->IN_ep[i].xfer_len = 0U;}for (i = 0U; i < hpcd->Init.dev_endpoints; i++){hpcd->OUT_ep[i].is_in = 0U;hpcd->OUT_ep[i].num = i;/* Control until ep is activated */hpcd->OUT_ep[i].type = EP_TYPE_CTRL;hpcd->OUT_ep[i].maxpacket = 0U;hpcd->OUT_ep[i].xfer_buff = 0U;hpcd->OUT_ep[i].xfer_len = 0U;}/* Init Device */if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK){hpcd->State = HAL_PCD_STATE_ERROR;return HAL_ERROR;}hpcd->USB_Address = 0U;hpcd->State = HAL_PCD_STATE_READY;/* Activate LPM */if (hpcd->Init.lpm_enable == 1U){(void)HAL_PCDEx_ActivateLPM(hpcd);}(void)USB_DevDisconnect(hpcd->Instance);return HAL_OK;
}/*** @brief  DeInitializes the PCD peripheral.* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
{/* Check the PCD handle allocation */if (hpcd == NULL){return HAL_ERROR;}hpcd->State = HAL_PCD_STATE_BUSY;/* Stop Device */if (USB_StopDevice(hpcd->Instance) != HAL_OK){return HAL_ERROR;}#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)if (hpcd->MspDeInitCallback == NULL){hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */}/* DeInit the low level hardware */hpcd->MspDeInitCallback(hpcd);
#else/* DeInit the low level hardware: CLOCK, NVIC.*/HAL_PCD_MspDeInit(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */hpcd->State = HAL_PCD_STATE_RESET;return HAL_OK;
}/*** @brief  Initializes the PCD MSP.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_MspInit could be implemented in the user file*/
}/*** @brief  DeInitializes PCD MSP.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_MspDeInit could be implemented in the user file*/
}#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/*** @brief  Register a User USB PCD Callback*         To be used instead of the weak predefined callback* @param  hpcd USB PCD handle* @param  CallbackID ID of the callback to be registered*         This parameter can be one of the following values:*          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID*          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID*          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID*          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID*          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID*          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID*          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID*          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID*          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID* @param  pCallback pointer to the Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,HAL_PCD_CallbackIDTypeDef CallbackID,pPCD_CallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){switch (CallbackID){case HAL_PCD_SOF_CB_ID :hpcd->SOFCallback = pCallback;break;case HAL_PCD_SETUPSTAGE_CB_ID :hpcd->SetupStageCallback = pCallback;break;case HAL_PCD_RESET_CB_ID :hpcd->ResetCallback = pCallback;break;case HAL_PCD_SUSPEND_CB_ID :hpcd->SuspendCallback = pCallback;break;case HAL_PCD_RESUME_CB_ID :hpcd->ResumeCallback = pCallback;break;case HAL_PCD_CONNECT_CB_ID :hpcd->ConnectCallback = pCallback;break;case HAL_PCD_DISCONNECT_CB_ID :hpcd->DisconnectCallback = pCallback;break;case HAL_PCD_MSPINIT_CB_ID :hpcd->MspInitCallback = pCallback;break;case HAL_PCD_MSPDEINIT_CB_ID :hpcd->MspDeInitCallback = pCallback;break;default :/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;break;}}else if (hpcd->State == HAL_PCD_STATE_RESET){switch (CallbackID){case HAL_PCD_MSPINIT_CB_ID :hpcd->MspInitCallback = pCallback;break;case HAL_PCD_MSPDEINIT_CB_ID :hpcd->MspDeInitCallback = pCallback;break;default :/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;break;}}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister an USB PCD Callback*         USB PCD callback is redirected to the weak predefined callback* @param  hpcd USB PCD handle* @param  CallbackID ID of the callback to be unregistered*         This parameter can be one of the following values:*          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID*          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID*          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID*          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID*          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID*          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID*          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID*          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID*          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);/* Setup Legacy weak Callbacks  */if (hpcd->State == HAL_PCD_STATE_READY){switch (CallbackID){case HAL_PCD_SOF_CB_ID :hpcd->SOFCallback = HAL_PCD_SOFCallback;break;case HAL_PCD_SETUPSTAGE_CB_ID :hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;break;case HAL_PCD_RESET_CB_ID :hpcd->ResetCallback = HAL_PCD_ResetCallback;break;case HAL_PCD_SUSPEND_CB_ID :hpcd->SuspendCallback = HAL_PCD_SuspendCallback;break;case HAL_PCD_RESUME_CB_ID :hpcd->ResumeCallback = HAL_PCD_ResumeCallback;break;case HAL_PCD_CONNECT_CB_ID :hpcd->ConnectCallback = HAL_PCD_ConnectCallback;break;case HAL_PCD_DISCONNECT_CB_ID :hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;break;case HAL_PCD_MSPINIT_CB_ID :hpcd->MspInitCallback = HAL_PCD_MspInit;break;case HAL_PCD_MSPDEINIT_CB_ID :hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;break;default :/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;break;}}else if (hpcd->State == HAL_PCD_STATE_RESET){switch (CallbackID){case HAL_PCD_MSPINIT_CB_ID :hpcd->MspInitCallback = HAL_PCD_MspInit;break;case HAL_PCD_MSPDEINIT_CB_ID :hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;break;default :/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;break;}}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Register USB PCD Data OUT Stage Callback*         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback* @param  hpcd PCD handle* @param  pCallback pointer to the USB PCD Data OUT Stage Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,pPCD_DataOutStageCallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->DataOutStageCallback = pCallback;}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister the USB PCD Data OUT Stage Callback*         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Register USB PCD Data IN Stage Callback*         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback* @param  hpcd PCD handle* @param  pCallback pointer to the USB PCD Data IN Stage Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,pPCD_DataInStageCallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->DataInStageCallback = pCallback;}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister the USB PCD Data IN Stage Callback*         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Register USB PCD Iso OUT incomplete Callback*         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback* @param  hpcd PCD handle* @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,pPCD_IsoOutIncpltCallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->ISOOUTIncompleteCallback = pCallback;}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister the USB PCD Iso OUT incomplete Callback*         USB PCD Iso OUT incomplete Callback is redirected*         to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Register USB PCD Iso IN incomplete Callback*         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback* @param  hpcd PCD handle* @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,pPCD_IsoInIncpltCallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->ISOINIncompleteCallback = pCallback;}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister the USB PCD Iso IN incomplete Callback*         USB PCD Iso IN incomplete Callback is redirected*         to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Register USB PCD BCD Callback*         To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback* @param  hpcd PCD handle* @param  pCallback pointer to the USB PCD BCD Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->BCDCallback = pCallback;}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister the USB PCD BCD Callback*         USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback  */}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Register USB PCD LPM Callback*         To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback* @param  hpcd PCD handle* @param  pCallback pointer to the USB PCD LPM Callback function* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
{HAL_StatusTypeDef status = HAL_OK;if (pCallback == NULL){/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;return HAL_ERROR;}/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->LPMCallback = pCallback;}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}/*** @brief  Unregister the USB PCD LPM Callback*         USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
{HAL_StatusTypeDef status = HAL_OK;/* Process locked */__HAL_LOCK(hpcd);if (hpcd->State == HAL_PCD_STATE_READY){hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback  */}else{/* Update the error code */hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;/* Return error status */status =  HAL_ERROR;}/* Release Lock */__HAL_UNLOCK(hpcd);return status;
}
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS *//*** @}*//** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions*  @brief   Data transfers functions*
@verbatim===============================================================================##### IO operation functions #####===============================================================================[..]This subsection provides a set of functions allowing to manage the PCD datatransfers.@endverbatim* @{*//*** @brief  Start the USB device* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;__HAL_LOCK(hpcd);if ((hpcd->Init.battery_charging_enable == 1U) &&(hpcd->Init.phy_itface != USB_OTG_ULPI_PHY)){/* Enable USB Transceiver */USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;}__HAL_PCD_ENABLE(hpcd);(void)USB_DevConnect(hpcd->Instance);__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Stop the USB device.* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;__HAL_LOCK(hpcd);__HAL_PCD_DISABLE(hpcd);(void)USB_DevDisconnect(hpcd->Instance);(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);if ((hpcd->Init.battery_charging_enable == 1U) &&(hpcd->Init.phy_itface != USB_OTG_ULPI_PHY)){/* Disable USB Transceiver */USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);}__HAL_UNLOCK(hpcd);return HAL_OK;
}#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
/*** @brief  Handles PCD interrupt request.* @param  hpcd PCD handle* @retval HAL status*/
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;uint32_t USBx_BASE = (uint32_t)USBx;USB_OTG_EPTypeDef *ep;uint32_t i;uint32_t ep_intr;uint32_t epint;uint32_t epnum;uint32_t fifoemptymsk;uint32_t RegVal;/* ensure that we are in device mode */if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE){/* avoid spurious interrupt */if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)){return;}/* store current frame number */hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS)){/* incorrect mode, acknowledge the interrupt */__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);}/* Handle RxQLevel Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL)){USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);RegVal = USBx->GRXSTSP;ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT){if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U){(void)USB_ReadPacket(USBx, ep->xfer_buff,(uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;}}else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT){(void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;}else{/* ... */}USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);}if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT)){epnum = 0U;/* Read in the device interrupt bits */ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);while (ep_intr != 0U){if ((ep_intr & 0x1U) != 0U){epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);(void)PCD_EP_OutXfrComplete_int(hpcd, epnum);}if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);/* Class B setup phase done for previous decoded setup */(void)PCD_EP_OutSetupPacket_int(hpcd, epnum);}if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);}/* Clear OUT Endpoint disable interrupt */if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD){if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF){USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;}ep = &hpcd->OUT_ep[epnum];if (ep->is_iso_incomplete == 1U){ep->is_iso_incomplete = 0U;#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);}/* Clear Status Phase Received interrupt */if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);}/* Clear OUT NAK interrupt */if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);}}epnum++;ep_intr >>= 1U;}}if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT)){/* Read in the device interrupt bits */ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);epnum = 0U;while (ep_intr != 0U){if ((ep_intr & 0x1U) != 0U) /* In ITR */{epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC){fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);if (hpcd->Init.dma_enable == 1U){hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;/* this is ZLP, so prepare EP0 for next setup */if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U)){/* prepare to rx more setup packets */(void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);}}#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC){CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);}if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE){CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);}if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE){CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);}if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD){(void)USB_FlushTxFifo(USBx, epnum);ep = &hpcd->IN_ep[epnum];if (ep->is_iso_incomplete == 1U){ep->is_iso_incomplete = 0U;#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);}if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE){(void)PCD_WriteEmptyTxFifo(hpcd, epnum);}}epnum++;ep_intr >>= 1U;}}/* Handle Resume Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT)){/* Clear the Remote Wake-up Signaling */USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;if (hpcd->LPM_State == LPM_L1){hpcd->LPM_State = LPM_L0;#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
#elseHAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}else{#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->ResumeCallback(hpcd);
#elseHAL_PCD_ResumeCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);}/* Handle Suspend Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP)){if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS){#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->SuspendCallback(hpcd);
#elseHAL_PCD_SuspendCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);}/* Handle LPM Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT)){__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);if (hpcd->LPM_State == LPM_L0){hpcd->LPM_State = LPM_L1;hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
#elseHAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}else{#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->SuspendCallback(hpcd);
#elseHAL_PCD_SuspendCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}}/* Handle Reset Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST)){USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);for (i = 0U; i < hpcd->Init.dev_endpoints; i++){USBx_INEP(i)->DIEPINT = 0xFB7FU;USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;USBx_OUTEP(i)->DOEPINT = 0xFB7FU;USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;}USBx_DEVICE->DAINTMSK |= 0x10001U;if (hpcd->Init.use_dedicated_ep1 != 0U){USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |USB_OTG_DOEPMSK_XFRCM |USB_OTG_DOEPMSK_EPDM;USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |USB_OTG_DIEPMSK_XFRCM |USB_OTG_DIEPMSK_EPDM;}else{USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |USB_OTG_DOEPMSK_XFRCM |USB_OTG_DOEPMSK_EPDM |USB_OTG_DOEPMSK_OTEPSPRM |USB_OTG_DOEPMSK_NAKM;USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |USB_OTG_DIEPMSK_XFRCM |USB_OTG_DIEPMSK_EPDM;}/* Set Default Address to 0 */USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;/* setup EP0 to receive SETUP packets */(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,(uint8_t *)hpcd->Setup);__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);}/* Handle Enumeration done Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE)){(void)USB_ActivateSetup(hpcd->Instance);hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);/* Set USB Turnaround time */(void)USB_SetTurnaroundTime(hpcd->Instance,HAL_RCC_GetHCLKFreq(),(uint8_t)hpcd->Init.speed);#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->ResetCallback(hpcd);
#elseHAL_PCD_ResetCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);}/* Handle SOF Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF)){#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->SOFCallback(hpcd);
#elseHAL_PCD_SOFCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);}/* Handle Global OUT NAK effective Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF)){USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++){if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U){/* Abort current transaction and disable the EP */(void)HAL_PCD_EP_Abort(hpcd, (uint8_t)epnum);}}}/* Handle Incomplete ISO IN Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR)){   for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++){RegVal = USBx_INEP(epnum)->DIEPCTL;if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)){hpcd->IN_ep[epnum].is_iso_incomplete = 1U;//          /* Abort current transaction and disable the EP */
//          (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));/* Keep application checking the corresponding Iso IN endpointcausing the incomplete Interrupt */#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */          }}__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);}/* Handle Incomplete ISO OUT Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)){for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++){RegVal = USBx_OUTEP(epnum)->DOEPCTL;if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&((RegVal & (0x1U << 16)) == (hpcd->FrameNumber & 0x1U))){hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U){USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;break;}}}__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);}/* Handle Connection event Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT)){#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->ConnectCallback(hpcd);
#elseHAL_PCD_ConnectCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);}/* Handle Disconnection event Interrupt */if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT)){RegVal = hpcd->Instance->GOTGINT;if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET){#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->DisconnectCallback(hpcd);
#elseHAL_PCD_DisconnectCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}hpcd->Instance->GOTGINT |= RegVal;}}
}
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) *//*** @brief  Data OUT stage callback.* @param  hpcd PCD handle* @param  epnum endpoint number* @retval None*/
__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);UNUSED(epnum);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_DataOutStageCallback could be implemented in the user file*/
}/*** @brief  Data IN stage callback* @param  hpcd PCD handle* @param  epnum endpoint number* @retval None*/
__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);UNUSED(epnum);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_DataInStageCallback could be implemented in the user file*/
}
/*** @brief  Setup stage callback* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_SetupStageCallback could be implemented in the user file*/
}/*** @brief  USB Start Of Frame callback.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_SOFCallback could be implemented in the user file*/
}/*** @brief  USB Reset callback.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_ResetCallback could be implemented in the user file*/
}/*** @brief  Suspend event callback.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_SuspendCallback could be implemented in the user file*/
}/*** @brief  Resume event callback.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_ResumeCallback could be implemented in the user file*/
}/*** @brief  Incomplete ISO OUT callback.* @param  hpcd PCD handle* @param  epnum endpoint number* @retval None*/
__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);UNUSED(epnum);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file*/
}/*** @brief  Incomplete ISO IN callback.* @param  hpcd PCD handle* @param  epnum endpoint number* @retval None*/
__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);UNUSED(epnum);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file*/
}/*** @brief  Connection event callback.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_ConnectCallback could be implemented in the user file*/
}/*** @brief  Disconnection event callback.* @param  hpcd PCD handle* @retval None*/
__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
{/* Prevent unused argument(s) compilation warning */UNUSED(hpcd);/* NOTE : This function should not be modified, when the callback is needed,the HAL_PCD_DisconnectCallback could be implemented in the user file*/
}/*** @}*//** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions*  @brief   management functions*
@verbatim===============================================================================##### Peripheral Control functions #####===============================================================================[..]This subsection provides a set of functions allowing to control the PCD datatransfers.@endverbatim* @{*//*** @brief  Connect the USB device* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;__HAL_LOCK(hpcd);if ((hpcd->Init.battery_charging_enable == 1U) &&(hpcd->Init.phy_itface != USB_OTG_ULPI_PHY)){/* Enable USB Transceiver */USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;}(void)USB_DevConnect(hpcd->Instance);__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Disconnect the USB device.* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;__HAL_LOCK(hpcd);(void)USB_DevDisconnect(hpcd->Instance);if ((hpcd->Init.battery_charging_enable == 1U) &&(hpcd->Init.phy_itface != USB_OTG_ULPI_PHY)){/* Disable USB Transceiver */USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);}__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Set the USB Device address.* @param  hpcd PCD handle* @param  address new device address* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
{__HAL_LOCK(hpcd);hpcd->USB_Address = address;(void)USB_SetDevAddress(hpcd->Instance, address);__HAL_UNLOCK(hpcd);return HAL_OK;
}
/*** @brief  Open and configure an endpoint.* @param  hpcd PCD handle* @param  ep_addr endpoint address* @param  ep_mps endpoint max packet size* @param  ep_type endpoint type* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,uint16_t ep_mps, uint8_t ep_type)
{HAL_StatusTypeDef  ret = HAL_OK;PCD_EPTypeDef *ep;if ((ep_addr & 0x80U) == 0x80U){ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 1U;}else{ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 0U;}ep->num = ep_addr & EP_ADDR_MSK;ep->maxpacket = ep_mps;ep->type = ep_type;if (ep->is_in != 0U){/* Assign a Tx FIFO */ep->tx_fifo_num = ep->num;}/* Set initial data PID. */if (ep_type == EP_TYPE_BULK){ep->data_pid_start = 0U;}__HAL_LOCK(hpcd);(void)USB_ActivateEndpoint(hpcd->Instance, ep);__HAL_UNLOCK(hpcd);return ret;
}/*** @brief  Deactivate an endpoint.* @param  hpcd PCD handle* @param  ep_addr endpoint address* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{PCD_EPTypeDef *ep;if ((ep_addr & 0x80U) == 0x80U){ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 1U;}else{ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 0U;}ep->num   = ep_addr & EP_ADDR_MSK;__HAL_LOCK(hpcd);(void)USB_DeactivateEndpoint(hpcd->Instance, ep);__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Receive an amount of data.* @param  hpcd PCD handle* @param  ep_addr endpoint address* @param  pBuf pointer to the reception buffer* @param  len amount of data to be received* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
{PCD_EPTypeDef *ep;ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];/*setup and start the Xfer */ep->xfer_buff = pBuf;ep->xfer_len = len;ep->xfer_count = 0U;ep->is_in = 0U;ep->num = ep_addr & EP_ADDR_MSK;if (hpcd->Init.dma_enable == 1U){ep->dma_addr = (uint32_t)pBuf;}if ((ep_addr & EP_ADDR_MSK) == 0U){(void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);}else{(void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);}return HAL_OK;
}/*** @brief  Get Received Data Size* @param  hpcd PCD handle* @param  ep_addr endpoint address* @retval Data Size*/
uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
}
/*** @brief  Send an amount of data* @param  hpcd PCD handle* @param  ep_addr endpoint address* @param  pBuf pointer to the transmission buffer* @param  len amount of data to be sent* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
{PCD_EPTypeDef *ep;ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];/*setup and start the Xfer */ep->xfer_buff = pBuf;ep->xfer_len = len;ep->xfer_count = 0U;ep->is_in = 1U;ep->num = ep_addr & EP_ADDR_MSK;if (hpcd->Init.dma_enable == 1U){ep->dma_addr = (uint32_t)pBuf;}if ((ep_addr & EP_ADDR_MSK) == 0U){(void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);}else{(void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);}return HAL_OK;
}/*** @brief  Set a STALL condition over an endpoint* @param  hpcd PCD handle* @param  ep_addr endpoint address* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{PCD_EPTypeDef *ep;if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints){return HAL_ERROR;}if ((0x80U & ep_addr) == 0x80U){ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 1U;}else{ep = &hpcd->OUT_ep[ep_addr];ep->is_in = 0U;}ep->is_stall = 1U;ep->num = ep_addr & EP_ADDR_MSK;__HAL_LOCK(hpcd);(void)USB_EPSetStall(hpcd->Instance, ep);if ((ep_addr & EP_ADDR_MSK) == 0U){(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);}__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Clear a STALL condition over in an endpoint* @param  hpcd PCD handle* @param  ep_addr endpoint address* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{PCD_EPTypeDef *ep;if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints){return HAL_ERROR;}if ((0x80U & ep_addr) == 0x80U){ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 1U;}else{ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];ep->is_in = 0U;}ep->is_stall = 0U;ep->num = ep_addr & EP_ADDR_MSK;__HAL_LOCK(hpcd);(void)USB_EPClearStall(hpcd->Instance, ep);__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Abort an USB EP transaction.* @param  hpcd PCD handle* @param  ep_addr endpoint address* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{HAL_StatusTypeDef ret;PCD_EPTypeDef *ep;if ((0x80U & ep_addr) == 0x80U){ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];}else{ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];}/* Stop Xfer */ret = USB_EPStopXfer(hpcd->Instance, ep);return ret;
}/*** @brief  Flush an endpoint* @param  hpcd PCD handle* @param  ep_addr endpoint address* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{__HAL_LOCK(hpcd);if ((ep_addr & 0x80U) == 0x80U){(void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);}else{(void)USB_FlushRxFifo(hpcd->Instance);}__HAL_UNLOCK(hpcd);return HAL_OK;
}/*** @brief  Activate remote wakeup signalling* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
{return (USB_ActivateRemoteWakeup(hpcd->Instance));
}/*** @brief  De-activate remote wakeup signalling.* @param  hpcd PCD handle* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
{return (USB_DeActivateRemoteWakeup(hpcd->Instance));
}/*** @}*//** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions*  @brief   Peripheral State functions*
@verbatim===============================================================================##### Peripheral State functions #####===============================================================================[..]This subsection permits to get in run-time the status of the peripheraland the data flow.@endverbatim* @{*//*** @brief  Return the PCD handle state.* @param  hpcd PCD handle* @retval HAL state*/
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
{return hpcd->State;
}/*** @brief  Set the USB Device high speed test mode.* @param  hpcd PCD handle* @param  testmode USB Device high speed test mode* @retval HAL status*/
HAL_StatusTypeDef HAL_PCD_SetTestMode(PCD_HandleTypeDef *hpcd, uint8_t testmode)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;uint32_t USBx_BASE = (uint32_t)USBx;switch (testmode){case TEST_J:case TEST_K:case TEST_SE0_NAK:case TEST_PACKET:case TEST_FORCE_EN:USBx_DEVICE->DCTL |= (uint32_t)testmode << 4;break;default:break;}return HAL_OK;
}
/*** @}*//*** @}*//* Private functions ---------------------------------------------------------*/
/** @addtogroup PCD_Private_Functions* @{*/
#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
/*** @brief  Check FIFO for the next packet to be loaded.* @param  hpcd PCD handle* @param  epnum endpoint number* @retval HAL status*/
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;uint32_t USBx_BASE = (uint32_t)USBx;USB_OTG_EPTypeDef *ep;uint32_t len;uint32_t len32b;uint32_t fifoemptymsk;ep = &hpcd->IN_ep[epnum];if (ep->xfer_count > ep->xfer_len){return HAL_ERROR;}len = ep->xfer_len - ep->xfer_count;if (len > ep->maxpacket){len = ep->maxpacket;}len32b = (len + 3U) / 4U;while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&(ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U)){/* Write the FIFO */len = ep->xfer_len - ep->xfer_count;if (len > ep->maxpacket){len = ep->maxpacket;}len32b = (len + 3U) / 4U;(void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len,(uint8_t)hpcd->Init.dma_enable);ep->xfer_buff  += len;ep->xfer_count += len;}if (ep->xfer_len <= ep->xfer_count){fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;}return HAL_OK;
}/*** @brief  process EP OUT transfer complete interrupt.* @param  hpcd PCD handle* @param  epnum endpoint number* @retval HAL status*/
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
{USB_OTG_EPTypeDef *ep;USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;uint32_t USBx_BASE = (uint32_t)USBx;uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;if (hpcd->Init.dma_enable == 1U){if ((DoepintReg & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) /* Class C */{/* StupPktRcvd = 1 this is a setup packet */if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);}}else if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) /* Class E */{CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);}else if ((DoepintReg & (USB_OTG_DOEPINT_STUP | USB_OTG_DOEPINT_OTEPSPR)) == 0U){/* StupPktRcvd = 1 this is a setup packet */if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);}else{ep = &hpcd->OUT_ep[epnum];/* out data packet received over EP */ep->xfer_count = ep->xfer_size - (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);if (epnum == 0U){if (ep->xfer_len == 0U){/* this is ZLP, so prepare EP0 for next setup */(void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);}else{ep->xfer_buff += ep->xfer_count;}}#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}}else{/* ... */}}else{if (gSNPSiD == USB_OTG_CORE_ID_310A){/* StupPktRcvd = 1 this is a setup packet */if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);}else{if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);}#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}}else{if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U)){/* this is ZLP, so prepare EP0 for next setup */(void)USB_EP0_OutStart(hpcd->Instance, 0U, (uint8_t *)hpcd->Setup);}#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
#elseHAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */}}return HAL_OK;
}/*** @brief  process EP OUT setup packet received interrupt.* @param  hpcd PCD handle* @param  epnum endpoint number* @retval HAL status*/
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
{USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;uint32_t USBx_BASE = (uint32_t)USBx;uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)){CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);}/* Inform the upper layer that a setup packet is available */
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)hpcd->SetupStageCallback(hpcd);
#elseHAL_PCD_SetupStageCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */if ((gSNPSiD > USB_OTG_CORE_ID_300A) && (hpcd->Init.dma_enable == 1U)){(void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);}return HAL_OK;
}
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) *//*** @}*/
#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
#endif /* HAL_PCD_MODULE_ENABLED *//*** @}*//*** @}*/

参考引用

https://blog.csdn.net/xiaowanbiao123/article/details/112611264#comments_15318445
https://my.oschina.net/u/2007478/blog/1204300

STM32 USB音频麦克风实现相关推荐

  1. pyaudio usb playback_5.5寸触控屏IP电话会议USB全向麦克风NK-OAM600U_影视工业网

    寸触控屏视频会议USB全向麦克风(拾音器)NK-OAM600U 概述: 派尼珂NK-OAM600U视频会议USB全向麦克风,是一款配置多点手势触控FHD屏的高清会议电话,便捷的连接方式:支持USB/以 ...

  2. 台湾SSS鑫创SSS1700替代Cmedia CM6533 24bit 96KHZ USB音频编解码芯片

    台湾鑫创在2021年推出一款芯片SSS1700可以替代兼容CM6533,不管在音质和兼容性方面都优于Cmedia CM6533,且SSS1700外围电路较简单易设计,芯片成本比Cmedia CM653 ...

  3. linux usb 全向麦克风,派尼珂USB视频会议全向阵列麦克风NK-OM300U

    USB视频会议全向阵列麦克风NK-OM300U 派尼珂USB视频会议全向阵列麦克风NK-OM300U是一款级的USB高清全向麦克风,采用USB线缆有线传输,做到一线传输音频及供电,同时支持无线2.4G ...

  4. SSS1630规格书|SSS1630中文设计方案|USB音频解码方案

    SSS1630规格书,中文设计方案,SSS1630电路设计,USB音频解码方案,高端USB耳机方案,游戏耳机方案,USB麦克风方案 SSS1630的主要功能特点: 1.SSS1630耳机输出 2.SS ...

  5. 高品质USB声卡/音频芯片SSS1700|SSS1700设计96 KHz 24位采样率USB耳机麦克风方案|SSS1700中文设计方案讲解

    高品质USB声卡/音频芯片SSS1700|SSS1700设计96 KHz 24位采样率USB耳机麦克风方案|SSS1700中文设计方案讲解 台湾鑫创在2021年新推的一款SSS1700,是一款高品质U ...

  6. 台湾SSS鑫创SSS1700替代Cmedia CM6533 24bit 96KHZ USB音频编解码芯片|SSS1700替代CM6533设计方案

    台湾SSS鑫创SSS1700替代Cmedia CM6533 24bit 96KHZ USB音频编解码芯片|SSS1700替代CM6533设计方案 台湾鑫创在2021年推出一款芯片SSS1700可以替代 ...

  7. USB声卡驱动(二):USB音频设备描述符

    USB声卡驱动(二)USB音频设备描述符 本篇笔记,分两部分,第一部分,是基本知识的记录.第二部分是一个实际的例子. 一.基本知识 一个音频设备(Audio Device)含有多个音频功能(Audio ...

  8. USB音频/耳机芯片DP108替代CM108AH

    已被广泛应用的USB音频/耳机芯片DP108,虚拟7.1声道,电脑界面驱动.内部集成晶振,包括双通道DAC和耳机功放,ADC,麦克风增压器,PLL,稳压器,USB收发器等模拟模块在DP108内.许多功 ...

  9. pyaudio usb playback_Behringer的X2222USB是一款22输入2/2总线调音台和USB音频接口

    Behringer的X2222USB是一款22输入2/2总线调音台和USB音频接口大量I / O,内置多FX和USB音频与您的计算机连接.Behringer的X2222USB可以在一个盒子里拥有录制和 ...

最新文章

  1. linux怎么停止ssh服务,Linux 故障排除:关闭 SSH 会话后如何保存工作状态?
  2. 最大整数(Noip1998连接多位数)
  3. Elasticsearch系列「」学习路线
  4. BIOS INT 10-13功能调用的“另类”玩法
  5. bzoj1059: [ZJOI2007]矩阵游戏
  6. c语言头文件_C语言学习之头文件的原理和使用方法
  7. 云计算教程学习入门视频课件:云计算基础服务组件讲解
  8. React+Webpack+ES6 兼容低版本浏览器(IE9)解决方案
  9. c语言 验证码怎么写,JS验证码实现代码
  10. h2测试软件,H2testw怎么测试 H2testw测试结果如何看的详细技巧
  11. 千月影视选集前端,这个可以H5多端
  12. 游戏后端自增id选型
  13. pada aws configuration
  14. 飞书开放平台-全新消息卡片搭建工具
  15. 新版本谷歌浏览器自动运行flash
  16. 项目产品化的版本管控实践方案
  17. 关于苹果ARKit的功能梳理和展望
  18. 《headfirst设计模式》读书笔记9-迭代器和组合模式
  19. 4-6:关注列表,粉丝列表
  20. 【时间序列】TFT:Temporal Fusion Transformers

热门文章

  1. 【推荐】写给想爱,正在爱,失去爱的人
  2. 为什么你的抖音号涨粉慢,粉丝上不去的关键原因
  3. python学习笔记 4 - 线性回归、波士顿房价数据分析
  4. 甲骨文服务器保活脚本(Oracle keep alive)
  5. 小米OV,明年靠什么冲刺KPI?
  6. vs code上配置tcl/tk语言开发环境
  7. Zookeeper中NullPointerException
  8. iFunk S机械键盘游戏本登陆苏宁
  9. 深度剖析ROC曲线以及AUC指标
  10. 怎么清理c盘的垃圾文件?有什么好的清理方法推荐?