STM32个人笔记:深入理解I2S协议

现实存在的声音是模拟量,这对声音保存和长距离传输造成很大的困难,一般的做法是把模拟量转成对应的数字量保存,在需要还原声音的地方再把数字量的转成模拟量输出。

模拟量转换成数字量,3个过程:采样、量化和编码。

蓝线的距离就是采样信号的周期,即对应一个采样频率(Fs)。Fs越高,采样信号越符合曲线,但采样数据量也会越大,一般使用44.1KHzFs即可得高保真的声音。 

蓝线长度就是源声音的量化值。量化位数表示每个采样点用多少位数代表数据范围,常用的有16bit、24bit和32bit等。位数越高,音质越好,数据量也越大。

VM8978是一个低功耗、高质量的立体声多媒体数字信号编译码器,集成DAC和ADC,可解决声音和数字量音频数据转换问题,但本身没有保存音频数据功能。通过VM8978芯片相关寄存器可控制转换过程的参数,比如采样频率,量化位数、增益、滤波等。该芯片与其他设备进行音频数据传输的接口就是I2S协议的音频接口。

I2S总线接口

I2S总线接口有3个主要信号,但只能实现数据半双工传输,后来为实现全双工传输增加了扩展数据引脚(如STM32F4xx,STM32F1xx不支持)

SD:串行数据线。如果是半双工模式,用于发送或接收两个时分复用的数据通道上的数据;如果是全双工模式,仅用于发送数据。

WS:字段选择线、帧时钟线(LRC)。表明当前传输数据的通道(左/右),不同标准不同定义。Fws=Fs。

CK:串行时钟线、位时钟(BCLK)。数字音频的每一位数据都对应一个CK脉冲,Fck=2*Fs*量化位数,2代表左右两个通道数据。

ext_SD:扩展串行数据线,用于全双工传输的数据接收。

另外,有时为使系统间更好地同步,还要传输一个主时钟(MSK),STM32F4xx系列控制器固定输出为256*Fs。

统一I2S硬件接口,几种不同的数据格式:MSB、LSB、I2S和PCM(脉冲编码)。

STM32F4xx系列I2S的数据寄存器只有16bit,并且左右声道数据一般是紧邻传输,为正确得到左右两个声道数据,需要软件控制数据对应通道数据写入或读取。另外,音频数据的量化位数可能不同,I2S支持16、24和32bit。因为数据寄存器只有16bit,所以对于24和32bit数据长度需要发送两个。因此,产生了4中数据和帧格式组合:

将16位数据封装在16位帧中、将16位数据封装在32位帧中、将24位数据封装在32位帧中、将32位数据封装在32位帧中

当使用32位数据帧的16位数据时,前16位为有效位,后16位被强制清零,无需任何软件操作或DMA请求(只需一个读/写操作)。

如果程序使用DMA传输(一般都会用),则24位和32位数据帧需要对数据寄存器执行两次DMA操作。对于所有数据格式和同学标准而言,时钟会先发送最高有效位(MSB优先)。

I2S标准

WS:0-左通道,1-右通道。WS信号从当前通道数据的MSB之前的一个时钟开始有效。发送方在时钟信号(CK)的下降沿改变数据,接收方在上升沿读取数据。WS信号也在SCK的下降沿变化。Fws=Fs,一个WS周期包括发送左通道和右通道数据,需要64个CK周期来完成一次传输。

左对齐标准 

WS:1-左通道,0-右通道。在WS发送翻转时,开始传输数据。该标准较少使用。

右对齐标准 

WS:1-左通道,0-右通道。在WS发送翻转时,开始传输数据。

PCM标准 

PCM即脉冲编码调制。WS不再作为通道数据选择。两种模式:短帧模式和长帧模式。以WS信号高电平保持时间为判断依据,长帧模式保持13个CK周期,短帧模式只保持1个CK周期,可以通过相关寄存器位选择。如果有多通道数据是在一个WS周期内传输完成的,传输完左通道数据就紧跟发送右声道数据。

I2S功能框图

STM32F4xx系列控制器有两个I2S:I2S2和I2S3,两个资源相互独立,但分别与SPI2和SPI3共用大部分资源。这样I2S2和SPI2只能选择一个功能使用,I2S3和SPI3只能选择一个功能使用。资源共用包括引脚共用和部分寄存器共用,部分专用。

控制器的I2S支持两种工作模式:主模式和从模式。主模式时使用自身时钟发生器生成通信时钟。

第一点,功能引脚

I2S的SD映射到SPI的MOSI引脚,ext_SD映射到SPI的MISO引脚,WS映射到SPI的NSS引脚,CK映射到SPI的SCK引脚。MCK是I2S专用引脚,用于主模式下输出时钟或在从模式下输入时钟。I2S时钟发生器可以由控制器内部时钟源分频产生,也可采用CKIN引脚输入时钟分频得到,一般使用内部时钟源即可。

引脚 I2S2 I2S3
SD PC3/PB15/PI3 PC12/PD6/PB5
ext_SD PC2/PB14/PI2 PC11/PB4
WS PB12/PB9 PA4/PA15
CK PB10/PB13/PD3 PC10/PB3
MCK PC6 PC7
CKIN PC9

第二点,数据寄存器

I2S有一个与SPI共用的SPI数据寄存器(SPI_DR),有效长度为16bit,用于I2S数据发送和接收。SPI数据寄存器组成:移位寄存器、发送缓冲区和接收缓冲区。当处于发送模式时向SPI_DR写入数据,先保存在发送缓冲区,总线自动把发送缓冲器内容转入到移位寄存器进行传输;当处于接收模式时向SPI_DR读取数据,实际接收到的数据先填充移位寄存器,然后自动转入接收缓冲区,软件读取SPI_DR时自动从接收缓冲器读取。I2S是挂载在APB1总线上的。 

第三点,逻辑控制

SPI_I2SCFGR:可实现I2S和SPI模式切换、选择I2S工作在主模式还是从模式并且选择是发送还是接收、选择I2S标准、传输数据长度等。

SPI_CR2:可设置相关中断和DMA请求使能。I2S有5个中断事件:发送缓冲区为空、接收缓冲区非空、上溢错误、下溢错误和帧错误。

SPI_SR:指示当前I2S状态。       

第四点,时钟发送器

I2S比特率用来确定I2S数据线上的数据流和I2S时钟信号频率。I2S比特率=每个通道的位数*通道数*音频采样频率。

I2SxCLK(x=2、3)可通过RCC_CFGR:I2SSRC选择使用PLLI2S时钟作为I2S时钟源或I2S_CKIN引脚输入时钟作为I2S时钟源。一般使用内部PLLI2S时钟(通过R分频系数)作为I2S时钟源。

SPI_I2SPR( SPI_I2S预分频器寄存器):MCKOE用于设置MCK引脚时钟输出使能。

SPI_I2SPR:ODD用于设置预分频器的奇数因子。实际分频值=I2SDIV*2+ODD,I2SDIV为8位线性分频器,不可设置为0或1。

当使能MCK时钟输出,即MCKOE=1时,采样频率计算如下:

Fs=I2SxCLK/[(16*2)*((I2SDIV*2)+ODD)*8)](通道帧宽度为16bit时)

Fs=I2SxCLK/[(32*2)*((I2SDIV*2)+ODD)*4)](通道帧宽度为32bit时)

当禁止MCK时钟输出,即MCKOE=0时,采样频率计算如下:

Fs=I2SxCLK/[(16*2)*((I2SDIV*2)+ODD))](通道帧宽度为16bit时)

Fs=I2SxCLK/[(32*2)*((I2SDIV*2)+ODD))](通道帧宽度为32bit时)

VM8978音频编译码器

它结合了立体声查分麦克风的前置放大与扬声器、耳机和差分、立体声线输出的驱动,减少了外部部件,比如不需要单独的麦克风或耳机的放大器。

与STM32控制器连接使用时,STM32一般作为主机,VM8978作为从机。

WAV格式文件

WAV是微软开发的音频格式文件,文件扩展名为.wav,用于保存windows的音频,符合资源互换文件格式(RIFF)文件规范。标准格式化的WAV文件和CD格式一样,也是44.1kHz的采样频率,16位量化位数,因此在声音文件质量和CD相差不大。WAV文件数据本身格式为PCM或压缩型,属于无损音乐格式的一种。

RIFF文件规范

RIFF由不同数量的chunk(区块)组成,每个chunk组成:ID、Size、Data。ID和Size都占用4个字节空间。

如下图,最开始是ID为“RIFF”的chunk,Size为“RIFF”chunk的Data的总Size,所以总文件大小为Size+8。

一般来说,chunk不允许内部再包含chunk,但有两个例外,ID为“RIFF”和“LIST”的chunk允许内部再包含chunk。

ID为“RIFF”的chunk的Data首4个字节用来存放格式标识码From Type,ID为“LIST”的chunk的Data首4个字节用来存放格式标识码LIST TYPE。

WAVE文件 

简单的RIFF文件,格式标识码WAVE。RIFF chunk包括两个子chunk,ID分别为fmt和data,还有一个可选的fact chunk。

Fmt chunk用于表示音频数据的属性,包括编码方式、通道数量、采样频率、每个采样需要的bit数等。

一般当WAVE文件由某些软件转化而成时包含了Fact chunk。

Data chunk包含WAVE文件的数字化波形声音数据。

I2S软件解析

初始化结构体

typedef struct
{
  uint32_t Mode;              //模式选择 
  uint32_t Standard;          //标准选择
  uint32_t DataFormat;        //数据格式  
  uint32_t MCLKOutput;        //主时钟输出使能
  uint32_t AudioFreq;         //采样频率 
  uint32_t CPOL;              //空闲电平选择
  uint32_t ClockSource;       //时钟源
  uint32_t FullDuplexMode;    //全双工模式选择
} I2S_InitTypeDef;

Mode:I2S_MODE_SLAVE_TX、I2S_MODE_SLAVE_RX、I2S_MODE_MASTER_TX、I2S_MODE_MASTER_RX。它设定SPI_I2SCFGR:I2SCFG的值。一般设置STM32控制器为主机模式,播放音乐时选择发送模式,录制声音时选择接收模式。

Standard:I2S_STANDARD_PHILIPS、I2S_STANDARD_MSB、I2S_STANDARD_LSB、I2S_STANDARD_PCM_SHORT、I2S_STANDARD_PCM_LONG。它设定SPI_I2SCFGR:I2SSTD、PCMSYNC的值。一般设置为I2S_STANDARD_PHILIPS。

DataFormat:I2S_DATAFORMAT_16B、I2S_DATAFORMAT_16B_EXTENDED、I2S_DATAFORMAT_24B、I2S_DATAFORMAT_32B。它设定SPI_I2SCFGR:DATLEN、CHLEN的值。对于16bit数据长度可选16bit或32bit帧长度,其他都是32bit帧长度。

MCLKOutput:I2S_MCLKOUTPUT_ENABLE、I2S_MCLKOUTPUT_DISABLE。它设定SPI_I2SPR:MCKOE的值。为提高系统性能一般使能主时钟输出。

AudioFreq:它设定SPI_I2SPR寄存器的值。

#define I2S_AUDIOFREQ_192K               (192000U)
#define I2S_AUDIOFREQ_96K                (96000U)
#define I2S_AUDIOFREQ_48K                (48000U)
#define I2S_AUDIOFREQ_44K                (44100U)
#define I2S_AUDIOFREQ_32K                (32000U)
#define I2S_AUDIOFREQ_22K                (22050U)
#define I2S_AUDIOFREQ_16K                (16000U)
#define I2S_AUDIOFREQ_11K                (11025U)
#define I2S_AUDIOFREQ_8K                 (8000U)
#define I2S_AUDIOFREQ_DEFAULT            (2U)

CPOL:I2S_CPOL_LOW、I2S_CPOL_HIGH。空闲状态的CK线电平,它设定SPI_I2SCFGR:CKPOL的值。一般设置为低电平即可。

ClockSource:I2S_CLOCK_PLL、I2S_CLOCK_EXTERNAL。一般设置为I2S_CLOCK_PLL即可。

FullDuplexMode:I2S_FULLDUPLEXMODE_DISABLE、I2S_FULLDUPLEXMODE_ENABLE。

物联沃分享整理
物联沃-IOTWORD物联网 » STM32个人笔记:深入理解I2S协议

发表评论