基于MM32F0163D7P的I2S接口的音乐播放器实验

发布时间:2023-08-02  

I2S(Inter-IC Sound)总线,又称集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准。采用了独立的导线传输时钟与数据信号的设计,通过将数据和时钟信号分离,避免了因时差诱发的失真。

MM32F0160系列的I2S 接口有以下主要特征:

  • 半双工通信(仅发送器或接收器)

  • 主操作或从操作

  • 9 位可配置线性预分频器,以达到精确的音频采样频率(8KHz~192KHz)

  • 数据帧格式可配置为 16 位、24 位或 32 位

  • 数据包帧固定为 16 位(16 位有效数据)或 32 位(16 位、24 位、32 位有效数据)

  • 可配置时钟极性(稳定状态)

  • 发送模式下具有下溢标志(仅从机),接收模式下具有上溢标志(主/从机)和发送/接收模式下的帧错误标志(仅从机)

  • 用于传输和接收的 32 位寄存器为两个声道分时复用

  • 数据方向始终是 MSB 优先

  • 支持 I2S 协议:

    • 飞利浦标准

    • MSB 对齐标准(MSB 位向左对齐)

    • LSB 对齐标准(LSB 位向右对齐)

    • PCM 标准(具有短帧同步模式、长帧同步模式的两种方式)

  • 利用 DMA 请求传输数据(32 位宽)

  • 可配置 MCLK 时钟输出来驱动外部音频组件,其比率固定在 256×Fs(其中 Fs 为音频采样频率)


1. MM32的I2S总线简述

MM32F0160的I2S总线与SPI总线复用即SPI_I2S串行外设(串行外设接口与集成电路内置音频总线)。

I2S总线接口与SPI总线接口引脚复用关系如下:

SD: 串行数据(映射在MOSI引脚上),用于发送或接收两次多路数据通道(仅在半双工模式下)。

WS: 声道选择(映射在NSS引脚上),是主模式控制数据的输出信号,或从模式的输入。

CK: 串行时钟(映射在SCK引脚上),是主模式串行时钟的输出,或从模式串行时钟的输入。

MCK: 可选的串行时钟(映射在MISO引脚上),用于驱动外部音频组件(仅当外部音频设备需要时钟输入时使用,由主模式提供)。


2. SPI_I2S功能框图简介

image.png

图1 SPI_I2S功能框图

如上图1所示为SPI_I2S外设的功能框图,SPI_I2S通过“总线接口逻辑”挂载在APB和DMA总线上,TXREG和RXREG寄存器、主模式控制单元和从模式控制单元、主从选择控制、收发控制逻辑以及时钟生成及控制单元,8Byte的发送缓冲和8Byte的接收缓冲构成,时钟控制单元由Spbrg和Pclk提供时钟。


3. SPI_I2S外设的I2S时钟预分频器

I2SCLK时钟由系统APB时钟提供,I2S模块的预分频器电路结构如下图2所示:

image.png

图2 SPI_I2S时钟预分频器电路结构图

如上图2所示,当MCKOE位为‘0’时芯片不需要输出MCK时钟,预分频器直接将I2SCLK分频到CK;当MCKOE位为‘1’时芯片会输出MCK时钟,预分频器将I2SCLK分频后得到MCK,然后再经过分频处理才得到CK(分频倍数由CHLEN选择为 4或8)。


音频采样率一般常用 192KHz,96 KHz,48 KHz,44.1 KHz,32 KHz,22.05 KHz,16 KHz,11.025KHz,8 KHz。因此可根据 I2S 时钟分频器的电路功能式样,配置寄存器 I2SCFGR中的I2SDIV[8:0]、MCKOE和CHLEN 位来得到期望的音频采样率。


I2S 传输数据时,比特率计算公式如下表1所示(CK 输出一个时钟周期对应传输 1 比特数据,因此比特率 = CK频率FCK)。

image.png

表1

音频采样率(Fs)和 I2S 比特率的关系由如下的公式定义:

Fs = I2S 比特率/(通道长度×通道数)= FCK /(通道长度×通道数)

注:通道长度,即数据包帧长度,可配置为16位或32位;通道数为左右声道,值固定为2。


综上所述,根据I2SDIV[8: 0]、MCKOE和CHLEN位的配置情况, 得到音频采样率与FI2SCLK(APB时钟频率)的关系如下表2所示:

image.png

表2


4. SPI_I2S外设的I2S接口的音乐播放器

工作原理介绍

基于I2S接口的音乐播放器工作原理框图如下图3所示:

image.png

图3 I2S接口的音乐播放器原理框图

如上图3所示为I2S接口的音乐播放器工作原理框图:

MM32F0160作为Host MCU其SPI1接口用于驱动25WQ80存储器用于写入和读取存储的音频文件。


MCU端I2S2(SPI2_I2S2)接口工作在从机模式,MCLK不输出时钟。通过PWM输出12MHz的REF_Clock给NAU88C22音频编解码芯片MCLK脚,NAU88C22内部PLL合成稳定的12.288MHz作为内部IMLCK主时钟。NAU88C22 BCLK输出bit clock时钟到MCU端I2S2_CK作为音频采样时钟。I2S2_WS接口即FS用于分时切换左右声道。I2S2_SD接口即DACIN输出从25WQ80存储器读取的音频信号流DAC Stream传输给NAU88C22音频编解码芯片。


MCU端I2C_SDA和I2C_SCL接口用于设置NAU88C22工作模式和参数。NAU88C22 DAC输出可以选择从Speaker PA输出推喇叭或者从Earphone PA耳机接口输出推动耳机。

5. I2S接口的GPIO初始化

I2S接口GPIO的初始化代码如下所示:


void I2S2_GPIO_Init(void)

{    

    GPIO_InitTypeDef GPIO_InitStruct;

    

    RCC_GPIO_ClockCmd(GPIOB, ENABLE); 

    

    GPIO_StructInit(&GPIO_InitStruct);

    /* PB12 I2S2_WS */    

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_12;    

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;    

    GPIO_Init(GPIOB, &GPIO_InitStruct); 


    /* PB13 I2S2_CK */    

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_13;    

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;    

    GPIO_Init(GPIOB, &GPIO_InitStruct); 


    /* PB14 I2S2_MCLK */    

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_14;    

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IPU;    

    GPIO_Init(GPIOB, &GPIO_InitStruct); 


    /* PB15 I2S2_SD */    

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_15;    

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;    

    GPIO_Init(GPIOB, &GPIO_InitStruct);


    /* PB12 AF I2S2_WS */    

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_0); 


    /* PB12 AF I2S2_CK */    

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0);


    /* PB12 AF I2S2_MCLK */    

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_0); 


    /* PB12 AF I2S2_SD */    

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0);

}

6. I2S从机的初始化

I2S从机的初始化步骤如下所示:


配置SPI_I2S_GCTL.SPIEN位为‘1’,开启模块使能;

配置SPI_I2S_GCTL.MODE位为‘0’,使模块功能为从模式;

配置寄存器SPI_I2S_I2SCFGR中的 I2SDIV[8:0]、 DATLEN 和 CHLEN 位,以符合希望得到的音频采样频率及数据包帧格式;

配置SPI_I2S_I2SCFGR.SPI_I2S位为‘1’,使能 I2S 传输功能;

配置寄存器SPI_I2S_I2SCFGR中的I2SSTD[1: 0]、 PCMSYNC 位,选择I2S传输时使用的通信标准;

配置SPI_I2S_GCTL.DMAMODE 位为‘1’,以启用 DMA 传输;

开启半双工传输许可, 即配置寄存器SPI_I2S_GCTL 中的 TXEN 或 RXEN 位为‘1’ (TXEN、 RXEN不可同时配置为‘1’)。

注意:从模式下发送时,在检测到WS的边沿之前,需要对寄存器SPI_I2S_TXREG进行1次数据写入操作;而且,从模式下接收时,在配置RXEN位为‘1’之前,需要一直维持WS输入信号在高电平。


I2S从机的初始化代码如下所示:


void I2S2_Slave_Init(void)

{

    RCC_APB1PeriphClockCmd(RCC_APB1ENR_SPI2, ENABLE); /* Enable SPI2_I2S Clock */


    SPI2- >CCTL &= ~SPI_CCTL_LSBFE;  /* MSB first enable */

    SPI2- >CCTL &= ~SPI_CCTL_CPHA;   /* Clock phase select start second clock */    

    SPI2- >CCTL |= SPI_CCTL_CPHASEL; /* CPHA polarity select start second clock */

    SPI2- >CCTL |= SPI_CCTL_SPILEN;  /* SPI character length 8bit data */

    SPI2- >CCTL |= SPI_CCTL_CPOL;    /* Clock polarity select high */

    SPI2- >CCTL |= SPI_CCTL_TXEDGE;  /* Transmit data edge for i2s bus */


    SPI2- >I2SCFGR &= ~SPI_I2SCFGR_MCKOE; /* I2S master clock output disable */  

    SPI2- >I2SCFGR &= ~SPI_I2SCFGR_CHLEN; /* Vocal tract length 16bit */    

    SPI2- >I2SCFGR |= SPI_I2SCFGR_DATLEN_32; /* Audio data width 32 */

    SPI2- >I2SCFGR |= SPI_I2SCFGR_I2SSTD_Philips; /* I2S STD Philips */

    SPI2- >I2SCFGR |= SPI_I2SCFGR_SPI_I2S; /* SPI/I2S module function selection */


    SPI2- >GCTL &= ~SPI_GCTL_MODE;           /* I2S Slave mode */

    SPI2- >GCTL |= SPI_GCTL_DW_8_32;         /* double-word data select signal */

    SPI2- >GCTL |= SPI_GCTL_DMAMODE;         /* DMA access mode enable */

    SPI2- >GCTL |= SPI_GCTL_TXEN;            /* I2S Transmit enable */

    SPI2- >GCTL |= SPI_GCTL_INTEN;           /* SPI_I2S interrupt enable */

    SPI2- >GCTL |= SPI_GCTL_SPIEN;           /* Enable I2S */    

}

7. I2S发送DAC音频信号流

MM32F0163D7P的I2S2发送DAC音频信号流使用DMA中断发送,代码接口如下所示:


void I2S2_TxData_DMA_Interrupt(uint8_t *Buffer, uint8_t datasize)

{    

    DMA_InitTypeDef  DMA_InitStruct;

    NVIC_InitTypeDef NVIC_InitStruct;


    RCC_DMA_ClockCmd(DMA1, ENABLE);/* Enable DMA1 Clock */


    DMA_DeInit(DMA1_Channel5);


    DMA_StructInit(&DMA_InitStruct);                            DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2- >TXREG);   /* SPI2_I2S2 BaseAddr */    

    DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)(Buffer);         /* Memory buffer for music data*/    

    DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralDST;    

    DMA_InitStruct.DMA_BufferSize         = datasize;                   /* Left and Right channel audio buffer size */    

    DMA_InitStruct.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;    

    DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;       /* memory increment */    

    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; /* half word transfer */    

    DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    /* half word transfer */    

    DMA_InitStruct.DMA_Mode               = DMA_Mode_Normal;                /* Normal mode */    

    DMA_InitStruct.DMA_Priority           = DMA_Priority_Medium;            /* DMA Priority Medium */    

    DMA_InitStruct.DMA_M2M                = DMA_M2M_Disable;                /* Disable memory to memory transfer */    

    DMA_InitStruct.DMA_Auto_reload        = DMA_Auto_Reload_Enable;         /* Enable auto reload */    

    DMA_Init(DMA1_Channel5, &DMA_InitStruct);    

    DMA_ClearFlag(DMA1_FLAG_TC5);   /* Clear transfer complete flag */    

    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); /* Enable DMA Channel5 SPI2_I2S2 DMA transfer complete interrupt */     NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel4_7_IRQn; /* Set SPI2_I2S2 DMA Channel NVIC intterrupt priority */    

    NVIC_InitStruct.NVIC_IRQChannelPriority = 0x01;    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;            /* Enable NVIC IRQChannel */    

    NVIC_Init(&NVIC_InitStruct); 


    DMA_Cmd(DMA1_Channel5, ENABLE); /* Enable SPI2_I2S2 DMA Channel5 */    

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    基于C89C58RD+单片机与VS1003实现MP3播放器设计;引 言 随着电子技术的发展, MP3 播放器是目前市场上流行的消费类数码产品之一, 具有大容量、高音质、小巧......
    、IMY等,其中MIDI是目前支持度最高的铃音文件格式,它的文件占用空间小,表现力强,几乎已经成为目前和弦铃声手机的标准配置。 手机中的MIDI和弦音乐是通过内置高集成度的和弦芯片播放MIDI音乐......
    和VS1003B音频解码器实现了MP3音乐播放。基于Android系统开发的客户端软件采用手机控制,完成了手机端与控制端之间的数据传输,实现了手机远程对音乐播放器的控制。结果表明,该系......
    年是iPod引领移动音乐播放的黄金时期。截至2006年iPhone手机发布前,iPod收入占当年苹果公司营收的比例达到40%。随着2007年集成音乐播放器功能的iPhone发布后,iPod才让位给智能手机......
    还原为WAV文件后,与压缩前的WAV文件内容相同。这种压缩与ZIP的方式类似,但FLAC的压缩比率大于ZIP和RAR,因为FLAC是专门针对PCM音频的特点设计的压缩方式。而且可以使用播放器直接播放......
    制式中波广播  56KBPS=话音  64KBPS=增加话音(手机铃声最佳比特率设定值、手机单声道MP3播放器最佳设定值)  112KBPS=FM调频立体声广播  128KBPS=磁带(手机立体声MP3播放器最佳设定值、低档......
    子专业的同学也可以尝试做一下。 图2 电子卡琳巴琴 工作原理也非常简单,当程序检测到有按键按下时,ESP32 通过蓝牙发送相应的MIDI 指令到手机手机收到相关的指令后,在手机上播放对应的音符。 讲完了工作原理,接下......
    应用在便携设备视频播放的高速OLED驱动芯片;随着科技的进步,视频播放应用已广泛进入商业电子产品中(如移动电话和MP3播放器)。移动电话和MP3播放器是当前最热门、发展最快的两种商业电子产品。手机......
    到主处理器上,实现多任务的调度管理。系统工作时,通过操作播放器上的配置按钮,设置服务器和用户终端的相关网络配置,点击播放器中的连接按钮,发送连接服务器请求,服务器收到用户终端的连接请求,验证......
    缺省的CBR(固定采样频率)技术可以以固定的频率采样一首歌曲,而VBR(可变采样频率)则可以在音乐“忙”的时候加大采样的频率获取更高的音质,不过产生的MP3文件可能在某些播放器上无法播放。把VBR的级......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>