wp网站搬家教程,北外网院网站建设作业,国外主题网站,世界比分榜文章目录 简介为什么需要I2S#xff1f;关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频#xff1f;位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载… 文章目录 简介为什么需要I2S关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载I2S驱动 总结 简介
在音频处理领域I2S是一种广泛使用的通信协议它专门用于芯片之间的音频数据传输。ESP32 作为一款高性能的微控制器不仅支持 I2S 通信还提供了强大的硬件接口和灵活的软件库使其成为音频项目开发的理想选择。本篇文章将介绍I2S的相关知识和使用ESP32驱动I2S音频设备时比较常用的相关底层API函数。
I2S即Inter-IC Sound 简称I2S意思是芯片间音频总线它是由飞利浦开发的一种用于数字音频设备的通信协议常用于麦克风、扬声器、音频处理器等设备之间的音频数据传输。
为什么需要I2S
传统的音频设备像模拟电路传递的是电压信号这种方式容易受到干扰比如噪声或者信号衰减。而数字音频需要传输数据通常是二进制的“0”和“1”直接用模拟接口传输会很麻烦。而 I2S就是为了解决这个问题的一种数字音频接口它让音频数据的传输变得简单、高效、而且抗干扰能力强。 使用 I2S可以很方便地把数字音频信号从一个芯片传递到另一个芯片对于开发者来讲只需要配置好芯片的 I2S 模块就可以实现数字音频数据的传输了。
关于音频信号
在自然界中音频信号是以模拟量的形式存在的它是一种随时间连续变化的物理量为了减少外界的干扰我们需要把它变成数字量我们一般可以通过一个模数转换器把它变成数字信号图1数字信号在计算机或数字设备中以离散的数值形式表示和处理比如用0和1的组合去表示这里可以了解下PCM编码它是一种模拟信号数字化的方法 图1 当然我们也能通过一个数模转换器把数字信号还原成模拟信号以便在扬声器上播放音频图2。 图2 这样音频信号之间的传递就可以通过数字信号来进行了图3可以减少外界对信号的干扰。 图3 在音频信号处理和传输中有三个非常重要的参数决定了音频质量和设备性能采样率、分辨率和 音频声道。
采样率
采样率就是每秒采集声音样本的频率这个频率越快采样的数字信号就越接近原始的声音的信号因为采样的越快离散数字曲线每个样本值之间的过渡就越接近曲线就会越平滑。这个过程和录像是类似的一个是采样光一个采样振动。我们知道录像其实就是一帧一帧的图像快速播放这个采样速度很快我们肉眼分辨不了看起来就是连续的。如果录像时采样的速度很慢比如1秒采样3次那我们就会丢失掉很多画面细节。采集声音的时候也是如此大家可以想象一下如果采集频率很慢听到的声音会是什么样子会明显感到声音听起来失真不连贯甚至变样。 每秒钟采集的音频样本数常见的有8K、16K、44.1K等采样率越高信号还原越精细一般使用44.1KHz采样频率就可以得到比较高保真的声音。
分辨率
对声音数据采样后我们将得到一些离散的样本点那我们在一些数字设备是如何存储这些样本点的呢我们采样的数据是以二进制的形式存储的比如对于每一个采样点我们用3位二进制来表示图4那么它可以表示的范围就是2^38 即8种量化电平信号(图5)可以简单理解为每个采样点可以存储 8种情况的声音。如果量化位数越多根据我们高中学过的排列组合知道得到的样本值就会越多那它可以表示自然界声音的细节就越多或者说能表示的声音就越丰富。 音频数据的量化位数或量化深度常见的有8bit、16bit、24bit、32bit等位数越高信号的动态范围和精细程度越好 图4 图5 音频声道
分为单声道双声道单声道是一种只有一个音频信号通道所有声音都合并到一个通道中输出无论是通过一个扬声器还是两个扬声器听到的声音是完全相同的。双声道分为左声道和右声道具有两个独立音频通道左声道和右声道可以传递不同的声音信号具有空间感和方向感也就是我们平常说的立体声。
怎样使用I2S传输音频
使用I2S传输音频的时候需要用到时钟信号、控制信号以及数据信号(图6)它们之间是分开传输的。对于标准通信模式下的 I2S 总线主要包含以下几个信号位时钟BCLK字时钟WS串行数据SD。有的时候还需要MCLK主时钟线该信号线可选具体取决于从机主要用于向 I2S 从机提供参考时钟。 (注意这几种信号有几种其它叫法这里结合英文选择了这几个名称大家只要在使用能区分就行)~ 图(6) 位时钟BCLK BCLKBit Clock位时钟 也叫BCK, SCLK(Serial Clock),对应数字音频的每一位数据是模块内的同步信号 BCLK 定义了数据传输的速率用来控制数据的传输节奏。它的频率通常是采样率乘以每个采样的位数再乘以声道数量。例如对于 44.1kHz 的采样率、16 位双声道音频BCLK 的频率为 44.1kHz × 16 × 2 1.4112 MHz。所以对于双声道来说BCLK的频率2×采样频率×采样位数。 字时钟WS WS(Word Select , 字选择时钟) 也叫 LRCLK Left Right Clock即左右声道时钟 用于标识当前正在传输的是左声道数据还是右声道数据。对于飞利浦公司定义的I2S标准当 WS 为低电平时表示左声道高电平时表示右声道。一个完整的 WS 信号周期包含两个声道的数据左声道和右声道 WS 信号的频率等于音频的采样率。 例如如果音频采样率是 44.1kHz那么 WS 的频率也是 44.1kHz。 串行数据SD SDSerial Data串行数据 i2s传输时的音频数据是用二进制补码表示的具体数据传输的格式主要包括I2S格式左对齐格式右对齐格式, 每个 BCK 周期会传输一位数据。数据发送端和接收端会根据 BCK 信号的跳变上升沿或下降沿同步数据的发送和接收。当 WS 为低电平时SD 传输左声道数据当 WS 为高电平时SD 传输右声道数据。 比如我们传输16 位双声道音频SD数据为1 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1 1 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1
它表示
每个 BCK 周期传输一位音频数据。当 WS 为低电平时SD 按位传输左声道的 16 位数据1 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1当 WS 为高电平时SD 按位传输右声道的 16 位数据 1 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1 个人总结 字时钟高低电平翻转总线在传输双声道音频 0为左 1为右字时钟的频率采样率 位时钟串行数据线的信号会在位时钟上升沿被采样位时钟的频率2×采样率×采样位数。 串行数据用二进制补码表示的音频数据先传输高位再传输低位 Tips:字时钟和位时钟都是由主机发送 了解了I2S是如何传输后我们再来看看他的传输模型和通信格式。
I2S传输模型
I2S通信支持全双工和半双工通信支持主/从模式。主设备就是发送时钟的从设备在时钟的控制下发送或者接收数据。
连接到I2S总线的设备可以分为两类 控制器——控制 SCK 和 WS 信号。 目标设备——接收 SCK 和 WS 信号 总线上只能有一个控制器但是总线可以有多个目标设备。
音频设备可以分为三类 发射器——发送音频信号。 接收器——接收音频信号。 控制器——控制音频信号 这里我们至少需要一个发射器和接收器控制器是可选的主要用于向 I2S 从机提供参考时钟
根据I2S总线谁作为控制器谁作为目标设备我们可以有三种I2S传输模型
发射器作为控制器 接收器作为目标设备 发射器作为目标设备接收器作为控制器 发射器和接收器都作为目标设备其他I2S控制器作为控制器 总结三种经典I2S传输模型 I2S通信格式
PCM510xA 支持行业标准的音频数据格式包括标准 I2S 和 左对齐Left-justified 格式等。
I2S格式
I2S格式又称飞利浦格式图7数据最高位总是出现在字时钟变化后的第二个位时钟脉冲处滞后一个位时钟这种格式下数据MSB的位置是确定的LSB的位置取决于字长。 图(7) 左对齐格式
左对齐格式(图8)数据最高位出现在字时钟变化后的第一个位时钟脉冲处无滞后位时钟 图(8) 右对齐格式
右对齐格式又称日本格式这种格式和左对齐差不多只不过整体是靠右对齐的即数据LSB与WCLK跳变沿对齐。 图(9) i2s基本配置 ①i2s的时钟使能和GPIO口配置 ②配置为i2s模式 ③i2s标准无论有多少位有效数据即数据的最高位总是出现在WS变化也就是一帧开始后的第2个CK脉冲处。 ④i2s数据长度包括16位16位扩展16位数据以32位包发送24位32位。 ⑤设置i2s时钟 ⑥设置i2s空闲状态下时钟电平 ⑦i2s使能 i2s 底层API
这里我们以ESP32 I2S通信为例开发环境是Arduino IDE介绍它的相关底层API在我们调库的时候下面这些函数会被调用我们看一下它的实现过程。
加载I2S驱动
函数原型
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue)参数说明
i2s_port_t i2s_num指定使用的 I2S 外设端口。i2s_port_t 是 I2S 外设端口的枚举类型有两个端口可用I2S_NUM_0 和 I2S_NUM_1对应 ESP32 的第一个和第二个 I2S 外设。
typedef enum {I2S_NUM_0 0, /*! I2S port 0 */
#if SOC_I2S_NUM 1I2S_NUM_1 1, /*! I2S port 1 */
#endifI2S_NUM_MAX, /*! I2S port max */
} i2s_port_t;const i2s_config_t * i2s_config : 设置I2S 外设的配置参数。其中i2s_config_t 是一个结构体定义了 I2S 外设的配置选项这里我们只看常用的配置选项就可以了主要包括mode、 sample_rate、bits_per_sample等如下
typedef struct {i2s_mode_t mode; /* 设置 I2S 的工作模式 */uint32_t sample_rate; /*! 设置音频采样率 */i2s_bits_per_sample_t bits_per_sample; /*! 设置采样位数 */i2s_channel_fmt_t channel_format; /*! 设置数据通道格式.*/i2s_comm_format_t communication_format; /*! 设置I2C数据传输格式 */int intr_alloc_flags; /*! 设置中断相关标志位*/int dma_buf_count; dma缓存个数 int dma_buf_len;
} i2s_driver_config_t;typedef i2s_driver_config_t i2s_config_t;
int queue_size 数据传输的队列的大小 void * i2s_queue存放和管理 I2S 传输的数据。
这个函数有一个esp_err_t 的返回值如果返回ESP_OK表示加载I2S驱动成功。
设置I2S使用的引脚
函数原型
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)参数说明
i2s_port_t i2s_num指定使用的 I2S 外设端口I2S_NUM_0 或I2S_NUM_1。
i2s_pin_config_t * pin配置I2S接口的各个引脚i2s_pin_config_t 是一个结构体里面是关于I2S引脚如时钟引脚左右声道选择引脚数据输入引脚等引脚的配置。如下
typedef struct {int mck_io_num; /*! MCK in out pin. Note that ESP32 supports setting MCK on GPIO0/GPIO1/GPIO3 only*/int bck_io_num; /*! BCK in out pin*/int ws_io_num; /*! WS in out pin*/int data_out_num; /*! DATA out pin*/int data_in_num; /*! DATA in pin*/
} i2s_pin_config_tI2S读取数据
函数原型
esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait);*/用于从 I2S接口读取音频数据
参数说明 i2s_port_t i2s_numI2S_NUM_0 或I2S_NUM_1。
void * dest读取目标数据的缓存区
size_t size要读取的数据大小单位是字节
size_t * bytes_read实际读取到的字节数
TickType_t ticks_to_wait超时等待时间因为I2S是按一定频率读取数据的如果一次传输的数据很多就需要等待这个参数一般写入portMAX_DELAY 表示无限等待。
如果返回ESP_OK表示I2S读取数据成功。
I2S发送数据
函数原型
esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait);*/用于向 I2S 接口写入音频数据参数说明 i2s_port_t i2s_numI2S_NUM_0 或I2S_NUM_1。
const void *src写入源数据的缓存区
size_t size要写入的数据大小单位是字节
size_t *bytes_written实际写入的字节数
TickType_t ticks_to_wait超时等待时间因为I2S是按一定频率发送数据的如果一次传输的数据很多就需要等待这个参数一般写入portMAX_DELAY 表示无限等待。
卸载I2S驱动
函数原型
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);参数说明 卸载I2S驱动的话我们只需要传入I2S端口就行了。
i2s_port_t i2s_num指定使用的 I2S 外设端口。i2s_port_t 是 I2S 外设端口的枚举类型有两个端口可用I2S_NUM_0 和 I2S_NUM_1对应 ESP32 的第一个和第二个 I2S 外设。
总结
以上我们介绍了I2S的相关知识和配置的相关函数下篇文章我们来看一下一个使用ESP32驱动I2S设备的小案例这系列的文章主要是分享一下本人学习过程的相关知识如果有错误可以交流学习下