关注分享主机优惠活动
国内外VPS云服务器

I2S公共汽车

简单介绍,又称总线,也称集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而开发的总线标准。该总线专用于音频设备之间的数据传输,并广泛用于各种多媒体系统中。位,这两个位用于选择标准,设置为,选择飞利浦标准。

一、I2S I2S(也称IIS,即Inter IC Sound)总线又称集成电路内置音频总线,是飞利浦为数字音频设备之间的音频数据传输而制定的总线标准。这种总线专用于音频设备之间的数据传输,广泛应用于各种多媒体系统。它采用沿独立导线传输时钟和数据信号的设计。通过分离数据和时钟信号,避免了时差带来的失真,节省了用户购买专业设备抵抗音频抖动的成本。特性●支持全双工/半双工通信●支持主/从模式设置●8位可编程线性预分频器、精确的音频采样频率(8~192Khz) ●支持16位/24位/32位数据格式●固定数据包帧为16位(仅16位数据帧)或32位(可容纳16位/24位数据帧)●可编程时钟极性●支持MSB对齐(左对齐)、LSB对齐(右对齐)和飞利浦标准

二。STM32F4的I2S框图和信号I2S框图I2S与SPI共享。I2S功能可以通过设置SPI_I2SCFGR寄存器的I2SMOD位来启动,I2S接口使用与SPI几乎相同的引脚、标志和中断。

信号1,SD:串行数据(映射到MOSI引脚)用于在两个时分复用数据通道上发送或接收数据(仅限半双工模式)。2、WS:字选(映射到NSS引脚),即左右时钟,用来切换左右声道的数据。WS频率等于音频信号采样率(fs)。3、CK:串行时钟(映射到SCK管脚),即位时钟,是主机模式下的串行时钟输出,从机模式下的串行时钟输入。CK频率=WS频率(fs)216(16位宽),如果是32位宽,则为:CK频率=WS频率(fs)232(32位宽)。4、I2S2ext_SD和I2S3ext_SD:用于控制I2S全双工模式的附加串行数据引脚(映射到MISO引脚),仅在全双工模式下使用。5、MCK:主时钟输出。当I2S配置为主模式(且SPI_I2SPR寄存器中的MCKOE位置1)时,使用该时钟,时钟频率为256×fs,fs:音频信号的采样频率。

STM32F4支持I2S全双工模式。除I2S2和I2S3外,还可以使用两个额外的I2S,称为扩展I2S(I2S2_ext、I2S3_ext)。框图如下:扩展I2S (I2Sx_ext)只能在全双工模式下使用。I2Sx_ext始终在从机模式下工作。I2Sx和I2Sx_ext均可用于发送和接收。

帧格式STM32F4的I2S支持四种数据和帧格式的组合,即:1 .将16位数据封装在16位帧中;2、将16位数据封装在32位帧中;3、将24位数据封装在32位帧中;4、将32位数据封装在32位帧中;

当16位数据封装在32位帧中时,前16位(MSB)为有效位,16位LSB被强制清零,无需任何软件操作或DMA请求(仅一次读/写操作)。如果应用选择DMA,则24位和32位数据帧需要由CPU或DMA读取或写入两次。对于24位数据帧,硬件会将8位非有效位扩展为0位的32位数据帧。四帧标准:1、飞利浦标准;2、MSB对齐(左对齐)标准;3、LSB对齐(右对齐)标准;4、PCM标准;I2S飞利浦标准帧24位数据,32位帧格式I2S飞利浦标准,使用WS信号来指示当前正在发送的数据所属的通道。该信号从当前通道数据的第一位(MSB)之前的一个时钟开始有效。发送方在时钟信号(ck)的下降沿改变数据,接收方在上升沿读取数据。WS信号也在CK的下降沿发生变化。24位模式下的数据传输需要读取或写入SPI_DR两次。比如,要发送数据0X8EAA33,需要两次写入SPI_DR,第一次:0X8EAA,第二次:0X33xx(xx可以是任意值),这样就发送了0X8EAA33。注意:从SD卡读取的24位WAV数据流,低位字节在前,高位字节在后。比如我们读取一个通道(24位)的数据,存储在buf[3]中,我们要通过SPI_DR发送这个24位的数据,过程如下:SPI _ DR =((U16)BUF[2]1102402。//11.025Khz采样率{1600,213,2,13,0},//16Khz采样率{2205,429,4,9,1},//22.05Khz采样率{3200,213,2,6,1},//。0}、//44.1Khz采样率{4800,258,3,3,1}、//48Khz采样率{8820,316,2,3,1}、//88.2Khz采样率{9600,344,2,3,1}、/。0}、//176.4Khz采样率{19200,393,2,2,0}、//192Khz采样率};5.将I2S寄存器1和SPI_I2S配置寄存器(SPI _ I2 SCFGR)的I2Smod位置1,以选择i2s模式。注意,当I2S/SPI被禁止时,该位必须置1。I2SE位置1时,使能I2S外设,I2SMOD位置1后,该位必须置1。用于配置I2S模式的I2SCFG[1:0]位设为10,选择主模式(传输)。用于选择I2S标准的I2std [1: 0]位设为00,选择飞利浦标准。CKPOL位用于设置空闲时钟电平,该位设为0,空闲时钟电平为低电平。DATLEN[1:0]位,用于设置数据长度,00,代表16位数据;01表示24位数据。CHLEN位,用于设置通道长度,即帧长,0表示16位;1,这意味着32位。2.将SPI_I2S预分频器寄存器(SPI_I2SSPR)中的MCKOE置1,并开启MCK输出。ODD和I2SDIV根据不同的fs设置。3.PLLI2S配置寄存器(RCC_PLLI2SCFGR)该寄存器用于配置两个系数,即PLLi2S和PLLI2SN。PLLi2S的范围为2~ 7,PLLI2SN的范围为192~432。同样,这两个也是根据fs的值来设置的。

I2S初始化步骤1)初始化WM8978这个过程是对上节课介绍的WM8978的几十个寄存器进行配置,包括软复位、DAC设置、输出设置、音量设置。2)初始化I2S这个过程主要设置SPI_I2SCFGR寄存器、I2S模式、I2S标准、时钟空闲电平和数据帧长度,最后开启I2S TX DMA使能I2S外设。3)分析WAV文件,得到音频信号的采样率和位数,设置I2S时钟分频器分析WAV文件,得到音频信号的采样率(fs)和位数(16或24位)。根据这两个参数,设置I2S时钟分频器,其通过上述的查找表方法来设置。4)设置DMA I2S播放音频。通常,DMA用于传输数据。这里我们用I2S2,它的TX用DMA1数据流4的通道0来传输数据。而且STM32F4的DMA有双缓冲机制,可以提高效率。这里我们设置DMA1数据流4为双缓冲周期模式,外设和存储器16位宽,开启DMA传输完成中断(方便填充数据)。5)编写DMA传输的中断服务函数,方便音频数据的填充。我们使用DMA传输来完成中断。每当发送一个缓冲数据,硬件自动切换到下一个缓冲区,同时进入中断服务功能,将数据填充到发送的缓冲区。如下图所示:6)开始DMA传输,填充数据。最后,只要启动DMA传输,及时将WAV数据填充到两个DMA缓冲区中即可。此时,您可以听到WM8978的耳机和扬声器通道中播放的音乐。七、播放WAV文件代码//播放一个WAV文件//fname:wav文件路径。//返回值://KEY0_PRES:下一首//KEY1_PRES:上一首//其他:错误u8wav _ play _ song(u8 * fname){ u8 key;u8t = 0;u8 resu32 fillnumaudio dev . file =(FIL *)mymalloc(SRAMIN,sizeof(FIL));audio dev . i2sbuf 1 = mymalloc(Sr Amin,WAV _ i2s _ TX _ DMA _ BUFSIZE);audio dev . i2sbuf 2 = mymalloc(Sr Amin,WAV _ i2s _ TX _ DMA _ BUFSIZE);audiodev.tbuf=mymalloc(SRAMIN,WAV _ i2s _ TX _ DMA _ BUFSIZE);if(audio dev . file & & audio dev . i2sbuf 1 & & audio dev . i2sbuf 2 & & audio dev . tbuf){ RES = wav _ decode _ init(fname,& wav ctrl);//获取文件信息if(res==0)//成功解析文件{if (wavctrl。bps = = 16) {wm8978 _ i2s _ CFG (2,0);//飞利浦标准,16位数据长度i2s2 _ init (i2s _标准_飞利浦,i2s _模式_ mastertx,i2s _ cpol _ low,i2s _ dataformat _ 16b扩展);//飞利浦标准,主机发送,时钟低,16位扩展帧长} else if (wavctrl。bps = = 24) {wm8978 _ i2s _ CFG (2,2);//飞利浦标准,24位数据长度i2s2 _ init (i2s _标准_飞利浦,i2s _模式_ mastertx,i2s _ cpol _ low,i2s _数据格式_ 24b);//飞利浦标准,主机发送,时钟低电平有效,24位扩展帧长} i2s2 _ samplerate _ set (wavctrl。samplerate);//设置采样率i2s 2 _ tx _ DMA _ init(audio dev . i2sbuf 1,audiodev.i2sbuf2,wav _ i2s _ tx _ DMA _ bufsize/2);//配置txd mai2s _ tx _ callback = wav _ i2s _ DMA _ tx _ callback;//回调函数引用wav _ i2s _ DMA _ callback audio _ stop();res=f_open(audiodev.file,(TCHAR*)fname,FA _ READ);//打开文件if(RES = = 0){ f _ lseek(audio dev . file,wav ctrl . data start);//跳过文件头fill num = wav _ buffill(audiodev . i2sbuf 1,wav _ i2s _ tx _ DMA _ bufsize,wav ctrl . bps);fill num = WAV _ buffill(audio dev . i2sbuf 2,WAV_I2S_TX_DMA_BUFSIZE,WAV ctrl . bps);audio_start()。while(RES = = 0){ while(wav transfered = = 0);//等待wav传输完成;wav transfered = 0;if(fillnum!=WAV_I2S_TX_DMA_BUFSIZE)//播放结束?{ res = KEY0 _ PRES打破;} if(wavwitchbuf)fill num = WAV _ buff il(audio dev . i2sbuf 2,WAV_I2S_TX_DMA_BUFSIZE,WAV ctrl . bps);//Fill buf 2 else Fill num = wav _ buff Fill(audiodev . i2sbuf 1,wav _ i2s _ tx _ DMA _ bufsize,wav ctrl . bps);//Fill buf 1 while(1){ KEY = KEY _ Scan(0);If(key==WKUP_PRES)//暂停{if (audiodev。状态& 0x01) audiodev。状态& = ~(1t = 0;LED0=!LED0} if((audio dev . status & 0x 01)= = 0)delay _ ms(10);else break} }音频_停止();} else res = 0XFF} else res = 0XFF} else res = 0XFFmyfree(SRAMIN,audio dev . tbuf);//释放内存myfree(SRAMIN,audiodev . i2sbuf 1);//释放内存myfree(SRAMIN,audiodev . i2sbuf 2);//释放内存myfree(SRAMIN,audio dev . file);//释放内存返回res}音乐播放到此为止!!!

未经允许不得转载:主机频道 » I2S公共汽车

评论 抢沙发

评论前必须登录!