TA的每日心情 | 怒 2018-11-20 13:41 |
---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I
|
STM32F769-DISCO 上面有个WM8994可以用于音频解码。WM8994具有高性能低功耗体积小等优点,曾用在早期的三星安卓手机上用到。下面的测试主要是使用WM8994播放WAV文件。
1、串行音频接口(SAI)
SAI 接口(串行音频接口)灵活性高、配置多样,可支持多种音频协议。该接口适用于许多立体声或单声道应用。例如,它可配置为支持 I2S 标准、 LSB 或 MSB 对齐、 PCM/DSP、TDM 和 AC’97 等协议。将音频模块配置为发送器时, SAI 接口可提供 SPDIF 输出。SAI 通过两个完全独立的音频子模块来实现这种灵活性和可配置性。每个模块都有自己的时钟发生器和 I/O 线控制器。SAI 可以配置为主模式或配置为从模式。音频子模块既可作为接收器,又可作为发送器;既可与另一模块同步,又可以不同步。
SAI 主要由两个各自带有时钟发生器的音频子模块组成,每个音频模块集成一个 32 位移位寄存器,该寄存器由模块自身的功能状态机控制。数据存储和读取都是通过专用的 FIFO 来完成。 FIFO 可通过 CPU 访问,也可通过 DMA 访问以减轻 CPU 的通信负担。每个音频模块是独立的。这两个音频子模块可彼此同步。SAI 中指定音频模块的 4 个专用引脚IO口( SD、 SCK、 FS、 MCLK)。
功能框图如下:
STM32F769-DISOC 上面的WM8994通过SAI1_Block_A和MCU进行解码数据通信,WM8994的初始化和各项配置则通过IIC实现。
2、WAV格式文件
WAVE文件是计算机领域最常用的数字化声音文件格式之一,它是微软专门为Windows系统定义的波形文件格式(Waveform Audio)。WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型。简单的理解WAV文件有一个文件头和数据部分组成,文件头里面包含该WAV的详细信息。一个典型的文件头格式如下:
这个文件头共有44字节,不同的格式文件头可能长度不同,为了方便处理我使用开源软件Audacity将WAV的头文件格式都转为相同的44字节模式,其他的参数为立体声44.1KHZ.
3、软件解码
播放的WAV文件放在TF卡里面,文件系统使用开源的FATFS,为了支持较长的歌曲名字,需要在FATFS中打开长文件名支持模式。同时为了支持中文显示,我把汉字点阵放到了
STM32F769-DISCO 的外置NORFLASH里面,具体的操作可以查看之前的帖子。
WAV的播放是使用DMA 循环模式把数据从SD卡搬送到codec进行解码,其中DMA使能了HalfTransfer和TransferComplete来不断的更新要解码的数据文件。
最开始的时候先将要解码的缓存写满,然后开始DMA传输,当传输完成一半时在使能标记开始更新前半部缓存,等传输完成继续更新后半部分缓存,这样可以实现更新缓存和
界面数据“同时进行”,当然这样做的前提是更新缓存数据速度要快于解码的数据,通过测试STM32F7完全没有压力。
程序的流程如下:
- 先扫描SD卡找到WAV文件,将找到的WAV文件信息放入到一个链表中。
- 显示找到的WAV文件名称到LCD上,并更新要播放的文件(名称为绿色字体)。
- 根据预设的要播放的文件序号找到要要播放的WAV文件的信息,从SD卡里面读取填充播放缓存。
- 开始播放WAV后不断的填充播放缓存直到播放完成。
- 播放完成一个WAV文件后,根据播放模式(单曲循环、列表循环、随机循环)播放下一个WAV文件。
- 播放的过程中可以通过用户按键切换下一个WAV文件进行播放。
程序下载后的:
使用按键切换歌曲:
mian 函数如下:
- _listfile_list *playfile;
- CPU_CACHE_Enable();
- HAL_Init();
- SystemClock_Config();
- USART1_Init();
- HAL_Delay(200);
- BSP_LED_Init(LED_GREEN);
- BSP_LCD_Init();
- BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS);
- BSP_LCD_SetTextColor(LCD_COLOR_RED);
- BSP_LCD_SetBackColor(LCD_COLOR_BLACK);
- HAL_Delay(500);
- BSP_QSPI_Init();
- CopyFont2NorFlash();
- BSP_QSPI_EnableMemoryMappedMode();
- CheckGBKFont4NorFlash();
- BSP_LCD_Clear(LCD_COLOR_WHITE);
- FatFs_SD_Init();
- wavfilenum = ScanWavFiles("/");
- PrintfWavFileTest();
- UpdateWavFileColor(playfilepos,playfilepos);
- playfile = list_search(WavFileList, playfilepos);
- if(playfile == NULL)while(1);
- //´
- wavFileLen = OpendWavFile(playfile->filename);
- //
- ReadWaveFile(BuffHead, PLAY_HEADER);
- //
- ReadWaveFile((uint8_t *)PlayBuff, PLAY_BUFF_SIZE * 2);
- Playback_Init();
- /* Start the playback */
- if(0 != audio_drv->Play(AUDIO_I2C_ADDRESS, NULL, 0))
- {
- while(1);
- }
- if(HAL_OK != HAL_SAI_Transmit_DMA(&SaiHandle, (uint8_t *)PlayBuff, PLAY_BUFF_SIZE))
- {
- while(1);
- }
[color=rgb(51, 102, 153) !important]复制代码
需要注意的是程序里面默认播放是44.1KHZ立体声的WAV文件,如果是其他的格式的要在播放之前更新SAI的配置。
- SaiHandle.Init.AudioMode = SAI_MODEMASTER_TX;
- SaiHandle.Init.Synchro = SAI_ASYNCHRONOUS;
- SaiHandle.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
- SaiHandle.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
- SaiHandle.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
- SaiHandle.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;
- SaiHandle.Init.Protocol = SAI_FREE_PROTOCOL;
- SaiHandle.Init.DataSize = SAI_DATASIZE_16;
- SaiHandle.Init.FirstBit = SAI_FIRSTBIT_MSB;
- SaiHandle.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
- SaiHandle.FrameInit.FrameLength = 32;
- SaiHandle.FrameInit.ActiveFrameLength = 16;
- SaiHandle.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
- SaiHandle.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
- SaiHandle.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
- SaiHandle.SlotInit.FirstBitOffset = 0;
- SaiHandle.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
- SaiHandle.SlotInit.SlotNumber = 2;
- SaiHandle.SlotInit.SlotActive = (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1);
[color=rgb(51, 102, 153) !important]复制代码
4、最后
使用STM32F769-DISOC配合论坛之前送的小音箱,播放音乐的效果和我手机电脑播放的听不出区别。我用手机语音备忘录录制了一段放在附件里面,感兴趣可以试听下。
PS:附件的源码里面我默认关闭了汉字库下载到NORFLASH,如果是第一次运行程序请打开相应的宏定义加载字库。
|
|