stm32音频接口I2S

时间:2024-03-07 09:43:16

stm32音频接口I2S

1 I2S简介

  I2S(Inter-IC Sound)飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准。I2S有3个主要信号

1.串行时钟SCLK,也叫位时钟(BCLK),即对应数字音频的每一位数据,SCLK都有1个脉冲。SCLK的频率=2×采样频率×采样位数。

2. 帧时钟LRCK,(也称WS),用于切换左右声道的数据。LRCK为“1”表示正在传输的是右声道的数据,为“0”则表示正在传输的是左声道的数据。LRCK的频率等于采样频率。

3.串行数据SDATA,就是用二进制补码表示的音频数据。

有时为了使系统间能够更好地同步,还需要另外传输一个信号MCLK,称为主时钟,也叫系统时钟(Sys Clock),是采样频率的256倍或384倍。

串行数据(SD)

  I2S格式的信号无论有多少位有效数据,数据的最高位总是出现在LRCK变化(也就是一帧开始)后的第2个SCLK脉冲处。这就使得接收端与发送端的有效位数可以不同。如果接收端能处理的有效位数少于发送端,可以放弃数据帧中多余的低位数据;如果接收端能处理的有效位数多于发送端,可以自行补足剩余的位。这种同步机制使得数字音频设备的互连更加方便,而且不会造成数据错位。(以上信息来自百度百科)

2  从设备ADMP441

  接口:标准飞利浦数字I2S接口,24-bit数据

  SCK :I2S接口的串行数据时钟引脚。

  SD  :I2S接口的串行数据输出引脚。

  WS :I2S接口的串行数据字选择引脚。

  电源电压:1.8 V < VDD < 3.3 V。

  数据格式:从机串行数据端口的格式为I2S 24-bit二进制补码。

  默认的数据格式为I2S (二进制补码),MSB 优先。

从机串行数据端口的格式为I2S 24-bit二进制补码。每个WS立体声数据帧对应64 个SCK 周期(fSCK = 64 × fWS)。;每个数据字必须对应32个SCK 周期。L/R控制引脚决定ADMP441从左通道还是右通道输出数据。

图1   硬件连接图

图2   立体声输出I2S时序图

3         stm32中I2S配置

3.1管脚映射

  stm32的大容量产品和互联型产品支持I2S音频协议(本文档使用stm32f103fzet6)。可以将SPI模块用作I2S音频接口。I2S和SPI共用3个引脚:

  ● SD:串行数据(映射至MOSI引脚),用来发送和接收2路时分复用通道的数据(PB15);

  ● WS:字选(映射至NSS引脚),主模式下作为数据控制信号输出,从模式下作为输入(PB12);

  ● CK:串行时钟(映射至SCK引脚),主模式下作为时钟信号输出,从模式下作为输入(PB13)。

  ● MCK:主时钟(独立映射),在I2S 配置为主模式,寄存器SPI_I2SPR的MCKOE位为’1’时,作为输出额外的时钟信号引脚使用。输出时钟信号的频率预先设置为256×Fs,其中Fs是音频信号的采样频率。(ADMP441用不到)

3.2参数说明和配置

  ●模式配置(IS_I2S_MODE):设置寄存器SPI_I2SCFG[1:0]选择I2S主模式和方向。

      00: 从设备发送(I2S_Mode_SlaveTx);

    01: 从设备接收(I2S_Mode_SlaveRx);

    10: 主设备发送(I2S_Mode_MasterTx);

  11: 主设备接受(I2S_Mode_MasterRx)。

    主设备输出WS,SCK;从设备WS,SCK作为输入信号。

    发送端输出SD;接收端SD作为输入信号。

图3 I2S模式配置

  ●数据格式(IS_I2S_DATA_FORMAT)

IS_I2S_DATA_FORMAT

IS_I2S_STANDARD

I2S_DataFormat_16b (16位全精度)

I2S_Standard_Phillips(飞利浦规定的格式)

I2S_DataFormat_16bextended(16位扩展32位)

I2S_Standard_MSB(日本格式、普通格式)

I2S_DataFormat_24b(24位帧)

I2S_Standard_LSB(较少使用)

I2S_DataFormat_32b(32位全精度)

I2S_Standard_PCMShort

  ADMP使用飞利浦24bit标准的I2S格式。如果只是读取前16bit的数据,也可以使用。在I2S 配置阶段,如果选择将16位数据扩展到32位声道帧,只需要访问一次寄存器SPI_DR。用来扩展到32位的低16位被硬件置为0x0000。接收时,每次收到高16位半字(MSB) 后,标志位RXNE 置’1’ ,如果允许了相应的中断,则可以产生中断。这样,在2次读和写之间有更多的时间,可以防止下溢或者上溢的情况发生。在使用16位数据扩展到32位帧时,前16位(MSB) 是有意义的数据,后16位(LSB) 被强制为0,该操作不需要软件干预,也不需要有DMA请求(仅需要一次读/ 写操作)。

图4   Phillips_I2S_DataFormat_16bextended

  ADMP取24bit数据时,24位数据帧需要CPU对寄存器SPI_DR进行2 次读或写操作,在使用DMA时,需要2 次DMA传输。对于24位数据,扩展到32位后,最低8位由硬件置0。如果接收0X8EAA33,第一次读SPI_DR得到0X8EAA,第二次读SPI_DR得到0X3300,只有高8位有效,低8位始终是00。

 

图5   Phillips_I2S_DataFormat_16b

3.3代码配置

●GPIO

         //Configure the GPIO Pins for I2S

    GPIO_InitTypeDef GPIO_InitStructure;

         /* Enable GPIOB, GPIOC and AFIO clock */

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOG | RCC_APB2Periph_GPIOF |    RCC_APB2Periph_AFIO, ENABLE);

         /* I2S2 SD, CK and WS pins configuration */

/*I2S2_SD-PB15;I2S2_ CK-PB13;I2S2_WS-PB12*/

         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;

         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

         GPIO_Init(GPIOB, &GPIO_InitStructure); 

●I2S

// Initialise and Configure the Mode for I2S

     I2S_InitTypeDef I2S_InitStructure;

/* Enable I2S peripheral clocks*/

         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

         /*Reset SPI2*/

         SPI_I2S_DeInit(SPI2);

         I2S_InitStructure.I2S_Mode = I2S_Mode_MasterRx;                                 I2S_InitStructure.I2S_Standard = _I2S_Standard_Phillips;           

    I2S_InitStructure.I2S_DataFormat = _I2S_DataFormat_16bextended;

    I2S_InitStructure.I2S_AudioFreq = _I2S_AudioFreq_8k;         

/*I2S clock steady state is low level */

         I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;                       

         I2S_Init(SPI2, &I2S_InitStructure);

         SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);

         I2S_Cmd(SPI2, ENABLE);

         SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);      

●NVIC

//Initialise the Nested Vectored Interrupt Controller
 NVIC_InitTypeDef NVIC_InitStructure;

         NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;

         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

         NVIC_Init(&NVIC_InitStructure);

●SPI2_IRQHandler

extern uint32_t usData;

extern uint32_t usData1;

void SPI2_IRQHandler(void)

{

         usData = SPI_I2S_ReceiveData(SPI2);

         if (SPI_I2S_GetFlagStatus(SPI2, I2S_FLAG_CHSIDE) != SET)   /*if it is left chanel*/

                   usData1 = usData;}

4实验结果

 

图6   逻辑分析仪采集(D1:SCK;D2:WS;D3:SD)

 

 

图7   电压-时间图(声音为语音信号)

5参考资料

  1. ADMP441_cn.pdf
  2. 百度百科
  3. STM32固件库使用手册的中文翻译版.pdf
  4. STM32中文参考手册_V10.pdf