USB -- STM32F103 USB AUDIO(音频)Microphone同步传输(In传输)讲解(八)

2023-12-28 13:45:27

目录

链接快速定位

前沿??

1 描述符修改

1.1 设备描述符修改

1.2 配置描述符修改

1.3 字符串描述符修改

1.4 编译报错修改

2 增加功能函数

2.1 Microphone功能模块介绍

2.2 增加Microphone初始化函数函数

2.3 I2S中断函数修改

2.4 USB复位函数修改

2.5 非零端点函数修改

3 运行演示


链接快速定位

USB -- 初识USB协议(一)

源码下载请参考链接USB -- STM32-FS-USB-Device驱动代码简述(二)

USB -- STM32F103虚拟串口bulk传输讲解(三)

USB -- STM32F103自定义HID设备及HID上位机中断传输讲解(四)

USB -- STM32F103 U盘(MassStorage)SDIO接口SCSI协议Bulk传输讲解(五)

USB -- STM32F103 USB DFU设备固件升级(IAP)控制传输讲解(六)

USB -- STM32F103 USB AUDIO(音频)Speak同步传输(Out传输)讲解(七)

audio数据手册

前沿??

????????前面两节主要是对USB的基本概念做了简单讲解,学习USB的最本质目的还是要回到USB的应用方向,接下来的几章主要讲解USB的各类应用,包括:

????????这里只讲怎么修改描述符和关键函数,具体的讲解可以查看:USB -- STM32F103 USB AUDIO(音频)Speak同步传输(Out传输)讲解(七)

? ? ? ? 我们这里使用《Audio_Speaker》例程进行修改。

1 描述符修改

????????usb_desc.h文件的描述符宏定义如下:

#define MICROPHONE_SIZ_DEVICE_DESC                    18
#define MICROPHONE_SIZ_CONFIG_DESC                    109
#define MICROPHONE_SIZ_INTERFACE_DESC_SIZE            9

#define MICROPHONE_SIZ_STRING_LANGID                  0x04
#define MICROPHONE_SIZ_STRING_VENDOR                  0x26
#define MICROPHONE_SIZ_STRING_PRODUCT                 0x22
#define MICROPHONE_SIZ_STRING_SERIAL                  0x1A

#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE             0x09
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE            0x07
/* USB Descriptor Types */
#define USB_DEVICE_DESCRIPTOR_TYPE                    0x01
#define USB_CONFIGURATION_DESCRIPTOR_TYPE             0x02
#define USB_STRING_DESCRIPTOR_TYPE                    0x03
#define USB_INTERFACE_DESCRIPTOR_TYPE                 0x04
#define USB_ENDPOINT_DESCRIPTOR_TYPE                  0x05

#define USB_DEVICE_CLASS_AUDIO                        0x01
#define AUDIO_SUBCLASS_AUDIOCONTROL                   0x01
#define AUDIO_SUBCLASS_AUDIOSTREAMING                 0x02
#define AUDIO_PROTOCOL_UNDEFINED                      0x00
#define AUDIO_STREAMING_GENERAL                       0x01
#define AUDIO_STREAMING_FORMAT_TYPE                   0x02

/* Audio Descriptor Types */
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE               0x24
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE                0x25


/* Audio Control Interface Descriptor Subtypes */
#define AUDIO_CONTROL_HEADER                          0x01
#define AUDIO_CONTROL_INPUT_TERMINAL                  0x02
#define AUDIO_CONTROL_OUTPUT_TERMINAL                 0x03
#define AUDIO_CONTROL_FEATURE_UNIT                    0x06

#define AUDIO_INPUT_TERMINAL_DESC_SIZE                0x0C
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE               0x09
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE           0x07

#define AUDIO_CONTROL_MUTE                            0x0001

#define AUDIO_FORMAT_TYPE_I                           0x01

#define USB_ENDPOINT_TYPE_ISOCHRONOUS                 0x01
#define AUDIO_ENDPOINT_GENERAL                        0x01

#define RX_SIZE 92

1.1 设备描述符修改

const uint8_t Speaker_DeviceDescriptor[] =
{
    MICROPHONE_SIZ_DEVICE_DESC,          /* bLength */
    USB_DEVICE_DESCRIPTOR_TYPE,           /* bDescriptorType */
    0x00,          /* 2.00 */             /* bcdUSB */
    0x02,
    0x00,                                 /* bDeviceClass */
    0x00,                                 /* bDeviceSubClass */
    0x00,                                 /* bDeviceProtocol */
    0x40,                                 /* bMaxPacketSize 40 */
    0x83,                                 /* idVendor */
    0x04,
    0x30,                                 /* idProduct  = 0x5730*/
    0x57,
    0x00,          /* 2.00 */             /* bcdDevice */
    0x02,
    1,                                    /* iManufacturer */
    2,                                    /* iProduct */
    3,                                    /* iSerialNumber */
    0x01                                  /* bNumConfigurations */
};

?

1.2 配置描述符修改

? ? ? ? 这里包括:

  • 接口描述符
  • 功能描述符
  • 端点描述符
/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t Speaker_ConfigDescriptor[] =
{
    /* Configuration 1 */
    0x09,                                 /* bLength */
    USB_CONFIGURATION_DESCRIPTOR_TYPE,    /* bDescriptorType */
    0x6D,                                 /* wTotalLength  109 bytes*/
    0x00,
    0x02,                                 /* bNumInterfaces */
    0x01,                                 /* bConfigurationValue */
    0x00,                                 /* iConfiguration */
    0xC0,                                 /* bmAttributes Self Powered*/
    0x32,                                 /* bMaxPower = 100 mA*/
    /* 09 byte*/

    /* USB Microphone Standard interface descriptor */
    MICROPHONE_SIZ_INTERFACE_DESC_SIZE,      /* bLength */
    USB_INTERFACE_DESCRIPTOR_TYPE,        /* 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 */
    MICROPHONE_SIZ_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 */
    0x01,                                 /* bTerminalID */
    0x01,                                 /* wTerminalType AUDIO_TERMINAL_USB_STREAMING   0x0101 */
    0x02,
    0x00,                                 /* bAssocTerminal */
    0x01,                                 /* bNrChannels */
    0x00,                                 /* wChannelConfig 0x0000  Mono */
    0x00,
    0x00,                                 /* iChannelNames */
    0x00,                                 /* iTerminal */
    /* 12 byte*/

    /* USB Microphone Audio Feature Unit Descriptor */
    0x09,                                 /* bLength */
    AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
    AUDIO_CONTROL_FEATURE_UNIT,           /* bDescriptorSubtype */
    0x03,                                 /* bUnitID */
    0x01,                                 /* bSourceID */
    0x01,                                 /* bControlSize */
    AUDIO_CONTROL_MUTE,                   /* bmaControls(0) */
    0x00,                                 /* bmaControls(1) */
    0x00,                                 /* iTerminal */
    /* 09 byte*/

    /*USB Microphone Output Terminal Descriptor */
    0x09,      /* bLength */
    AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
    AUDIO_CONTROL_OUTPUT_TERMINAL,        /* bDescriptorSubtype */
    0x02,                                 /* bTerminalID */
    0x01,                                 /* wTerminalType  0x0101*/
    0x01,
    0x00,                                 /* bAssocTerminal */
    0x01,                                 /* bSourceID */
    0x00,                                 /* iTerminal */
    /* 09 byte*/

    /* USB Microphone Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth */
    /* Interface 1, Alternate Setting 0                                             */
    MICROPHONE_SIZ_INTERFACE_DESC_SIZE,  /* bLength */
    USB_INTERFACE_DESCRIPTOR_TYPE,        /* 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                                           */
    MICROPHONE_SIZ_INTERFACE_DESC_SIZE,  /* bLength */
    USB_INTERFACE_DESCRIPTOR_TYPE,        /* 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 */
    0x02,                                 /* bTerminalLink */
    0x01,                                 /* bDelay */
    0x02,                                 /* wFormatTag AUDIO_FORMAT_PCM  0x0001*/
    0x00,
    /* 07 byte*/

    /* USB Microphone Audio Type I Format Interface Descriptor */
    0x0B,                                 /* bLength */
    AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
    AUDIO_STREAMING_FORMAT_TYPE,          /* bDescriptorSubtype */
    AUDIO_FORMAT_TYPE_I,                  /* bFormatType */
    0x01,                                 /* bNrChannels */
    0x02,                                 /* bSubFrameSize */
    16,                                    /* bBitResolution */
    0x01,                                 /* bSamFreqType */
    0xF0,                                 /* tSamFreq 22000 = 0x55F0 */
    0x55,
    0x00,
    /* 11 byte*/

    /* Endpoint 1 - Standard Descriptor */
    AUDIO_STANDARD_ENDPOINT_DESC_SIZE,    /* bLength */
    USB_ENDPOINT_DESCRIPTOR_TYPE,         /* bDescriptorType */
    0x81,                                 /* bEndpointAddress 1 in endpoint*/
    USB_ENDPOINT_TYPE_ISOCHRONOUS,        /* bmAttributes */
    RX_SIZE / 2,                          /* wMaxPacketSize 44 bytes*/
    0x00,
    0x01,                                 /* 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*/
};

1.3 字符串描述符修改

????????这里只需要修改StringProduct字符串描述符,修改名称为microphone。

const uint8_t Speaker_StringProduct[SPEAKER_SIZ_STRING_PRODUCT] =
  {
    SPEAKER_SIZ_STRING_PRODUCT,  /* bLength */
    USB_STRING_DESCRIPTOR_TYPE,        /* bDescriptorType */
    'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, ' ', 0,
    'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'p', 0, 'h', 0, 'o', 0, 'n', 0, 'e', 0
  };

1.4 编译报错修改

? ? ? ? 发现修改了这些位置,会出现报错,我们继续修改,主要修改以下文件:

  • usb_desc.c
  • usb_desc.h
  • usb_prop.c

? ? ? ? 按照下图修改。

? ? ? ? 按照上图修改完成,在设备管理器会出现STM32 Microphone的设备,证明修改成功,如果修改之后设备管理器没有反应,大概率是D+的上拉电阻没有配对。

2 增加功能函数

2.1 Microphone功能模块介绍

? ? ? ? Microphone模块使用的是Adafruit公司的3421,可以直接去淘宝搜索关键词《Adafruit 3421》查找相应的模块进行购买。

2.2 增加Microphone初始化函数函数

? ? ? ? 此函数在main函数调用,目的是初始化I2S,因为Microphone模块是用I2S驱动的。

/*******************************************************************************
* Function Name  : I2S_GPIO_Config
* Description    : Initializes the GPIO pins used by the codec application.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Microphone_I2S_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    /* Enable GPIOB clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /* I2S2 SD, CK and WS pins configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*******************************************************************************
* Function Name  : I2S_Config
* Description    : Configure the I2S Peripheral.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Microphone_I2S_Config(void)
{
    I2S_InitTypeDef I2S_InitStructure;
    /* Enable I2S2 APB1 clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    /* Deinitialize SPI2 peripheral */
    SPI_I2S_DeInit(SPI2);
    /* I2S2 peripheral configuration */
    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterRx;
    I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
    I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_32b;
    I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
    I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_22k;
    I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
    I2S_Init(SPI2, &I2S_InitStructure);
    /* Disable the I2S2 RXNE Interrupt */
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
    /* Enable the SPI2/I2S2 peripheral */
    I2S_Cmd(SPI2, ENABLE);
}

? ? ? ? 并且屏蔽main函数的《Speaker_Config()》函数,修改之后的main函数如下:

/*******************************************************************************
* Function Name  : main.
* Description    : Main routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int main(void)
{
  Set_System();
  Set_USBClock();
  USB_Config();
  USB_Init();

  Microphone_I2S_GPIO_Config();
  Microphone_I2S_Config();

  while (1)
  {}
}

2.3 I2S中断函数修改

? ? ? ? 替换以前的I2S中断函数,改为下面的中断处理函数。

uint16_t Mic_Buff[RX_SIZE];  //RX_SIZE=92
uint16_t MIn_Data_Offset;
uint16_t MOut_Data_Offset;

/**
  * @brief  This function handles SPI2 global interrupt request.
  * @param  None
  * @retval None
  */
void SPI2_IRQHandler(void)
{
    if ((SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET))
    {
        if (MIn_Data_Offset > MOut_Data_Offset)
        {
            Mic_Buff[MOut_Data_Offset++] = SPI_I2S_ReceiveData(SPI2);     //高位在前
        }
    }
}

2.4 USB复位函数修改

extern uint16_t MIn_Data_Offset;
extern uint16_t MOut_Data_Offset;


/*******************************************************************************
* Function Name  : Speaker_Reset.
* Description    : Speaker reset routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Speaker_Reset()
{
    /* Set Microphone device as not configured state */
    pInformation->Current_Configuration = 0;
    /* Current Feature initialization */
    pInformation->Current_Feature = Speaker_ConfigDescriptor[7];
    SetBTABLE(BTABLE_ADDRESS);
    /* Initialize Endpoint 0 */
    SetEPType(ENDP0, EP_CONTROL);
    SetEPTxStatus(ENDP0, EP_TX_NAK);
    SetEPRxAddr(ENDP0, ENDP0_RXADDR);
    SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
    SetEPTxAddr(ENDP0, ENDP0_TXADDR);
    Clear_Status_Out(ENDP0);
    SetEPRxValid(ENDP0);
    /* Initialize Endpoint 1 */
    SetEPType(ENDP1, EP_ISOCHRONOUS);
    SetEPDblBuffAddr(ENDP1, ENDP1_BUF0Addr, ENDP1_BUF1Addr);
    SetEPDblBuffCount(ENDP1, EP_DBUF_IN, RX_SIZE / 2);
    ClearDTOG_RX(ENDP1);
    ClearDTOG_TX(ENDP1);
    ToggleDTOG_RX(ENDP1);
    SetEPRxStatus(ENDP1, EP_RX_DIS);
    SetEPTxStatus(ENDP1, EP_TX_NAK);
    SetEPRxValid(ENDP0);
    /* Set this device to response on default address */
    SetDeviceAddress(0);
    bDeviceState = ATTACHED;
    MIn_Data_Offset = RX_SIZE;
    MOut_Data_Offset = 0;
}

2.5 非零端点函数修改

? ? ? ? 因为这个是Microphone,是同步In传输,所以需要屏蔽OUT函数(usb_endp.c文件中),并增加In函数。

? ? ? ? 因为录制的语音会有点噪声,这里对一些尖锐的声音进行了简单的处理。

#include "usb_desc.h"
#include <string.h>

extern uint16_t Mic_Buff[RX_SIZE];  //RX_SIZE=92
extern uint16_t MIn_Data_Offset;
extern uint16_t MOut_Data_Offset;

void EP1_IN_Callback(void)
{
    uint16_t buff[RX_SIZE / 4];
    uint8_t i = 0, j = 0;

    /*录制麦克音频 ,88的原因是左右声道各占44*/
    for (i = 0; i < RX_SIZE / 4; i++)
    {
        //滤波
        while (Mic_Buff[j] <= 0xC000)
        {
            if (j >= MOut_Data_Offset)
            {
                break;
            }

            j++;
        }

        buff[i] = Mic_Buff[j];
        j++;
    }

    buff[RX_SIZE / 4 - 1] = buff[RX_SIZE / 4 - 2] = buff[RX_SIZE / 4 - 3];
    FreeUserBuffer(ENDP1, EP_DBUF_IN);

    if (GetENDPOINT(ENDP1) & EP_DTOG_TX)
    {
        UserToPMABufferCopy((uint8_t*)buff, ENDP1_BUF0Addr, RX_SIZE / 2);
        SetEPDblBuf0Count(ENDP1, EP_DBUF_IN, RX_SIZE / 2);
    }
    else
    {
        UserToPMABufferCopy((uint8_t*)buff, ENDP1_BUF1Addr, RX_SIZE / 2);
        SetEPDblBuf1Count(ENDP1, EP_DBUF_IN, RX_SIZE / 2);
    }

    SetEPTxValid(ENDP1);
    memset(Mic_Buff, 0, RX_SIZE);
    MIn_Data_Offset = RX_SIZE;
    MOut_Data_Offset = 0;
}

3 运行演示

1. 正确下载程序,能够在设备管理器查看到Microphone设备。

2. 打开音乐设置,选择侦听模式。

3. 此时如果外接喇叭或者佩戴耳机,能够听见麦克风传递的声音信息。通过逻辑分析仪抓取波形,查看到IN包数据也没有ACK回复。

接下来讲解STM32 USB VIDEO Camera(照相机)同步传输通信实验,敬请期待。。。

文章来源:https://blog.csdn.net/binhao002/article/details/135226191
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。