《DNESP32P4开发指南_V1.0》第四十三章 音乐播放器实验(上)

第四十三章 音乐播放器实验

正点原子DNESP32P4开发板配备了三个HP系统的全双工I2S接口和一个LP系统的双工低功耗I2S接口,此外,还外接了一颗HIFI级音频编解码芯片——ES8388,支持最高192KHz 24位的音频播放。该开发板不仅支持高质量的音频播放,还具备音频录制功能(将在下一章详细介绍)。本章将带领读者利用DNESP32P4开发板实现一个简单的音乐播放器,目前仅支持WAV格式的播放。
本章分为如下几个小节:
43.1 WAV&ES8388&I2S简介
43.2 硬件设计
43.3 程序设计
43.4 下载验证

43.1 WAV&ES8388&I2S简介
本节将介绍本章的几个关键知识点,包括WAV格式、ES8388音频编解码器和I2S接口。下面逐一介绍这三个重要概念。

43.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 Chunk、Format Chunk、 Fact Chunk(可选)和Data Chunk。每个Chunk由块标识符、数据大小和数据三部分组成,如下图所示:

image002

图43.1.1.1 Chunk组成结构

一个基本的WAVE文件包含三种必备的Chunk:RIFF Chunk、FMT Chunk 和 Data Chunk。如下图所示。

image003

图43.1.1.2 PCM格式的wav文件构成

上图展示了WAV文件的基本必备Chunk,除了这些必备的Chunk,还有其他可选的Chunk。值得注意的是,虽然这些其他Chunk的顺序并没有严格的限制,但其中一个特别需要关注的可选Chunk 是Fact Chunk。Fact Chunk通常用于非PCM编码格式的WAV 文件,提供音频的额外信息。接下来,笔者将使用十六进制编辑器打开WAV文件,逐一分析各个Chunk的内容和作用,帮助读者更深入地理解WAV文件的结构和数据存储方式。

1,RIFF Chunk,共12字节
RIFF Chunk 是WAV文件的根Chunk,它定义了文件的基本类型。RIFF是“Resource Interchange File Format”的缩写,用于标识这是一个基于RIFF格式的文件。下图为十六进制编辑器解析RIFF Chunk的数据。

image005

图43.1.1.3 RIFF Chunk数据

在上图中,RIFF Chunk 占据了文件的前 12 字节。下面表格展示了这 12 字节的字段内容及其说明。

QQ截图20260813101021

表43.1.1.1 RIFF chunk字段描述

从上表可以得知,所解析的WAV文件总大小为37199220 + 8,即37199228字节。该文件通过Chunk ID字段标识为“RIFF”格式,并通过Format字段标注为WAV文件(“WAVE”)。

2,Format Chunk,共24~26字节
Format Chunk(通常标识为 “fmt ”)描述了音频数据的格式,包括采样率、比特深度、声道数等。下图为十六进制编辑器解析Format Chunk的数据。

image007

图43.1.1.4 Format Chunk数据

在上图中,Format Chunk位于RIFF Chunk的后方,占据24字节。下表展示了这24字节的字段内容及其说明。

QQ截图20260813101031

表43.1.1.2 Format chunk字段描述

从上表中可以看到,该WAV文件采用PCM音频格式,声道数为2(即立体声),采样率为44100Hz,且每个样本的位数为16位。这些信息表明该文件存储的是标准的CD质量音频数据。值得注意的是,有些软件生成的wav格式,该部分可能有18个字节,含有2个字节的附加信息,具体大小请看Format Size字段。

3,Fact Chunk可选块,共12字节
Fact Chunk(0X74636166)是一个可选的Chunk,通常用于非PCM编码格式的WAV文件(例如压缩音频格式)。它提供额外的元数据,例如压缩音频格式的附加信息或其他特定的音频数据。如果WAV文件使用的是PCM编码格式,则通常不需要Fact Chunk。在本章节中,解析的WAV文件未包含Fact Chunk,因此我们在这里不再对其进行详细讲解。

4,Data Chunk,共N字节
Data Chunk包含实际的音频样本数据,是音频播放的核心数据内容。下图为十六进制编辑器解析Data Chunk的数据。

image009

图43.1.1.5 Data Chunk数据

在上图中,Data Chunk位于Format Chunk的后方(若有Fact Chunk,则Data Chunk位于Fact Chunk的后方),占据N字节。下表展示了这N字节的字段内容及其说明。

QQ截图20260813101039

表43.1.1.2 Data Chunk字段描述

从上表中可以看到,WAV文件的数据大小为37198936字节。要获取音频数据,我们需要偏移到Data Chunk块的起始位置,这个位置可以通过偏移到文件的0x80地址来访问。此时,我们可以开始读取WAV音频数据并将其通过I2S接口进行发送。
下面是笔者以数据结构体的形式对上述各个Chunk进行描述。每个结构体代表一个Chunk,包含该Chunk的字段信息及其数据类型,帮助读者更清晰地理解各个Chunk的结构。
首先,我们来看看RIFF块(RIFF WAVE Chunk),该块以“RIFF”作为标示,紧跟wav文件大小(该大小是wav文件的总大小-8),然后数据段为“WAVE”,表示是wav文件。RIFF块的Chunk结构如下:

typedef 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 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 */
//    uint16_t ByteExtraData;   /* 附加的数据字节;2个; 线性PCM,没有这个参数 */
} ChunkFMT;                     /* fmt块 */

然后,我们再看看Fact块(Fact Chunk),该块为可选块,以“fact”作为标示,不是每个WAV文件都有,在非PCM格式的文件中,一般会在Format结构后面加入一个Fact块,该块Chunk结构如下:

typedef struct 
{
    uint32_t ChunkID;           /* chunk id;这里固定为"fact",即0X74636166 */
    uint32_t ChunkSize;         /* 子集合大小(不包括ID和Size);这里为:4 */
    uint32_t NumOfSamples;      /* 采样的数量 */
} ChunkFACT;                    /* fact块 */

最后,我们来看看数据块(Data Chunk),该块是真正保存wav数据的地方,以“data”作为该Chunk的标示,然后是数据的大小。数据块的Chunk结构如下:

typedef struct
{
    uint32_t ChunkID;           /* chunk id;这里固定为"data",即0X5453494C */
    uint32_t ChunkSize;         /* 子集合大小(不包括ID和Size) */
} ChunkDATA;                    /* data块 */

ChunkSize后紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,wav数据的bit位置可以分成如下表所示的几种形式:

QQ截图20260813101053

表43.1.1.3 WAVE文件数据采样格式

本章,我们播放的音频支持:16位和24位,立体声,所以每个取样为4/6个字节,低字节在前,高字节在后。在得到这些wav数据以后,通过I2S传输给ES8388,就可以欣赏音乐了。

43.1.2 ES8388简介
ES8388音频编解码器是上海顺芯推出的一款高性能、低功耗、性价比高的音频编解码器,具备丰富的功能,如2个ADC通道、2个DAC通道、麦克风放大器、耳机放大器、数字音效处理、模拟混合与增益控制等。

1,ES8388的主要特性
 I2S接口:支持最高96kHz采样率和24bit音频播放。
 DAC信噪比:96dB,ADC信噪比:95dB。
 工作模式:支持主机模式和从机模式。
 支持立体声差分输入和麦克风输入。
 支持左右声道音量独立调节。
 支持40mW耳机输出,确保没有爆音现象。

2,音频数据传输与控制
I2S接口:ES8388通过I2S接口(即数字音频接口)与MCU进行音频数据传输,支持音频接收和发送。
配置接口:通过两线接口(CE=0/1,即I2C接口)或三线接口(CE脚产生一个下降沿,即SPI接口)进行配置。

3,ES8388的I2S接口
I2S接口由4个引脚组成,分别为:
 ASDOUT:ADC数据输出。
 DSDIN:DAC数据输入。
 LRC:数据左/右对齐时钟。
 SCLK:位时钟,用于同步音频数据的传输。
 MCLK:提供从机ES8388参考时钟。

4,主机/从机模式
ES8388可作为I2S接口的主机,输出LRC和SCLK时钟。然而,在大多数应用中,ES8388作为从机接收LRC和SCLK时钟信号。

5,音频数据模式
ES8388的I2S接口支持4种不同的音频数据模式:
 左(MSB)对齐标准。
 右(LSB)对齐标准。
 飞利浦(I2S)标准。
 DSP/PCM模式。

6,飞利浦(I2S)标准模式
在飞利浦(I2S)标准模式下,数据通过跟随LRC的BCLK的第二个上升沿传输MSB(最高有效位),之后的数据按顺序依次传输,直到LSB(最低有效位)。这种传输方式的具体协议依赖于字长、BCLK频率和采样率。每个采样的LSB与下一个采样的MSB之间应有一个未用的BCLK周期,用于同步和时序的调整。飞利浦标准模式的I2S数据传输协议如下图所示:

image005

图43.1.2.1 飞利浦标准模式I2S数据传输图

图中,fs即音频信号的采样率,比如44.1Khz,因此可以知道,LRC的频率就是音频信号的采样率。另外,ES8388还需要一个MCLK,本章我们采用ESP32-P4为其提供MCLK时钟,MCLK的频率必须等于256fs,也就是音频采样率的256倍。
ES8388的框图如下图所示:

image013

图43.1.2.2 ES8388框图

从上图可以看出,ES8388内部有很多的模拟开关,用来选择通道,同时还有一些运放调节器,用来设置增益和音量。
本章,我们通过IIC接口(CE=0)连接ES8388,ES8388的IIC地址为:0X10。关于ES8388的IIC详细介绍,请看《ES8388-DS》数据手册第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的数据手册自行研究。

43.1.3 I2S简介
I2S(Inter-IC Sound)是一种用于数字音频设备之间传输音频数据的串行通信协议,广泛应用于音频数据的传输,如在DSP(数字信号处理器)、DAC(数模转换器)、ADC(模数转换器)及其他音频处理单元之间的数据交换。ESP32-P4的I2S模块集成了多功能的音频传输接口,支持多种音频数据格式和采样率,适用于音频录制、回放、音频处理等应用。
ESP32-P4的HP系统集成了三个I2S接口:I2S0、I2S1和I2S2和LP系统的一个低功耗I2S接口。这些接口为多媒体应用中的数字数据流传输提供了灵活的通信方式,尤其适用于数字音频应用。I2S协议常用于数字音频设备之间的数据传输,使ESP32-P4能够高效支持各种音频相关的应用。
1,I2标准总线有三个主要信号:
1)位时钟(BCK):位时钟用于同步设备之间的数据传输速率,定义了I2S总线上传输数据位的速度。
2)字选择(WS):该信号也称为通道选择信号,用于区分传输的数据是左声道还是右声道,从而实现立体声音频传输。
3)串行数据(SD):此线路以串行位流的形式传输实际的音频数据。
4)主时钟线(MCLK):该信号线可选,具体取决于从机,用于向 I2S 从机提供参考时钟。
在基本的I2S总线配置中,包含一个主设备和一个从设备。主设备生成BCK和WS信号,控制通信的时序,从设备则遵循主设备的时序。这种主从关系在整个通信过程中保持不变ESP32-P4的I2S模块设计有独立的发送(TX)和接收(RX)单元,支持高性能的同时数据传输和接收。
2,ESP32-P4的I2S模块特性
1)主模式和从模式:支持I2S设备作为主设备或从设备进行通信。
2)全双工和半双工通信:支持数据的双向传输,可以在同一时间发送和接收数据。
3)独立的 TX和RX单元:可以独立工作或同时工作,提高数据处理的灵活性。
4)支持多种音频标准:
 TDM Philips标准
 TDM MSB对齐标准
 TDM PCM标准
 PDM 标准
5)支持多种TX/RX模式:
 TDM TX模式:支持最多16个通道
 TDM RX模式:支持最多16个通道
 PDM TX模式:原始 PDM 数据传输和PCM 转 PDM 数据格式转换(仅支持 I2S0),最多支持 2 个通道
6)PDM RX模式
 原始PDM数据接收
 PDM转PCM数据格式转换(仅支持 I2S0),最多支持 8 个通道
7)可配置的APLL时钟:频率最高可达240 MHz。
8)可配置的高精度采样时钟:支持多种采样频率。
9)8/16/24/32位数据宽度:支持多种数据宽度,以满足不同的数据精度需求。
10)TX模式下的同步计数器:确保数据传输的同步性。
11)ETM特性:扩展了数据的传输能力。
12)直接内存访问(仅支持GDMA-AHB):提供高效的数据传输。
13)标准I2S接口中断:便于实时数据处理。

43.1.3.1 I2S硬件架构与工作原理
ESP32-P4 I2Sn模块的结构如下图所示。

image015

图43.1.3.1.1 ESP32-P4 I2Sn框架图

上图展示了ESP32-P4 I2S模块(I2Sn)的架构,包含多个关键部件,以支持音频数据的传输和接收。具体描述如下:
1,时钟生成器(Clock Generator)
用于生成I2S模块的时钟信号,支持XTAL(晶振)、APLL(音频锁相环)以及外部MCLK输入,灵活调整时钟源,以满足不同的采样率和传输速率需求。
2,GDMA支持
I2S模块可以通过GDMA控制器直接访问内部存储器,以实现高效的数据处理,详细内容可参考《ESP32-P4技术参考手册》的GDMA控制器章节。
3,压缩/解压缩单元
支持A-law和μ-law音频压缩/解压功能,适用于语音数据压缩需求,从而有效地降低传输带宽要求,提高数据传输效率。
4,发送和接收FIFO缓冲区
用于生成I2S模块的时钟信号,支持XTAL(晶振)、APLL(锁相环)以及外部MCLK输入,灵活调整时钟源,以满足不同的采样率和传输速率需求。
5,发送(TX)和接收(RX)单元
发送控制单元(TX Unit):负责将音频数据从TX FIFO缓冲区传输到外部设备。它支持传统TDM(时分复用)格式和PDM(脉冲密度调制)格式,还内置了一个PCM(脉冲编码调制)到PDM的转换器,以实现多种音频编码的兼容性。
接收控制单元(RX Unit):从外部设备接收音频数据并存储到RX FIFO缓冲区。与TX单元相似,RX单元也支持TDM和PDM格式,并配有PDM到PCM的转换器,能够处理不同编码格式的音频信号。
6,GPIO矩阵(I/O Sync)
确保I2S的输入和输出信号同步。在主模式下,该单元会生成时钟信号(如BCK、WS),在从模式下则接收外部时钟信号以进行同步。这种设计使I2S模块能够作为主设备或从设备运行,灵活适应不同的应用场景。I2S信号可以通过高性能GPIO矩阵(HP GPIO Matrix)映射到芯片的特定引脚,相关内容请参考《ESP32-P4技术参考手册》的GPIO矩阵和IO MUX章节
通过这些模块的协同工作,ESP32-P4的I2S接口可以在高效处理和传输音频数据的同时,支持多种数据格式(如PCM、PDM),满足语音、音乐等多种应用场景的需求。
下面,笔者将重点讲解时钟生成器(Clock Generator)如何为TX/RX模块提供所需的时钟。具体内容请参见下图。

image017

图43.1.1.2 I2Sn时钟生成器

上图详细描述了ESP32-P4的I2S时钟生成模块的工作原理。以下是该模块的主要总结:
1)时钟源选择
I2S模块的TX(发送)和RX(接收)时钟可以从多个时钟源中选择,以确保与系统的时序需求匹配。时钟源包括系统的40 MHz晶体时钟(XTAL_CLK)、音频锁相环(APLL_CLK)时钟以及外部输入的MCLK信号(I2Sn_MCLK_in)。其中,XTAL_CLK适用于大多数标准时序要求,APLL_CLK则提供了可调频率的优势,适合高保真音频应用,而I2Sn_MCLK_in则用于需要外部同步的场景。通过配置 HP_SYS_CLKRST_I2Sn_TX/RX_CLK_SRC_SEL 和 HP_SYS_CLKRST_I2S0_TX/RX_CLK_EN 寄存器,用户可以灵活地选择TX和RX的时钟源,确保数据传输的精确性和稳定性。
2)分频器配置
I2S模块的TX和RX主时钟(分别为I2Sn_TX_CLK和I2Sn_RX_CLK)是通过所选时钟源经过分频器生成的。主时钟频率fI2Sn_CLK_S,也就是上图讲解的三个时钟源其中一个,通过以下公式计算:

image019

其中,𝑁是一个整数分频值,范围为2到256,用户可以通过配置 HP_SYS_CLKRST_I2Sn_TX/RX_DIV_N 寄存器来设置。参数𝑎和𝑏则用于配置分数分频器(fractional divider),通过精细调节这些值,可以实现更高精度的频率设置,从而满足特定应用的时钟要求。
3)串行时钟(BCK)生成
I2S模块的TX和RX串行时钟(分别为 I2SnO_BCK_out 和 I2SnI_BCK_out)是通过主时钟 I2Sn_TX_CLK 和 I2Sn_RX_CLK 进一步分频生成的。发送BCK频率的计算公式如下:

image021

其中,MO是一个整数值,通过I2Sn_TX_BCK_DIV_NUM配置,且需确保𝑀𝑂≠1。接收BCK频率的计算方式类似,MI为I2Sn_RX_BCK_DIV_NUM寄存器数值+1,同样它不允许为1。这些分频设置使得可以精确调整串行时钟频率,以适应不同的音频数据传输需求。
4)I2Sn_MCLK输出
在I2S主模式下,I2Sn模块可以输出主时钟(I2Sn_MCLK_out)作为外设的时钟源,用于同步外围设备的操作。
通过上述配置和分频设计,ESP32-P4的I2S时钟生成器可以灵活地选择时钟源并生成适合的时钟信号,以适应不同的音频采样率和传输速率要求。这些模块的协同工作增强了ESP32-P4在音频处理方面的灵活性和兼容性。

43.1.3.2 I2S驱动文件调用结构
在ESP32-P4的开发中,I2S(Inter-IC Sound)接口驱动提供了多种通信模式,包括标准模式、PDM模式和TDM模式,以适应不同的音频应用需求。I2S驱动的文件结构和调用关系经过精心设计,以支持多种应用场景,提供了新旧两套API供用户选择使用。
为了兼容已有的I2S驱动应用,同时提供更灵活和高效的音频处理能力,ESP-IDF框架中实现了原有的I2S驱动和新驱动。用户可以基于需求选择适合的API接口,但需要注意的是,原有驱动与新驱动无法共存。在开发过程中,用户应根据项目需求选择合适的头文件,选择适合的通信模式,并依赖正确的头文件结构来确保应用的稳定性和兼容性。I2S驱动文件结构分为公共头文件、私有头文件和源文件三部分。公共头文件主要向应用程序提供API接口,私有头文件则主要用于驱动内部调用。整个结构的模块化设计使得代码维护和扩展更为方便,帮助开发者更快地集成I2S功能。下图为I2S 文件结构

image023

图43.1.3.2.1 I2S 文件结构

上图展示了I2S文件结构和各文件的依赖关系。以下是对文件结构的说明:
1,顶层应用接口文件:
i2s.h:提供原有I2S API,供使用旧驱动的应用程序调用。旧版API不支持新特性,但在一些老应用中依然可用。
i2s_std.h:提供标准通信模式的API,用于新驱动的标准模式。该文件包含配置标准I2S通信的函数。
i2s_pdm.h:提供PDM通信模式的API,供新驱动的PDM模式使用。PDM(脉冲密度调制)模式主要用于麦克风输入等音频处理场景。
i2s_tdm.h:提供TDM通信模式的API,供新驱动的TDM模式使用。TDM(时分多路复用)模式用于多通道音频通信。
2,公共类型文件:
i2s_types_legacy.h:定义旧驱动中使用的类型和结构体,专为与旧I2S API兼容而设计。
i2s_types.h:定义I2S模块中的公共类型,包括在各个I2S模式下都可能使用的基础类型。
3,公共功能文件
i2s_common.h:提供所有通信模式通用的API接口,包括初始化、配置、启动等公共操作。这样可以避免在每个模式文件中重复实现公共操作。
i2s_common.c:实现了i2s_common.h中声明的通用API逻辑,将公共操作的功能具体实现,以便不同模式复用。
4,私有头文件
i2s_private.h:包含仅在驱动内部使用的私有函数和定义,避免了与公共接口的混淆。该文件中的内容不直接对用户开放,只在驱动的内部实现中使用。
5,HAL层文件
i2s_hal.h:定义了硬件抽象层(HAL)的接口,屏蔽了底层硬件细节,为上层提供更为抽象的I2S操作。
i2s_hal.c:实现了HAL层的具体操作逻辑,与底层硬件直接交互。
i2s_ll.h:提供低层(LL)接口,包含底层寄存器操作函数,以更直接的方式访问I2S硬件。
6,旧版I2S驱动文件
i2s_legacy.c:包含旧I2S驱动的具体实现逻辑,适用于兼容原有I2S API的应用。
注意:原有驱动与新驱动不可共存。应用应选择包含i2s.h来使用原有驱动,或包含i2s_std.h、i2s_pdm.h、i2s_tdm.h来使用新驱动。未来,原有驱动可能会被移除。

43.2 硬件设计
43.2.1 程序功能
本章实验功能简介:开机后,先初始化各外设,然后检测字库是否存在,如果检测无问题,则开始循环播放SD卡MUSIC文件夹里面的歌曲(必须在SD卡根目录建立一个MUSIC文件夹,并存放歌曲在里面),在TFTLCD上显示歌曲名字、播放时间、歌曲总时间、歌曲总数目、当前歌曲的编号等信息。KEY0用于选择下一曲,KEY1用于选择上一曲,KEY2用来控制暂停/继续播放。LED0闪烁,提示程序运行状态。
注意:在接入RGBLCD屏时,我们发现MCU与ES8388之间的通信可能会出现丢包现象。经过半个月的调试,最终通过将RGBLCD的数据线与I2C通信线分开布线,极大的减少了丢包现象。然而,偶尔仍会出现丢包现象。为了解决这一问题,我们在ES8388的写函数中添加了do-while语句,确保ES8388能收到应答后再继续执行操作。若读者希望进一步减少丢包现象,可以尝试调整RGBLCD的电源电压。具体方法是在rgblcd.c文件中,将LDO4的输出电压调整为2200mV(即2V)。在DNESP32P4开发板中,ESP32-P4芯片的LDO4用于控制VDDPST1电源域的电压,而VDDPST1管脚则用于与RGBLCD进行通信。通过调节LDO4的输出电压,可以更好地减少与ES8388通信时的丢包问题。需要注意的是,此问题仅出现在接入RGBLCD屏时,若接入MIPI显示屏则不会出现丢包现象。

43.2.2 硬件资源
本实验,大家需要准备1张TF卡(在里面新建一个MUSIC文件夹,并存放一些歌曲在MUSIC文件夹下)和一个耳机(非必备),分别插入TF卡接口和耳机接口,然后下载本实验就可以通过耳机或板载喇叭来听歌了。实验用到的硬件资源如下:
1)LED灯
LED 0 - IO51
2)ES8388音频CODEC芯片,通过I2S驱动
3)I2S音频接口
I2S_BCK_IO - IO47
I2S_WS_IO - IO48
I2S_DO_IO - IO49
I2S_DI_IO - IO50
I2S_MCK_IO - IO46
4)XL9555
IIC_INT - IO36
IIC_SDA - IO33
IIC_SCL - IO32
EXIO_8 - KEY0
EXIO_9 - KEY1
EXIO_10 - KEY2
5)RGBLCD/MIPILCD(引脚太多,不罗列出来)
6) SPIFFS
7)SD卡
CMD - IO44
CLK - IO43
D0 - IO39
D1 - IO40
D2 - IO41
D3 - IO42

43.2.3 原理图
ES8388器件相关原理图,如下图所示。

image025

图43.2.3.1 ES8388硬件原理图

DNESP32P4开发板板载的ES8388解码芯片的驱动电路原理图如上图所示。图中,PHONE接口可以用来插耳机,SPK_IN连接了板载的喇叭,IIC接口和24C02等芯片共用。

posted @ 2026-08-18 10:44  正点原子  阅读(7)  评论(0)    收藏  举报