本篇是此系列的最后一篇,重点是SAI(Serial audio interface).
前奏介绍
众所周知,声频、视频是人机界面的核心部分,有了它们,计算机的人性化、亲和感才会大大提升。从某个角度看,视频数据的处理表达已经变得容易多了,而声频数据表达要求的时间精确均匀的数据流,总是让人甚感棘手。嵌入处理器支持使用DAM的SAI接口使得声频在嵌入系统的CPU占用大大降低。
简单地看,SAI就像是连两个更全面的I2S总线构成(顺便说一句,各种串行通讯方式已经成为学习掌握嵌入系统的基本功夫,先学习SPI可以建立一个很好的基础)。对于声频数据传输,满足声频信息中包含的各种取样频率的要求,就是声频数据传输和普通SPI的一个重要不同点。通常SAI用于在播放解码和录音编码芯片之间建立通讯接口。
如图是 STM32F7的SAI功能图:
下图是STM32F7的I2S功能块图:
可以看出STM32F7的SAI有两个独立可配置的通道,带有FIFO、帧同步异步、时钟发生、主从模式、声频格式、DMA和中断等全面支持。每个通道主要有四信号线:数据、时钟、帧同步、主模式时钟(用于和外部编码解码芯片的时序协调,STM32F769-DISCO使用的声频处理芯片是WM8994)。
代码例子:
这里我们通过例子BSP例程(STM32F7xx_DFP\2.8.0\Projects\STM32F769I-Discovery\Examples\BSP)的一部分Audio-Player来说明SAI的工作方式。例子代码见附件,解压到STM32F7xx_DFP\2.8.0\Projects\STM32F769I-Discovery\Example下使用。
主程序:
- int main(void)
- {
- uint8_t lcd_status = LCD_OK;
- MPU_Config();
- CPU_CACHE_Enable();
- HAL_Init();
- SystemClock_Config();
- BSP_LED_Init(LED_GREEN);
- BSP_LED_Init(LED_RED);
- BSP_PB_Init(BUTTON_WAKEUP, BUTTON_MODE_GPIO);
- lcd_status = BSP_LCD_Init();
- while(lcd_status != LCD_OK);
- BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS);
- BSP_LCD_Clear(LCD_COLOR_WHITE);
- //以上所有例程序几乎一样,无需解释。详细学习,直接研究STM32F7xx_DFP\2.8.0\Projects\STM32F769I-Discovery\Examples\BSP
- while (1)
- AudioPlay_demo(); // 我们这里只分析这个例子。
- }
复制代码
AudioPlay_Demo()第一部分,初始化:主要是LCD界面!!
- void AudioPlay_demo (void)
- {
- uint32_t *AudioFreq_ptr;
- AudioFreq_ptr = AudioFreq+6; /*AF_48K*/
- uint8_t frequency_str[256] = {0};
- uint8_t volume_str[256] = {0};
- uint8_t ts_status = TS_OK;
- Point Points2[] = {{100, 140}, {160, 180}, {100, 220}};
- uwVolume = 40;
- Audio_SetHint();
- BSP_LCD_SetFont(&Font20);
- ts_status = BSP_TS_Init(BSP_LCD_GetXSize(), BSP_LCD_GetYSize());
- if (ts_status != TS_OK)
- {
- BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
- BSP_LCD_SetTextColor(LCD_COLOR_RED);
- BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 95, (uint8_t *)"ERROR", CENTER_MODE);
- BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 80, (uint8_t *)"Touch Screen cannot be initialized", CENTER_MODE);
- }
- /* if(BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE1, uwVolume, *AudioFreq_ptr) == 0)
- if(BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE2, uwVolume, *AudioFreq_ptr) == 0)*/
- if(BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_BOTH, uwVolume, *AudioFreq_ptr) == 0)
- {
- BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
- BSP_LCD_SetTextColor(LCD_COLOR_GREEN);
- BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 95, (uint8_t *)" AUDIO CODEC OK ", CENTER_MODE);
- }
- else
- {
- BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
- BSP_LCD_SetTextColor(LCD_COLOR_RED);
- BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 95, (uint8_t *)" AUDIO CODEC FAIL ", CENTER_MODE);
- BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 80, (uint8_t *)" Try to reset board ", CENTER_MODE);
- }
- /* Play audio on slots 0 and 2 */
- BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
- AUDIO_Start((uint32_t *)AUDIO_SRC_FILE_ADDRESS, (uint32_t)AUDIO_FILE_SIZE);
复制代码此例使用系统时钟SysTick_Handler处理声频
本文来自论坛,点击查看完整帖子内容。