1)实验平台:正点原子ESP32S3开发板
2)购买链接:https://detail.tmall.com/item.htm?id=768499342659
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-347618-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子手把手教你学ESP32S3快速入门视频教程:https://www.bilibili.com/video/BV1sH4y1W7Tc
6)正点原子FPGA交流群:132780729
第四十一章 音乐播放器实验
正点原子DNESP32S3开发板拥有串行音频接口(SAI),支持SAI、LSB/MSB对齐、PCM/DSP、TDM和AC’97等协议,且外扩了一颗HIFI级CODEC芯片:ES8388,支持最高192K 24BIT的音频播放,并且支持录音(下一章介绍)本章,我们将利用DNESP32S3开发板实现一个简单的音乐播放器(仅支持WAV播放)。
本章分为如下几个小节:
41.1 WAV&ES8388&SAI简介
41.2 硬件设计
41.3 程序设计
41.4 下载验证
41.1 WAV&ES8388&SAI简介
本章知识点比较多,包括:WAV、ES8388和SAI等三个知识点。下面我们将分别向大家介绍。
41.1.1 WAV简介
WAV即WAVE文件,WAV是计算机领域最常用的数字化声音文件格式之一,它是微软专门为Windows系统定义的波形文件格式(Waveform Audio),由于其扩展名为"*.wav"。它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITT A LAW 等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16 位量化数字,因此在声音文件质量和CD相差无几!
WAV一般采用线性PCM(脉冲编码调制)编码,本章,我们也主要讨论PCM的播放,因为这个最简单。
WAV 文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE Chunk、Format Chunk、 Fact Chunk(可选)和Data Chunk。每个Chunk由块标识符、数据大小和数据三部分组成,如图 41.1.1 所示:
图41.1.1 Chunk组成结构
对于一个基本的WAVE文件而言,以下三种Chunk是必不可少的:文件中第一个Chunk是RIFF Chunk,然后是FMT Chunk,最后是Data Chunk。对于其他的Chunk,顺序没有严格的限制。使用WAVE文件的应用程序必须具有读取以上三种chunk信息的能力,如果程序想要复制WAVE文件,必须拷贝文件中所有的chunk。本章,我们主要讨论PCM,因为这个最简单,它只包含3个Chunk,我们看一下它的文件构成,如图41.1.2。
图41.1.2 PCM格式的wav文件构成
可以看到,不同的Chunk有不同的长度,编码文件时,按照Chunk的字节和位序排列好之后写入文件头,加上wav的后缀,就可以生成一个能被正确解析的wav文件了,对于PCM结构,我们只需要把获取到的音频数据填充到Data Chunk中即可。我们将利用ES8388实现16位,8Khz采样率的单声道WAV录音(PCM格式)。
首先,我们来看看RIFF块(RIFF WAVE Chunk),该块以“RIFF”作为标示,紧跟wav文件大小(该大小是wav文件的总大小-8),然后数据段为“WAVE”,表示是wav文件。RIFF块的Chunk结构如下:
typedef __PACKED_STRUCT
- {
- uint32_t ChunkID; /* chunk id;这里固定为"RIFF",即0X46464952 */
- uint32_t ChunkSize; /* 集合大小;文件总大小-8 */
- uint32_t Format; /* 格式;WAVE,即0X45564157 */
- }ChunkRIFF; /* RIFF块 */
复制代码 接着,我们看看Format块(Format Chunk),该块以“fmt”作为标示(注意有个空格!),一般情况下,该段的大小为16个字节,但是有些软件生成的wav格式,该部分可能有18个字节,含有2个字节的附加信息。Format块的Chunk结构如下:
- typedef __PACKED_STRUCT
- {
- uint32_t ChunkID; /* chunk id;这里固定为"fmt ",即0X20746D66 */
- uint32_t ChunkSize ; /* 子集合大小(不包括ID和Size);这里为:20. */
- uint16_t AudioFormat; /* 音频格式;0X01,表示线性PCM;0X11表示IMA ADPCM */
- uint16_t NumOfChannels; /* 通道数量;1,表示单声道;2,表示双声道; */
- uint32_t SampleRate; /* 采样率;0X1F40,表示8Khz */
- uint32_t ByteRate; /* /字节速率; */
- uint16_t BlockAlign; /* 块对齐(字节); */
- uint16_t BitsPerSample; /* 单个采样数据大小;4位ADPCM,设置为4 */
- }ChunkFMT; /* fmt块 */
复制代码 接下来,我们再看看Fact块(Fact Chunk),该块为可选块,以“fact”作为标示,不是每个WAV文件都有,在非PCM格式的文件中,一般会在Format结构后面加入一个Fact块,该块Chunk结构如下:
- typedef __PACKED_STRUCT
- {
- uint32_t ChunkID; /* chunk id;这里固定为"fact",即0X74636166; */
- uint32_t ChunkSize ; /* 子集合大小(不包括ID和Size);这里为:4. */
- uint32_t NumOfSamples; /* 采样的数量; */
- }ChunkFACT; /* fact块 */
复制代码 DataFactSize是这个Chunk中最重要的数据,如果这是某种压缩格式的声音文件,那么从这里就可以知道他解压缩后的大小。对于解压时的计算会有很大的好处!不过本章我们使用的是PCM格式,所以不存在这个块。
最后,我们来看看数据块(Data Chunk),该块是真正保存wav数据的地方,以“data”作为该Chunk的标示,然后是数据的大小。数据块的Chunk结构如下:
- typedef __PACKED_STRUCT
- {
- uint32_t ChunkID; /* chunk id;这里固定为"data",即0X5453494C */
- uint32_t ChunkSize; /* 子集合大小(不包括ID和Size) */
- }ChunkDATA; /* data块 */
复制代码 ChunkSize后紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,wav数据的bit位置可以分成如表41.1.1.1所示的几种形式:
表41.1.1.1 WAVE文件数据采样格式
本章,我们播放的音频支持:16位和24位,立体声,所以每个取样为4/6个字节,低字节在前,高字节在后。在得到这些wav数据以后,通过SAI丢给ES8388,就可以欣赏音乐了。
41.1.2 ES8388简介
ES8388是上海顺芯推出的一款高性能、低功耗、高性价比的音频编解码器,有2个ADC通道和2个DAC通道,麦克风放大器,耳机放大器,数字音效以及模拟混合和增益功能组成。
ES8388的主要特性有:
●SAI接口,支持最高192K,24bit音频播放
●DAC信噪比96dB;ADC信噪比95dB
●支持主机和从机模式
●支持立体声差分输入/麦克风输入
●支持左右声道音量独立调节
●支持40mW耳机输出,无爆音
ES8388的控制通过I2S接口(即数字音频接口)同MCU进行音频数据传输(支持音频接收和发送),通过两线(CE=0/1,即IIC接口)或三线(CE脚产生一个下降沿,即SPI接口)接口进行配置。ES8388的SAI接口,由4个引脚组成:
ASDOUT:ADC数据输出
DSDIN:DAC数据输入
LRC:数据左/右对齐时钟
SCLK:位时钟,用于同步
ES8388可作为SAI主机,输出LRC和SLCK时钟,不过我们一般使用ES8388作为从机,接收LRC和SLCK。另外,ES8388的SAI接口支持4种不同的音频数据模式:左(MSB)对齐标准、右(LSB)对齐标准、飞利浦(SAI)标准、DSP/PCM。本章,我们用飞利浦标准来传输SAI数据。
飞利浦(SAI)标准模式,数据在跟随LRC传输的BCLK的第二个上升沿时传输MSB,其他位一直到LSB按顺序传输。传输依赖于字长、BCLK频率和采样率,在每个采样的LSB和下一个采样的MSB之间都应该有未用的BCLK周期。飞利浦标准模式的SAI数据传输协议如图41.1.2.1所示:
图41.1.2.1 飞利浦标准模式SAI数据传输图
图中,fs即音频信号的采样率,比如44.1Khz,因此可以知道,LRC的频率就是音频信号的采样率。另外,ES8388还需要一个MCLK,本章我们采用DNESP32S3为其提供MCLK时钟,MCLK的频率必须等于256fs,也就是音频采样率的256倍。
ES8388的框图如图41.1.2.2所示:
图41.1.2.2 ES8388框图
从上图可以看出,ES8388内部有很多的模拟开关,用来选择通道,同时还有一些运放调节器,用来设置增益和音量。
本章,我们通过IIC接口(CE=0)连接ES8388,ES8388的IIC地址为:0X10。关于ES8388的IIC详细介绍,请看其数据手册第10页5.2节。
这里我们简单介绍一下要正常使用ES8388来播放音乐,应该执行哪些配置。
1,寄存器R0(00h),是芯片控制寄存器1,需要用到的位有:最高位SCPRese(bit7)用于控制ES8388的软复位,写0X80到该寄存器地址,即可实现软复位ES8388,复位后,再写0X00,ES8388恢复正常。VMIDSEL[1:0]位用于控制VMID(校正噪声用),我们一般设置为10,即用500KΩ校正。
2,寄存器R1(01h),是芯片控制寄存器2,主要要设置PdnAna(bit3),该位设置为1,模拟部分掉电,相当于复位模拟部分;设置为0,模拟部分才会工作,才可以听到声音。
3,寄存器R2(02h),是芯片电源管理控制寄存器,所有位都要用到:adc_DigPDN(bit7)和dac_DigPDN(bit6)分别用于控制ADC和DAC的DSM、DEM、滤波器和数字接口的复位,1复位,0正常;adc_stm_rst(bit5)和dac_stm_rst(bit4)分别用于控制ADC和DAC的状态机掉电,1掉电,0正常;ADCDLL_PDN(bit3)和DACDLL_PDN(bit2)分别用于控制ADC和DAC的DLL掉电,停止时钟,1掉电,0正常;adcVref_PDN(bit1)和dacVref_PDN(bit0)分别控制ADC和DAC的模拟参考电压掉电,1掉电,0正常;因此想要ADC和DAC都正常工作,R2寄存器必须全部设置为0,否则ADC或者DAC就会不能正常工作。
4,寄存器R3(03h),是ADC电源管理控制寄存器,需要用到的位有:PdnAINL(bit7)和PdnAINR(bit6)用于控制左右输入模拟通道的电源,1掉电,0正常;PdnADCL(bit5)和PdnADCR(bit4)用于控制左右通道ADC的电源,1掉电,0正常;pdnMICB(bit3)用于控制麦克风的偏置电源,1掉电,0正常;PdnADCBiasgen(bit2)用于控制偏置电源的产生,1掉电,0正常;这里6个位,我们全部设置为0,ADC部分就可以正常工作了。
5,寄存器R4(04h),是DAC电源管理控制寄存器,需要用到的位有:PdnDACL(bit7)和PdnDACR(bit6)分别用于左右声道DAC的电源控制,1掉电;0正常;LOUT1(bit5)和ROUT1(bit4)分别用于控制通道1的左右声道输出是能,1使能,0禁止;LOUT2(bit3)和ROUT2(bit2)分别用于控制通道2的左右声道输出是能,1使能,0禁止;我们一般设置PdnDACL和PdnDACR为0,使能左右声道DAC,另外,两个输出通道则根据自己的需要设置。
6,寄存器R8(08h),是主模式控制寄存器,需要用到的位有:MSC(bit7)用于控制接口模式,0从模式,1主模式;MCKDIV2(bit6)用于控制MCLK的2分频,0不分频,1二分频;BCLK_INV(bit5)用于控制BCLK的反相,0不反相;1,反相;一般设置这3个位都为0。
7,寄存器R9(09h),是ADC控制寄存器1,所有位都要用到:MicAmpL(bit7:4)和MicAmpR(bit3:0),这两个分别用于控制MIC的左右通道增益,从0开始,3dB一个档,最大增益为24dB,我们一般设置MicAmpR/L[3:0]=1000,即24dB。
8,寄存器R10(0Ah),是ADC控制寄存器2,需要用到的位有:LINSE(bit7:6)和RINSE(bit5:4)分别选择左右输入通道,0选择通道1,1选择通道2。
9,寄存器R12(0Ch),是ADC控制寄存器4,全部位都要用到:DATSEL(bit7:6)用于选择数据格式,一般设置为01,左右边数据等于左右声道ADC数据;ADCLRP(bit5)在I2S模式下用于设置数据对其方式,一般设置为0,正常极性;ADCWL(bit4:2)用于选择数据长度,我们设置011,选择16位数据长度;ADCFORMAT(bit1:0)用于设置ADC数据格式,一般设置为00,选择I2S数据格式。
10,寄存器R13(0Dh),是ADC控制寄存器5,全部位都要用到:ADCFsMode(bit7)用于设置Fs模式,0单速模式,1双倍速模式,一般设置为0;ADCFsRatio(bit4:0)用于设置ADC的MCLK和FS的比率,我们设置00010,即256倍关系。
11,寄存器R16(10h)和R17(11h),这两个寄存器分别用于控制ADC左右声道的音量衰减,LADCVOL(bit7:0)和RADCVOL(bit7:0)分别控制左声道和右声道ADC的衰减,0.5dB每步,我们一般设置为0,即不衰减。
12,寄存器R18(12h),是ADC控制寄存器10,全部位都要用到:ALCSEL(bit7:6)用于控制ALC,00表示ALC关闭,01表示ALC仅控制左声道,10表示ALC仅控制右声道11表示ALC立体声控制;我们一般设置为11。
13,寄存器R23(17h),是DAC控制寄存器1,需要用到的位有:DACLRSWAP(bit7)用于控制左右声道数据交换,0正常,1互换,一般设置为0;DACLRP(bit6) 在I2S模式下用于设置数据对其方式,一般设置为0,正常极性;DACWL(bit5:3)用于选择数据长度,我们设置011,选择16位数据长度;ADCFORMAT(bit1:0)用于设置DAC数据格式,一般设置为00,选择I2S数据格式。
14,寄存器R24(18h),是DAC控制寄存器2,全部位都要用到:DACFsMode(bit7)用于设置Fs模式,0单速模式,1双倍速模式,一般设置为0;DACFsRatio(bit4:0)用于设置DAC的MCLK和FS的比率,我们设置00010,即256倍关系。
15,寄存器R26(1Ah)和R27(1Bh),这两个寄存器分别用于控制DAC左右声道的音量衰减,LDACVOL(bit7:0)和RDACVOL(bit7:0)分别控制左声道和右声道DAC的衰减,0.5dB每步,0表示0dB衰减,192表示96dB衰减;通过这两个寄存器可以完成输出音量的调节。
16,寄存器R29(1Dh),是DAC控制寄存器7,需要用到的位有:ZeroL(bit7)和ZeroR(bit6)分别控制左右声道的全0输出,类似静音,1输出0,0正常;一般设置为0。Mono(bit5)用于单声道控制,0立体声,1单声道;一般设置为0。SE(bit4:2)用于设置3D音效,0~7表示3D效果的强弱,0表示关闭。
17,寄存器39(27h)和42(2Ah),分别控制DAC左右通道的混音器,LD2LO(bit7)和RD2RO(bit7)分别控制左右DAC的混音器开关,0关闭,1开启,需设置为1;LI2LO(bit6)和RI2RO(bit6)分别控制左右输入通道的混音器开关,0关闭,1开启,一般设置为1;LI2LOVOL(bit5:3)和RI2ROVOL(bit5:3)分别控制左右输入通道的增益,0~7表示-6 ~ -15dB的增益调节范围,默认设置为111,即-15dB。
18,寄存器43(2Bh),是DAC控制寄存器21,这里我们只关心slrck(bit7)这个位,用于控制DACLRC和ADCLRC是否共用,我们设置为1,表示共用。
以上,就是我们使用ES8388时所需要用到的一些寄存器,按照以上所述,对各个寄存器进行相应的配置,即可使用ES8388正常播放音乐了。关于ES8388更详细的寄存器设置说明,我们这里就不再介绍了,请大家参考ES8388的数据手册自行研究。
41.1.3 I²S控制器介绍
I²S(Inter-IC Sound,集成电路内置音频总线)是一种同步串行通信协议,通常用于两个数字音频设备之间传输音频数据。DNESP32S3内置两个I²S接口(I²S0和I²S1),为多媒体应用,尤其是为数字音频应用提供了灵活的数据通信接口。
I²S标准总线定义了三种信号:串行时钟信号BCK、字选择信号WS和串行数据信号SD。一个基本的I²S数据总线有一个主机和一个从机。主机和从机的角色在通信过程中保持不变。DNESP32S3的I²S模块包含独立的发送单元和接收单元,能够保证优良的通信性能。
I²S有如下功能:
主机模式:I²Sn作为主机,BCK/WS向外部输出,向从机发送或从其接收数据。
从机模式:I²Sn作为从机,BCK/WS从外部输入,从主机接收或向其发送数据。
全双工:主机与从机之间的发送线和接收线各自独立,发送数据和接收数据同时进行。
半双工:主机和从机只能有一方先发送数据,另一方接收数据。发送数据和接收数据不能同时进行。
TDM RX模式:利用时分复用方式接收脉冲编码调制(PCM)数据,并将其通过DMA存入储存器的模式。信号线包括
BCK、WS和DATA。可以接收最多16个通道的数据。通过用户配置,可支持TDM Philips格式、TDM MSB对齐格式、TDM PCM格式等。
PDM RX模式:接收脉冲密度调制(PDM)数据,并将其通过DMA存入储存器的模式。信号线包括WS和DATA。通过用户配置,可支持PDM标准格式等。
TDM TX模式:通过DMA从储存器中取得脉冲编码调制(PCM)数据,并利用时分复用方式将其发送的模式。信号线包括BCK、WS和DATA,可以发送最多16个通道的数据。通过用户配置,可支持TDM Philips格式、TDM MSB对齐格式、TDM PCM格式等。
PDM TX模式:通过DMA从储存器中取得脉冲密度调制(PDM)数据,并将其发送的模式。信号线包括WS和DATA。通过用户配置,可支持PDM标准格式等。
PCMtoPDM TX模式(仅对I²S0有效):通过DMA从储存器中取得脉冲编码调制(PCM)数据,将其转换为脉冲密度调制(PDM)数据,并将其发送的主机模式。信号线包括WS和DATA。通过用户配置,可支持PDM标准格式等。
PDMtoPCM RX模式(仅对I²S0有效):接收脉冲密度调制(PDM)数据,将其转换为脉冲编码调制(PCM)数据,并将其通过DMA存入储存器的主机模式或从机模式。信号线包括WS和DATA。通过用户配置,可支持PDM标准格式等。
|