风筝
发表于: 2021-9-6 17:43:39 | 显示全部楼层

I2S协议,全称Inter-IC Sound,主要用于在两个设备之间的同步串口中传输或接收音频数据。在数字设备中有许多需要音频通信的应用,例如添加麦克风或添加扬声器输出以播放某些音频。


在使用音频编解码器、DAC或 ADC的电子设备中有多种音频协议可用。最简单也可能是最好的方法之一是使用 I2S 协议,该协议使用简单的引脚配置并在两个数字音频设备之间进行通信。I2S 协议由飞利浦半导体(现为恩智浦半导体)设计,广泛应用于使用该协议进行数据通信的不同微控制器、编解码器、音频模块、麦克风。


接下来让我们探讨一下I2S的关键特性以及该协议如何在微控制器中工作。


I2S连接

I2S协议使用三根线进行通信。发射器和接收器之间的连接如下所示。

I2S-3-Wire-Connection.png


字选择 (WS) 或帧选择(FS) 线:

由于I2S协议同时使用立体声操作,因此可以使用WS引脚选择左声道或右声道。一般情况下,如果WP引脚处于低电平状态,则选择通道1或左通道,反之,如果WS引脚处于高电平状态,则使用右通道。

如果不考虑上述通道选择引脚,I2 协议使用两个在任何串行接口中最常见的引脚。


串行数据引脚或SD:

I2S通信协议的第二根线是串行数据或承载数据信号的SD引脚。通过这条线传输数据采用2补码方式。


在I2S数据传输中,首先传输最高有效位 (MSB) ,这样做的原因很明显。在I2S中,从发送器传输到接收器,数据可以采用不同的字长。


因此,如果首先发送MSB,则发送器和接收器将不存在知道传输或传入多少位的相关性。


这就产生了一个新问题,因为接收器和发送器不知道字长,所以匹配数据变得困难,因为在数据传输过程中由于噪声和其他因素可能会丢失数据。这可以使用WS引脚解决。如果接收器的 WS大于发送器的WS,则该字被截断,最低有效数据位设置为0。如果接收器的WS小于发送器的WS,则LSB之后的位被忽略。


位时钟线或BCLK:

I2S 通信的最后一个也是最重要的引脚是串行时钟 (SCK),也称为位时钟线 (BCLK)。顾名思义,它是一个时钟引脚,在串行数据通信协议中很重要。


它用于在同一循环中获取所有组件。BCLK线频率取决于采样率、每通道位数以及它使用的通道数。


I2S 时序图

在下图中,显示了时序:

I2S-Timing-Diagram.png


在上面的时序图中,显示了三根线:BCLK、WS、SD。 BCLK 将为I2S线提供所需的时钟周期。 WS将其状态从右声道更改为左声道。


数据通过I2S传输,并在每个时钟周期发送。在I2S数据线的一个时钟周期开始传输MSB之前,WS引脚将其状态从一个通道更改为另一通道。这是因为接收器需要时间来存储先前发送的字并清除寄存器。


ESP32中的I2S控制器功能

ESP32是一种广受欢迎的低成本、支持WiFi和蓝牙的32位微控制器单元,支持I2S功能。


下面是ESP32的I2S控制器功能的完整列表。

●    I2S 控制器驱动程序可以作为系统主机或从机运行。

●    它还能够充当I2S总线中的发送器或接收器。

●    ESP32有一个专用的 DMA 控制器,可以流式传输样本数据,而无需依赖CPU来复制和检查每个数据样本。

●    I2S外设也支持LCD。在此模式下,I2S数据开始通过并行总线进行通信。在某些LCD和相机模块中需要它。


I2S诺基亚音调发生器

让我们在I2S协议中连接一个扬声器,并使用ESP32 I2S生成一段诺基亚曲调。


然而,由于扬声器是一个模拟设备并且要驱动它,我们需要一个支持I2S的放大器;我们选择使用基于I2S的单声道放大器MAX98357A模块。


下图显示了模块的引脚排列。

MAX98357A.jpg


模块的三个重要引脚是 BCLK、DIN 和 LRC。 DIN为数据输入引脚,与SD相同,LRC为左右声道选择引脚,与WS相同。


电路连接原理图如下:

ESP32-I2S-Communication-Schematic.png


ESP32的I2S示例代码

为了运行代码,sampleaac.h头文件包含转换为HEX格式的诺基亚曲调的aac。


头文件的格式是这样的:

  1. const unsigned char sampleaac[] PROGMEM = { 0xFF, 0xF9, 0x5C, 0x80, 0x2E, …………. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2. 0xF2
  3. };
复制代码

首先包含所有头文件

  1. #include "AudioGeneratorAAC.h"
  2. #include "AudioOutputI2S.h"
  3. #include "AudioFileSourcePROGMEM.h"
  4. #include "sampleaac.h"
复制代码

我们使用音频生成器AAC库,该库使用I2S协议生成音频。这可以在下面的 GitHub 中找到:https://github.com/earlephilhower/ESP8266Audio


之后,根据之前提供的引脚图设置引脚。

  1. #define Bit_Clock_BCLK 27
  2. #define Word_Select_WS 26
  3. #define Serial_Data_SD 25
复制代码

然后在setup函数中,设置I2S设备引脚。

  1.   in = new AudioFileSourcePROGMEM(sampleaac, sizeof(sampleaac));
  2.   aac = new AudioGeneratorAAC();
  3.   out = new AudioOutputI2S();
  4.   out -> SetGain(GAIN);
  5.   out -> SetPinout(Bit_Clock_BCLK,Word_Select_WS,Serial_Data_SD);
  6.   aac->begin(in, out);
  7. }
复制代码

loop()函数一直循环播放示例AAC的音频。

  1. void loop(){
  2.   if (aac->isRunning()) {
  3.             aac->loop();
  4.   } else {
  5.             aac -> stop();
  6.             Serial.printf("Sound Generator\n");
  7.             delay(1000);
  8.   }
  9. }
复制代码

使用I2S通信在ESP32上播放诺基亚曲调

现在我们知道了ESP32上的I2S通信是如何工作的,接下来就可以建立连接、上传代码并播放测试音频。在本文中,以诺基亚曲调为例。所有东西都已正确连接并准备好进行测试。

ESP32-I2S-Audio.jpg


希望本文能帮助您在未来的所有项目中使用ESP32 I2S音频。如果您有任何问题,可以随时在本帖下面回复。


跳转到指定楼层
01q2f
发表于: 2022-11-22 15:43:59 | 显示全部楼层


您的代码我测试了一下,我的ESP32-s3,可以播放,但是要删除下面这句话,不知道为啥
  out -> SetGain(GAIN);
回复

使用道具 举报

01q2f
发表于: 2022-11-24 08:08:15 | 显示全部楼层

01q2f 发表于 2022-11-22 15:43
您的代码我测试了一下,我的ESP32-s3,可以播放,但是要删除下面这句话,不知道为啥
  out -> SetGain(GAI ...

弄明白了,out -> SetGain(0.2);            //设置音量

范围是0.1~1之间,这里要输入明确的数值
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 56 | 回复: 109



手机版|

GMT+8, 2024-12-21 20:49 , Processed in 0.046999 second(s), 8 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表