I2S相关

I2S

一、简介
I2S(Inter IC Sound)又称集成电路内置音频总线,是一种数字音频设备间的音频数据传输总线标准,该总线专责于音频设备之间的数据传输。采用独立导线传输和时钟信号分离避免因时差引发失真。
二、I2S特点
支持全双工/半双工通信支持主/从模式设置
8位可编程线性预分频器,可实现精确的音频采样频率(8~192Khz)支持16位/24位/32位数据格式
数据包帧固定为16位(仅16位数据帧)或32位(可容纳16/24/32位数据帧)可编程时钟极性
支持MSB对齐(左对齐)、LSB对齐(右对齐)、飞利浦标准和PCM标准等12S标准支持DMA数据传输(16位宽)
数据方向固定位MSB在前
支持主时钟输出(固定为256*fs, fs即音频采样率)
三、Stm32F4上I2S的框图
在这里插入图片描述
STM32F4的12S是与SPI部分共用的,通过设置SPL 12SCFGR寄存器的I2SMOD位为1即可开启I2S功能。I2S接口使用了几乎与SPI相同的引脚、标志和中断.(MOSI和MISO两个引脚一般只有全双工的时候用到,半双工的时候不用)
I2S用到的信号
1,SD:串行数据(映射到 MOSI 引脚),用于发送或接收两个时分复用的数据通道上的数据(仅半双工模式)。(相当于WM8978的ADCADAT和DACDAT)
2,WS:字选择(映射到NSS引脚),即左右时钟,用于切换左右声道的数据。WS频率等于音频信号采样率(fs)。(相当于LRC)
3,CK:串行时钟(映射到SCK引脚),即位时钟,是主模式下的串行时钟输出以及从模式下的串行时钟输入。CK频率=WS频率(fs)216(16位宽),如果是32位宽,则是:CK频率=WS频率(fs)232(32位宽)。(相当于BCLK)
4,I2S2ext_SD和I2S3ext_SD:用于控制I2S全双工模式的附加串行数据引脚(映射到MISO引脚),这两个引脚仅用于全双工模式
5,MCK:即主时钟输出,当I2S配置为主模式(且SPI_I2SPR寄存器的MCKOE位置1)时,使用此时钟,该时钟频率为 256×fs,fs:音频信号采样频率。
STM32F4为支持I2S全双工模式,除了I2S2和I2S3,还可以使用两个额外的I2S,它们称为扩展I2S(I2S2_ext、I2S3_ext),其框图为:
在这里插入图片描述
扩展I2S (I2Sx_ext)只能用于全双工模式。I2Sx_ext始终在从模式下工作。I2Sx和I2Sx_ext 均可用于发送和接收。
I2S帧格式:
四种帧组合
1,将16位数据封装在16位帧中;
2,将16位数据封装在32位帧中;
3,将24位数据封装在32位帧中;
4,将32位数据封装在32位帧中;

将16位数据封装在32位帧中时,前16位(MSB)为有效位,16位LSB被强制清零,无需任何软件操作或DMA请求(只需一个读/写操作)。如果应用程序选则DMA,则24位和32位数据帧需要对SPI_DR执行两次CPU读取或写入操作,或者需要两次DMA操作。24位的数据帧,硬件会将8位非有效位扩展到带有0位的32位数据帧。

STM32F4的I2S支持四种帧标准:
1、飞利浦标准 2、MSB对齐标准 3、LSB对齐标准 4、PCM标准
飞利浦标准
在这里插入图片描述
I2S飞利浦标准,使用WS信号来指示当前正在发送的数据所属的通道。该信号从当前通道数据的第一个位(MSB)之前的一个时钟开始有效。发送方在时钟信号(CK)的下降沿改变数据,接收方在上升沿读取数据。WS信号也在CK的下降沿变化。(上图WS=LRC)
使用24位数据32位帧格式。

在24位模式下数据传输,需要对SPI_DR执行两次读取或写入操作。比如要发送0X8EAA33这个数据,就要分两次写入SPI_DR,第一次写入:0X8EAA,第二次写入0X33xx(xx可以为任意数值),这样就把0X8EAA33发送出去了。
注意:从SD卡读取到的24位WAV数据流,是低字节在前,高字节在后的,比如,我们读到一个声道的数据(24bit),存储在buf[3]里面,那么要通过SPI_DR发送这个24位数据,过程如下:
SPI_DR=((u16)buf[2]<<8)+buf[1];
SPI_DR=(u16)buf[0]<<8;
这样,第一次发送高16位数据,第二次发送低8位数据,完成一次24bit数据的发送。

STM32的I2S时钟发生器
在这里插入图片描述
上图中的I2SxCLK,可以来自PLLI2S输出(通过R系数分频)或者来自外部时钟(I2S_CKIN引脚),一般我们使用前者作为I2SxCLK输入时钟。
我们需要根据音频采样率(fs)来计算各个分频器的值,常用的音频采样率有:22.05Khz、44.1Khz、48Khz、96Khz、196Khz等。

当MCK输出使能时,fs频率计算公式如下:
fs=I2SxCLK/[256*(2 * I2SDIV+ODD)]
其中:I2SxCLK=(HSE/pllm) * PLLI2SN / PLLI2SR。HSE我们是8Mhz,而pllm在系统时钟初始化就确定了,是8,这样结合以上2式,可得计算公式如下:
fs= (1000 * PLLI2SN / PLLI2SR ) / [ 256 * (2 * I2SDIV+ODD)]
fs单位是:Khz。其中:PLLI2SN取值范围:192 ~ 432;PLLI2SR取值范围:2 ~ 7;I2SDIV取值范围:2 ~ 255;ODD取值范围:0/1。
根据以上约束条件,便可根据fs来设置各个系数的值了,不过很多时候,并不能取得和fs一模一样的频率,只能近似等于fs,比如44.1Khz采样率,我们设置PLLI2SN=271,PLLI2SR=2,I2SDIV=6,ODD=0,得到fs=44.108073Khz,误差为:0.0183%。晶振频率决定了有时无法通过分频得到我们所要的fs,所以,某些fs如果要实现0误差,大家必须得选用外部时钟(例如上文所说的I2S_CKIN)才可以。
如果要通过程序去计算这些系数的值,是比较麻烦的,所以,我们事先计算好常用fs对应的系数值,建立一个表,这样,用的时候,只需要查表取值就可以了,大大简化了代码,常用fs对应系数表如下:

  //表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
const u16 I2S_PSC_TBL[][5]=
{
        {800 ,256,5,12,1},		//8Khz采样率
        {1102,429,4,19,0},		//11.025Khz采样率 
        {1600,213,2,13,0},	//16Khz采样率
        {2205,429,4, 9,1},		//22.05Khz采样率
        {3200,213,2, 6,1},		//32Khz采样率
        {4410,271,2, 6,0},		//44.1Khz采样率
        {4800,258,3, 3,1},		//48Khz采样率
        {8820,316,2, 3,1},		//88.2Khz采样率
        {9600,344,2, 3,1},  	//96Khz采样率
        {17640,361,2,2,0},  	//176.4Khz采样率 
        {19200,393,2,2,0},  	//192Khz采样率
};

//表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
F4的I2S寄存器
(1)SPI_I2S配置寄存器(SPI_I2SCFGR)
在这里插入图片描述
I2SMOD位,设置为1,选择I2S模式,必须在I2S/SPI禁止的时候,设置该位。即在I2S还未使能时才能进行配置。
I2SE位,设置为1,使能I2S外设,该位必须在I2SMOD位设置之后再设置。
I2SCFG[1:0]位, 这两个位用于配置I2S模式,设置为10,选择主模式(发送)。
I2SSTD[1:0]位,这两个位用于选择I2S标准,设置为00,选择飞利浦标准。
CKPOL位,用于设置空闲时时钟电平,设置为0,空闲时时钟低电平。
DATLEN[1:0]位,用于设置数据长度,00,表示16位数据;01表示24位数据。
CHLEN位,用于设置通道长度,即帧长度,0,表示16位;1,表示32位。
(2)SPI_I2S预分频寄存器(SPI_I2SSPR)
在这里插入图片描述
设置MCKOE为1,则开启MCK输出,ODD和I2SDIV则根据不同的fs,查表进行设置。
(3)PLLI2S配置寄存器(RCC_PLLI2SCFGR)
在这里插入图片描述
该寄存器用于配置PLLI2SR和PLLI2SN两个系数,PLLI2SR的取值范围是:2 ~ 7,PLLI2SN的取值范围是:192 ~ 432。同样,这两个也是根据fs的值来设置的。
此外,还要用到SPI_CR2寄存器的bit1位,设置I2S TX DMA数据传输,SPI_DR寄存器用于传输数据,本例程用DMA来传输,所以设置DMA的外设地址为SPI_DR即可.

[(SPI_CR2): 位 1 TXDMAEN:发送缓冲区 DMA 使能 (Tx buffer DMA enable) 当此位置 1 时,每当 TXE 标志置 1 时,即产生 DMA 请求。
0:关闭发送缓冲区 DMA 1:使能发送缓冲区 DMA SPI 数据寄存器
(SPI_DR): 位 15:0 DR[15:0]:数据寄存器 (Data register) 已接收或者要发送的数据。 数据寄存器分为 2个缓冲区,一个用于写入(发送缓冲区),一个用于读取(接收缓冲区)。对数据寄存器执行写操作时,数据将写入发送缓冲区,从数据寄存器执行读取时,将返回接收缓冲区中的值。
针对 SPI 模式的说明: 发送或接收的数据为 8 位或 16 位,具体取决于数据帧格式选择位(SPI_CR1 寄存器中 的DFF)。必须在使能 SPI 前进行此项选择,以确保操作正确。
对于 8 位数据帧,缓冲区为 8 位,只有寄存器的 LSB(SPI_DR[7:0]) 用于发送/接收。 在接收模式下,寄存器的 MSB (SPI_DR[15:8]) 强制为 0。
对于16位数据帧,缓冲区为 16 位,整个寄存器 SPI_DR[15:0] 均用于发送/接收。]

初始化步骤

1)初始化WM8978
这个过程就是配置第一讲介绍的WM8978那十几个寄存器,包括软复位、DAC设置、输出设置和音量设置等。
2)初始化I2S
此过程主要设置SPI_I2SCFGR寄存器,设置I2S模式、I2S标准、时钟空闲电平和数据帧长等,最后开启I2S TX DMA,使能I2S外设。
3)解析WAV文件,获取音频信号采样率和位数并设置I2S时钟分频器
解析WAV文件,取得音频信号的采样率(fs)和位数(16位或24位),根据这两个参数,来设置I2S的时钟分频,我们用前面介绍的查表法来设置。
4)设置DMA
I2S播放音频,一般采用DMA来传输数据,这里我们用I2S2,其TX用DMA1数据流4的通道0来传输数据。并且,STM32F4的DMA具有双缓冲机制,这样可以提高效率。这里,我们将DMA1数据流4设置为:双缓冲循环模式,外设和存储器都是16位宽,并开启DMA传输完成中断(方便填充数据)。
5)编写DMA传输完成中断服务函数
为了方便填充音频数据,我们使用DMA传输完成中断,每当一个缓冲数据发送完后,硬件自动切换为下一个缓冲,同时进入中断服务函数,填充数据到发送完的这个缓冲。如下图所示:
在这里插入图片描述
6)开启DMA传输,填充数据
  最后,我们就只需要开启DMA传输,然后及时填充WAV数据到DMA的两个缓存区即可。此时,就可以在WM8978的耳机和喇叭通道听到所播放音乐了

在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Verilog I2S 是一种数字音频传输接口协议,其全称为Inter-IC Sound。它用于在集成电路之间传输音频数据,常见的应用包括数字音频处理和数字音频设备之间的数据传输。下面将简单介绍 I2S 接口的工作原理和 Verilog 语言在 I2S 设计中的应用。 I2S 接口通常由三条线路组成:串行数据线(SDATA),位时钟线(BCLK)和帧同步线(LRCLK)。SDATA 传输音频数据,BCLK 提供位时钟用于同步数据传输,而 LRCLK 表示每个数据帧的开始与结束。具体来说,在一个数据帧周期中,BCLK 在恒定的频率上生成,以指示每个数据位的传输时间。而 LRCLK 指示了数据帧的开始和结束,并且在数据传输期间改变数据通道。 在 Verilog 设计中,我们可以使用状态机进行 I2S 接口的实现。首先,我们需要定义状态机的状态和状态转移条件。例如,我们可以定义状态为等待帧开始、接收数据、等待帧结束和数据传输完成。接着,根据不同的状态,我们可以编写相应的 Verilog 代码来执行相应的操作。例如,在等待帧开始状态,我们可以等待 LRCLK 的下降沿,以便我们准备接收音频数据。而在接收数据状态,我们可以在每个 BCLK 上升沿时,按照 SDATA 的值来接收音频数据。最后,在数据传输完成状态,我们可以进行某些处理,例如将音频数据发送到外部设备或是进行数字信号处理。 除了状态机,我们还可以使用 Verilog 编程实现其他 I2S 接口的功能,例如时钟频率的控制、数据的格式转换等。通过合理设计和编写 Verilog 代码,我们可以实现一个完整的 I2S 接口设计,并用于数字音频相关的应用中。 总之,Verilog I2S 是一种用于音频数据传输的数字接口协议。通过在 Verilog 中实现 I2S 接口的状态机和其他相关功能,我们可以设计和开发出数字音频处理和相关设备之间的数据传输系统。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值