STM32个人笔记-I2S
现实存在的声音是模拟量,这对声音保存和长距离传输造成很大的困难,一般的做法是把模拟量转成对应的数字量保存,在需要还原声音的地方再把数字量的转成模拟量输出。模拟量转换成数字量,3个过程:采样、量化和编码。蓝线的距离就是采样信号的周期,即对应一个采样频率(Fs)。Fs越高,采样信号越符合曲线,但采样数据量也会越大,一般使用44.1KHzFs即可得高保真的声音。蓝线长度就是源声音的量化值。量化位数表示每
现实存在的声音是模拟量,这对声音保存和长距离传输造成很大的困难,一般的做法是把模拟量转成对应的数字量保存,在需要还原声音的地方再把数字量的转成模拟量输出。
模拟量转换成数字量,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。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)