[牛人杂谈] 新唐的I2S,初始化问题

[复制链接]
5075|11
 楼主| mintspring 发表于 2016-5-15 12:10 | 显示全部楼层 |阅读模式
新唐的I2S接口可以外接audio codec,例如:接新唐的NAU8822,NAU8810等。一般支持I2S数据格式和MSB Justified数据格式,有一些支持PCM mode A和PCM mode B格式。可以作为I2S Master 和I2S slave,一般情况下都是作为I2S slave使用,不然播放不同采样率的音频,MCLK引脚出不同的频率给audio codec比较困难。
I2S 接口如下,共5根脚:
QQ截图20160515121016.png
²  I2SMCLK:由 I2S Master 提供。I2S 做 Master 时提供 MCLK 给 audio codec,它应该=采样频率*2*256,例如:如果采样频率=44.1K 则 MCLK 应该给=44.1*2*256= 22.5792M
²  LRCLK:由 I2S Master 提供。是左右声道的时钟信号
²  I2SDO:I2S 数据输出
²  I2SBCLK:由 I2S Master 提供。I2S 收/发数据时每个 bit 的时钟。它应该=分辨率*采样率*通道数。例如: 16bit, 48K,stereo 的数据,BCLK 输出的频率=16×48×2= 1536K

²  I2SDI:I2S 数据输入

 楼主| mintspring 发表于 2016-5-15 12:11 | 显示全部楼层
下面的波形是MSB Justified的波形,左声道LRCLK拉high, 右声道LRCLK拉low。MSB优先, BCLK上升沿latch数据。各种不同的I2S格式,波形也是不同的。
1.jpg
下面以M451的I2S 为例说明I2S的用法。M451 I2S和SPI1两个IP共用逻辑电路,所以I2S的说明放在SPI IP里面。SPI1和SPI2可以作为2个I2S接口使用,而SPI0是单纯的SPI。
该I2S发送和接收各有4级32bit FIFO,一般我们设定TX/RX 阀值中断是2。对于TX来说,当发送 FIFO中有效数据<=2时,会发生TX 阀值中断;对于RX来说,当接收FIFO中的有效数据>=2时,会发生RX 阀值中断。

也就是将该4级FIFO分成2块做ping-pong。对于发送来说先把4个FIFO都填满,然后发生TX threshold中断时表示第一块已经发送出去,可以填2笔数据到TX FIFO中,此时TX在发送第二块;再次发生TXthreshold中断时,表示第二块已经发送出去,可以填2笔数据到TX FIFO中。对于RX 也是一样的,每次发生RX 阀值中断,可以读两笔数据出来。下面的democode,I2S作为slave,数据宽度16bit,stereo,I2S 波形。采样率由I2S Master决定。只demo I2S可以收发数据而已,如果连接了audiocode,还要通过I2C去初始化audio codec。我们的 M451 BSP里面目录SampleCode\StdDriver下面有2个demo :I2S_Master和I2S_Slave。将两片M451 板子的I2S对接,一个跑I2S_Master,一个跑I2S_Slave,就可以测试I2S的特性。

 楼主| mintspring 发表于 2016-5-15 12:12 | 显示全部楼层
  1. void I2S_Init(void)
  2. {     uint32_t u32RxValue1, u32RxValue2;

  3.     /* SPI1选择PCLK1作为时钟源,默认PCLK1的时钟等于HCLK的时钟 */
  4.     CLK_SetModuleClock(SPI1_MODULE, CLK_CLKSEL2_SPI1SEL_PCLK1, MODULE_NoMsk);

  5.     /* 使能SPI1的时钟 */
  6.     CLK_EnableModuleClock(SPI1_MODULE);
  7. /* 配置 SPI1 相关引脚 */
  8.     /* GPA[7:4] : SPI1_CLK (I2S1_BCLK), SPI1_MISO (I2S1_DI), SPI1_MOSI (I2S1_DO), SPI1_SS (I2S1_LRCLK) */
  9.     SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk |
  10. SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);
  11.     SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA4MFP_SPI1_SS | SYS_GPA_MFPL_PA5MFP_SPI1_MOSI | SYS_GPA_MFPL_PA6MFP_SPI1_MISO | SYS_GPA_MFPL_PA7MFP_SPI1_CLK);

  12.         /* I2S1使用SPI1接口,配置为16bit, Stereo,I2S format,使能TX和RX FIFO threshold中断,连续发送数据0xAA00AA01, 0xAA02AA03, ..., 0xAAFEAAFF 每个发送5000次,然后改变TX的值*/
  13.     /* I2S 外设时钟频率等于 PCLK1 的时钟频率 */
  14.     I2S_Open(SPI1, I2S_MODE_SLAVE, 0, I2S_DATABIT_16, I2S_STEREO, I2S_FORMAT_I2S);  
  15.     /* 初始化发送数据计数 */
  16.     g_u32DataCount = 0;
  17.     /* 初始化发送/接收数据 */
  18.     g_u32TxValue = 0xAA00AA01;     u32RxValue1 = 0;     u32RxValue2 = 0;
  19.     /* 使能TX/RX threshold 中断 */
  20.     I2S_EnableInt(SPI1, I2S_FIFO_TXTH_INT_MASK| I2S_FIFO_RXTH_INT_MASK);
  21.     NVIC_EnableIRQ(SPI1_IRQn);

  22.     while(1)
  23.     {
  24.         /* 改变要发送的数据 */
  25.         if(g_u32DataCount >= 50000)
  26.         {
  27.             g_u32TxValue = 0xAA00AA00 | ((g_u32TxValue + 0x00020002) & 0x00FF00FF); /* g_u32TxValue: 0xAA00AA01, 0xAA02AA03, ..., 0xAAFEAAFF */             printf("TX value: 0x%X\n", g_u32TxValue);             g_u32DataCount = 0;
  28.         }
  29.     }
  30. }  uint32_t g_au32PcmRecBuf[96];
  31. /*I2S1 中断处理函数*/
  32. void SPI1_IRQHandler()
  33. {    uint32_t u32I2SIntFlag;     uint32_t i, u32Idx;
  34.      u32I2SIntFlag = SPI1->I2SSTS;     /*发生Tx Threshold中断*/     if(u32I2SIntFlag & SPI_I2SSTS_TXTHIF_Msk)
  35.     {
  36.          /* 写2 笔TX 值到 TX FIFO */
  37.     I2S_WRITE_TX_FIFO(SPI1, g_u32TxValue);         I2S_WRITE_TX_FIFO(SPI1, g_u32TxValue);         g_u32DataCount += 2;
  38. }
  39. /*发生Rx Threshold中断*/ if(u32I2SIntFlag & SPI_I2SSTS_RXTHIF_Msk)
  40. {           g_au32PcmRecBuf[g_u32RecPos++] = I2S_READ_RX_FIFO(SPI1);      g_au32PcmRecBuf[g_u32RecPos++] = I2S_READ_RX_FIFO(SPI1);      if(g_u32RecPos >= 96)                    g_u32RecPos = 0;
  41. }
  42. }
  43.   
上面的代码在M451SeriesBSP_CMSIS_v3.00.005里面,SampleCode\StdDriver\I2S_Slave目录下。
上面的demo,通过I2S发送一些数据出去,就是说I2S不一定非得传输音频数据,也可以拿来单纯的传输数据用。通过RX收到的数据我们也没有做进一步的处理,只是放在变量g_au32PcmRecBuf中。如果做USB声卡应用,g_au32PcmRecBuf里面的数据可以通过USB发送到PC上。

lovecat2015 发表于 2016-5-15 22:38 | 显示全部楼层
这个上升沿和下降沿的变化和音频芯片能完全对应上吗
lp0532 发表于 2018-2-24 12:06 | 显示全部楼层
咨询一下,新唐这个i2s 做为master时,时钟是从mcu产生的?还是从需要外接时钟源?
734774645 发表于 2018-2-24 12:15 | 显示全部楼层
作为主机时候肯定需要自己提供时钟源。从机时候,有主机MCU提供
xixi2017 发表于 2018-2-26 20:40 | 显示全部楼层
用这个可以做音频应用
dongnanxibei 发表于 2018-2-26 21:06 | 显示全部楼层
很不错的用法
yiyigirl2014 发表于 2018-2-27 13:19 | 显示全部楼层
这种格式怎么变成声音?
643757107 发表于 2018-2-27 18:23 | 显示全部楼层
音频有不少这个系列的芯片和方案提供
jiekou001 发表于 2018-2-27 19:07 | 显示全部楼层
音频系列好像都是用这个接口。
jiekou001 发表于 2018-2-27 19:07 | 显示全部楼层
如果带USB,不知道可以用这个做USB声卡不。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

303

主题

4964

帖子

24

粉丝
快速回复 在线客服 返回列表 返回顶部