目錄
鏈接快速定位
前沿??
1 描述符講解
1.1 設(shè)備描述符
1.2 配置描述符
1.3 接口描述符
1.4 功能描述符
1.4.1?音頻控制接口描述符(AudioControl Interface Descriptors)
1.4.2?音頻流接口描述符(AudioStreaming Interface Descriptors)
1.4.3?音頻流端點(diǎn)描述符(AudioControl Endpoint Descriptors)
1.5 端點(diǎn)描述符
1.6 字符串描述符
2 關(guān)鍵函數(shù)講解
2.1 GPIO配置講解
2.2 非零端點(diǎn)函數(shù)講解
2.3 中斷函數(shù)講解--USB復(fù)位函數(shù)講解
2.4 主函數(shù)講解
3 運(yùn)行演示
鏈接快速定位
USB -- 初識USB協(xié)議(一)
源碼下載請參考鏈接:USB -- STM32-FS-USB-Device驅(qū)動代碼簡述(二)
USB -- STM32F103虛擬串口bulk傳輸講解(三)
USB -- STM32F103自定義HID設(shè)備及HID上位機(jī)中斷傳輸講解(四)
USB -- STM32F103 U盤(MassStorage)SDIO接口SCSI協(xié)議Bulk傳輸講解(五)
USB -- STM32F103 USB DFU設(shè)備固件升級(IAP)控制傳輸講解(六)
audio數(shù)據(jù)手冊
前沿??
????????前面兩節(jié)主要是對USB的基本概念做了簡單講解,學(xué)習(xí)USB的最本質(zhì)目的還是要回到USB的應(yīng)用方向,接下來的幾章主要講解USB的各類應(yīng)用,包括:
- 虛擬串口(環(huán)回測試)-- bulk傳輸(USB -- STM32F103虛擬串口bulk傳輸講解(三))
- 自定義HID -- 中斷傳輸(USB -- STM32F103自定義HID設(shè)備及HID上位機(jī)中斷傳輸講解(四))
- U盤 -- bulk傳輸(USB -- STM32F103 U盤(MassStorage)SDIO接口SCSI協(xié)議Bulk傳輸講解(五))
- 在線固件升級(DFU)-- 控制傳輸(USB -- STM32F103 USB DFU設(shè)備固件升級(IAP)控制傳輸講解(六))
- 語音錄制及播放 -- 同步傳輸(本章講解)
- 照相機(jī) -- 同步傳輸
- 復(fù)合設(shè)備 -- 中斷+bulk傳輸
????????主要還是帶領(lǐng)大家找相關(guān)的資料及相關(guān)的工具和代碼。
1 描述符講解
? ? ? ? 描述符是USB能夠正常通信的前提,沒有描述符,USB就不知道當(dāng)前是什么樣的設(shè)備,所以描述符在USB整個(gè)通信過程中占有十分重要的地位,所以這里重點(diǎn)講解一下USB的各類描述符。
? ? ? ? ST的例程為我們配置好了應(yīng)用的描述符,我們不需要關(guān)注也能正常運(yùn)行程序,但是我們這里講解一下怎么通過查找資料來知道具體描述符的含義。
1.1 設(shè)備描述符
? ? ? ? 以下是STM32F103系列的audio_speak的設(shè)備描述符代碼(每個(gè)字節(jié)對應(yīng)的含義可以在USB -- 初識USB協(xié)議(一)中查看):
const uint8_t Speaker_DeviceDescriptor[] =
{
SPEAKER_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 */
};
? ? ? ? 設(shè)備描述符顧名思義就是描述USB設(shè)備的基本信息,主要包括以下信息:
- USB版本號
- USB設(shè)備類型
- USB設(shè)備協(xié)議
- 端點(diǎn)0最大傳輸大小(最大64byte)
- 廠商向USBIF申請的VID(需付費(fèi),由芯片廠商提供)
- 設(shè)備PID(廠商自定義)
- 制造商的字符串描述符索引(描述生產(chǎn)這個(gè)產(chǎn)品的廠商)
- 產(chǎn)品的字符串描述符索引(描述是什么產(chǎn)品)
- 設(shè)備序號的字符串描述符索引(主要是芯片的UID)
- 配置的數(shù)量(一般為1)
? ? ? ? 設(shè)備類型可以通過USB官網(wǎng)Class查詢,我們這里是CDC設(shè)備,所以bDeviceClass=0x01,其他兩項(xiàng)任意填寫。
?
????????但實(shí)際這里的bDeviceClass=0x00,是因?yàn)?x00表示class可以在接口與描述符中定義。
?
????????制造商的字符串描述符索引、產(chǎn)品的字符串描述符索引和設(shè)備序號的字符串描述符索引主要是制造商、產(chǎn)品和設(shè)備序列號在字符串描述符的索引位置。
????????比如這里舉個(gè)例子,以下三個(gè)是字符串描述符,分別是制造商描述符、產(chǎn)品描述符和序列號描述符:
const uint8_t Speaker_StringVendor[SPEAKER_SIZ_STRING_VENDOR] =
{
SPEAKER_SIZ_STRING_VENDOR, /* Size of manufacturer string */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/
/* Manufacturer: "STMicroelectronics" */
'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
'c', 0, 's', 0
};
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,
'S', 0, 'p', 0, 'e', 0, 'a', 0, 'k', 0, 'e', 0, 'r', 0
};
uint8_t Speaker_StringSerial[SPEAKER_SIZ_STRING_SERIAL] =
{
SPEAKER_SIZ_STRING_SERIAL, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0
};
? ? 由下面代碼可知,他們的位置也是根據(jù)索引號排列的,所以主機(jī)請求index為1的描述符,那么設(shè)備就發(fā)送制造商描述符給主機(jī),告訴主機(jī)USB的制造商是什么。
ONE_DESCRIPTOR String_Descriptor[4] =
{
{(uint8_t*)Speaker_StringLangID, SPEAKER_SIZ_STRING_LANGID},
{(uint8_t*)Speaker_StringVendor, SPEAKER_SIZ_STRING_VENDOR},
{(uint8_t*)Speaker_StringProduct, SPEAKER_SIZ_STRING_PRODUCT},
{(uint8_t*)Speaker_StringSerial, SPEAKER_SIZ_STRING_SERIAL},
};
? ? ? ? 如果設(shè)備描述符的索引值修改了,那么String_Descriptor數(shù)組存放數(shù)據(jù)的順序也需要相應(yīng)的修改。
? ? ? ? VID可以通過USB官網(wǎng):USB_Members查看,比如這里的是ST的VID,0x0483的10進(jìn)制是1155,我們在USB官網(wǎng)查看,如下:
?
1.2 配置描述符
? ? ? ? 配置描述符顧名思義就是描述USB設(shè)備的配置信息,主要包括以下信息:
- USB接口的數(shù)量(會在接口描述符講解)
- USB的配置值(一般為1,根據(jù)設(shè)備描述符配置數(shù)量決定)
- USB的供電信息
- USB的最大電流
const uint8_t Speaker_ConfigDescriptor[] =
{
0x09, /* bLength */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
0x6D, /* wTotalLength 110 bytes*/
0x00,
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xC0, /* bmAttributes Self Powered*/
0x32, /* bMaxPower = 100 mA*/
}
1.3 接口描述符
? ? ? ? 這里的接口描述符有兩個(gè),由配置描述符指定個(gè)數(shù)。
? ? ? ? 第一個(gè)接口描述符是標(biāo)準(zhǔn)音頻控制接口描述符(Standard AudioControl Interface Descriptors)。
? ? ? ? 第二個(gè)接口描述符是標(biāo)準(zhǔn)音頻流接口描述符(Standard AudioStreaming Interface Descriptors),它又分為兩個(gè)子類:
- 備用設(shè)置0是一個(gè)零帶寬設(shè)置,用于在麥克風(fēng)未使用時(shí)放棄總線上要求的帶寬。這是通電后的默認(rèn)設(shè)置。通過指定接口的此備用設(shè)置沒有與其關(guān)聯(lián)的端點(diǎn)(bNumEndpoints=0)來實(shí)現(xiàn)零帶寬。此備用設(shè)置的描述符集合是為了減少標(biāo)準(zhǔn)接口描述符。
- 備用設(shè)置1是接口的操作設(shè)置。它包含標(biāo)準(zhǔn)和類特定的接口和端點(diǎn)描述符。
uint8_t Speak_InterfaceDescriptor[ ] =
{
/* USB Speaker Standard interface descriptor */
SPEAKER_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 */
。
。
。
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth */
/* Interface 1, Alternate Setting 0 */
SPEAKER_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 Speaker Standard AS Interface Descriptor - Audio Streaming Operational */
/* Interface 1, Alternate Setting 1 */
SPEAKER_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 */
}
?????????首先下載audio數(shù)據(jù)手冊,打開《audio10.pdf》文件,找到4.3.1小節(jié),這里有對接口描述符的全部解釋,由手冊可知,bInterfaceSubClass為Abstract Control Model,bInterfaceProtocol為Common AT commands,其它位也相同,查找手冊,找出對應(yīng)的解釋.
1.4 功能描述符
? ? ? ? USB功能描述符這里分為三個(gè)部分:
- 音頻控制接口描述符(AudioControl Interface Descriptors)
- 音頻流接口描述符(AudioStreaming Interface Descriptors)
- 音頻流端點(diǎn)描述符(AudioControl Endpoint Descriptors)
????????打開《audio10.pdf》文件,在4.3.2章節(jié)查看具體描述符的具體含義,這里不做詳細(xì)說明,音頻本身涉及的問題比較復(fù)雜,這里只是針對USB講解,不過多的講解音頻的具體協(xié)議。
1.4.1?音頻控制接口描述符(AudioControl Interface Descriptors)
uint8_t Speak_FunctionalDescriptor[ ] =
{
/* USB Speaker Class-specific AC Interface Descriptor */
SPEAKER_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 Speaker 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 */
0x01,
0x00, /* bAssocTerminal */
0x01, /* bNrChannels */
0x00, /* wChannelConfig 0x0000 Mono */
0x00,
0x00, /* iChannelNames */
0x00, /* iTerminal */
/* 12 byte*/
/* USB Speaker Audio Feature Unit Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */
0x02, /* bUnitID */
0x01, /* bSourceID */
0x01, /* bControlSize */
AUDIO_CONTROL_MUTE, /* bmaControls(0) */
0x00, /* bmaControls(1) */
0x00, /* iTerminal */
/* 09 byte*/
/*USB Speaker Output Terminal Descriptor */
0x09, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */
0x03, /* bTerminalID */
0x01, /* wTerminalType 0x0301*/
0x03,
0x00, /* bAssocTerminal */
0x02, /* bSourceID */
0x00, /* iTerminal */
/* 09 byte*/
}
1.4.2?音頻流接口描述符(AudioStreaming Interface Descriptors)
uint8_t Speak_FunctionalDescriptor[ ] =
{
/* USB Speaker Audio Streaming Interface Descriptor */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x01, /* bTerminalLink */
0x01, /* bDelay */
0x02, /* wFormatTag AUDIO_FORMAT_PCM8 0x0002*/
0x00,
/* 07 byte*/
/* USB Speaker 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 */
0x01, /* bSubFrameSize */
8, /* bBitResolution */
0x01, /* bSamFreqType */
0xF0, /* tSamFreq 22000 = 0x55F0 */
0x55,
0x00,
/* 11 byte*/
}
1.4.3?音頻流端點(diǎn)描述符(AudioControl Endpoint Descriptors)
uint8_t Speak_FunctionalDescriptor[ ] =
{
/* 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.5 端點(diǎn)描述符
? ? ? ? 這里用到1個(gè)端點(diǎn),具體的解釋可參見USB -- 初識USB協(xié)議(一)。
uint8_t Speak_EndpointDescriptor[ ] =
{
/* Endpoint 1 - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bEndpointAddress 1 out endpoint*/
USB_ENDPOINT_TYPE_ISOCHRONOUS, /* bmAttributes */
0x16, /* wMaxPacketSize 22 bytes*/
0x00,
0x01, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* 09 byte*/
}
1.6 字符串描述符
? ? ? ? 在設(shè)備描述符中已經(jīng)對制造商描述符、產(chǎn)品描述符和設(shè)備序號描述符做了說明,這里僅對語言ID描述符做簡單說明。
? ? ? ? 語言ID描述符相對很簡單,就是告訴主機(jī)用的哪種語言編碼,這里一般選擇0x0409,使用美國的編碼。一般使用最多的也是美國編碼。
/* USB String Descriptor (optional) */
const uint8_t Speaker_StringLangID[SPEAKER_SIZ_STRING_LANGID] =
{
0x04,
0x03,
0x09,
0x04
}
; /* LangID = 0x0409: U.S. English */
?
2 關(guān)鍵函數(shù)講解
2.1 GPIO配置講解
? ? ? ? 這里對USB的D+外部上拉電阻進(jìn)行了配置,如果讀者使用的開發(fā)板和ST官網(wǎng)的外部上拉不一致,需要修改這個(gè)位置的IO口定義。這里也需要注意,ST開發(fā)板使用的是PNP型三極管作為上拉電阻的使能信號,所以這里GPIO輸出低D+上拉。
?
?
?
2.2 非零端點(diǎn)函數(shù)講解
? ? ? ? 非0端點(diǎn)傳輸函數(shù)主要在“usb_endp.c”文件中實(shí)現(xiàn),我們打開usb_endp.c文件,看到只有1個(gè)函數(shù),因?yàn)槭荢peak,所以是OUT傳輸,并且同步傳輸不回ACK,類似于UDP協(xié)議。
?
2.3 中斷函數(shù)講解--USB復(fù)位函數(shù)講解
? ? ? ? USB復(fù)位函數(shù)十分的重要,因?yàn)樵赨SB主機(jī)識別到設(shè)備的時(shí)候,首先發(fā)出復(fù)位指令,USB設(shè)備收到復(fù)位指令之后,會去初始化一些使用到的端點(diǎn)(端點(diǎn)0必須初始化),然后再通過相應(yīng)的端點(diǎn)實(shí)現(xiàn)設(shè)備與主機(jī)間的通信。
? ? ? ? 下圖是利用DSVIEW抓取的USB枚舉過程的波形,每次在USB設(shè)備枚舉之前,都會產(chǎn)生一個(gè)復(fù)位信號。
?
? ? ? ? 下面代碼是USB復(fù)位信號來臨之后,USB所做的一些事情,主要就是初始化了端點(diǎn)的狀態(tài),為后續(xù)枚舉過程做準(zhǔn)備,這里把端點(diǎn)1配置為雙buffer模式,為了提高傳輸效率,后面有機(jī)會可以給大家講解。
/*******************************************************************************
* Function Name : Speaker_Reset.
* Description : Speaker reset routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Speaker_Reset()
{
/* Set Speaker 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_OUT, 0x40);
ClearDTOG_RX(ENDP1);
ClearDTOG_TX(ENDP1);
ToggleDTOG_TX(ENDP1);
SetEPRxStatus(ENDP1, EP_RX_VALID);
SetEPTxStatus(ENDP1, EP_TX_DIS);
SetEPRxValid(ENDP0);
/* Set this device to response on default address */
SetDeviceAddress(0);
bDeviceState = ATTACHED;
In_Data_Offset = 0;
Out_Data_Offset = 0;
}
2.4 主函數(shù)講解
? ? ? ? 主函數(shù)代碼相對簡單,就是實(shí)現(xiàn)了收到的數(shù)據(jù)然后發(fā)送出去和音頻芯片的初始化,初始化ST已經(jīng)為我們做好了,如果想進(jìn)一步了解需要自行下載AK4343芯片手冊,并查看相應(yīng)的寄存器位的功能,并配置,音頻芯片使用的是AK4343芯片。
/*******************************************************************************
* Function Name : main.
* Description : Main routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int main(void)
{
Set_System();
Set_USBClock();
USB_Config();
USB_Init();
Speaker_Config();
while (1)
{}
}
? ? ? ? 這里附圖一張ST官網(wǎng)的AK4343的原理圖。
? ? ? ? 但是經(jīng)過我們的實(shí)際測試,如果接耳機(jī),ST官網(wǎng)提供的原理圖是不能識別到聲音的,所以需要修改一下原理圖,修改的原理圖如下圖所示,主要修改了輸出聲道的串聯(lián)電容,把它去掉了。
3 運(yùn)行演示
1. 正確下載程序,能夠在設(shè)備管理器查看到Speak設(shè)備。
2. 打開音樂播放器,并且禁止所有增強(qiáng)效果。
3. 通過聲音屬性查看STM32 Speak正在播放音樂,并且邏輯分析儀住區(qū)波形也有數(shù)據(jù)(注意查看這里的OUT包沒有ACK應(yīng)答)。
4. 抓取USB波形每包數(shù)據(jù)為22字節(jié),這是因?yàn)樵O(shè)置的頻率是22000Hz,1個(gè)SOF是1ms,22000Hz就是1ms傳輸22個(gè)字節(jié),所以每個(gè)SOF傳輸是22字節(jié)。
?文章來源:http://www.zghlxwxcb.cn/news/detail-765088.html
接下來講解STM32 USB AUDIO Microphone同步傳輸(In傳輸)通信實(shí)驗(yàn),敬請期待。。。文章來源地址http://www.zghlxwxcb.cn/news/detail-765088.html
到了這里,關(guān)于USB -- STM32F103 USB AUDIO(音頻)Speaker同步傳輸(Out傳輸)講解(七)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!