[原创] 心仪M7--STM32F769I-DISCO评测-SAI(四)

okwh   2017-1-4 22:59 楼主
本篇是此系列的最后一篇,重点是SAI(Serial audio interface).
前奏介绍
众所周知,声频、视频是人机界面的核心部分,有了它们,计算机的人性化、亲和感才会大大提升。从某个角度看,视频数据的处理表达已经变得容易多了,而声频数据表达要求的时间精确均匀的数据流,总是让人甚感棘手。嵌入处理器支持使用DAM的SAI接口使得声频在嵌入系统的CPU占用大大降低。
简单地看,SAI就像是连两个更全面的I2S总线构成(顺便说一句,各种串行通讯方式已经成为学习掌握嵌入系统的基本功夫,先学习SPI可以建立一个很好的基础)。对于声频数据传输,满足声频信息中包含的各种取样频率的要求,就是声频数据传输和普通SPI的一个重要不同点。通常SAI用于在播放解码和录音编码芯片之间建立通讯接口。
如图是 STM32F7的SAI功能图:
40.png
下图是STM32F7的I2S功能块图:
41.png
可以看出STM32F7SAI有两个独立可配置的通道,带有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下使用
主程序:
  1. int main(void)
  2. {
  3. uint8_t lcd_status = LCD_OK;
  4. MPU_Config();
  5. CPU_CACHE_Enable();
  6. HAL_Init();
  7. SystemClock_Config();
  8. BSP_LED_Init(LED_GREEN);
  9. BSP_LED_Init(LED_RED);
  10. BSP_PB_Init(BUTTON_WAKEUP, BUTTON_MODE_GPIO);
  11. lcd_status = BSP_LCD_Init();
  12. while(lcd_status != LCD_OK);
  13. BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS);
  14. BSP_LCD_Clear(LCD_COLOR_WHITE);
  15. //以上所有例程序几乎一样,无需解释。详细学习,直接研究STM32F7xx_DFP\2.8.0\Projects\STM32F769I-Discovery\Examples\BSP
  16. while (1)
  17. AudioPlay_demo(); // 我们这里只分析这个例子。
  18. }
AudioPlay_Demo()第一部分,初始化:主要是LCD界面!!
  1. void AudioPlay_demo (void)
  2. {
  3. uint32_t *AudioFreq_ptr;
  4. AudioFreq_ptr = AudioFreq+6; /*AF_48K*/
  5. uint8_t frequency_str[256] = {0};
  6. uint8_t volume_str[256] = {0};
  7. uint8_t ts_status = TS_OK;
  8. Point Points2[] = {{100, 140}, {160, 180}, {100, 220}};
  9. uwVolume = 40;
  10. Audio_SetHint();
  11. BSP_LCD_SetFont(&Font20);
  12. ts_status = BSP_TS_Init(BSP_LCD_GetXSize(), BSP_LCD_GetYSize());
  13. if (ts_status != TS_OK)
  14. {
  15. BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
  16. BSP_LCD_SetTextColor(LCD_COLOR_RED);
  17. BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 95, (uint8_t *)"ERROR", CENTER_MODE);
  18. BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 80, (uint8_t *)"Touch Screen cannot be initialized", CENTER_MODE);
  19. }
  20. /*<b><font color="#0000ff"> SAI初始化</font></b>*/
  21. if(<b><font color="#0000ff">BSP_AUDIO_OUT_Init</font></b>(OUTPUT_DEVICE_BOTH, uwVolume, *AudioFreq_ptr) == 0)
  22. {
  23. BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
  24. BSP_LCD_SetTextColor(LCD_COLOR_GREEN);
  25. BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 95, (uint8_t *)" AUDIO CODEC OK ", CENTER_MODE);
  26. }
  27. else
  28. {
  29. BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
  30. BSP_LCD_SetTextColor(LCD_COLOR_RED);
  31. BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 95, (uint8_t *)" AUDIO CODEC FAIL ", CENTER_MODE);
  32. BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 80, (uint8_t *)" Try to reset board ", CENTER_MODE);
  33. }
  1. /* Play audio on slots 0 and 2 */

  2. BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
  3. AUDIO_Start((uint32_t *)AUDIO_SRC_FILE_ADDRESS, (uint32_t)AUDIO_FILE_SIZE);

  4. //开始播放,播放的声频文件audio_sample_tdm.bin\Binary目录,事先用ST-Link utility写入flash地址0x08080000
  5. /* Display the state on the screen */
  6. BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
  7. BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
  8. BSP_LCD_DisplayStringAt(0, LINE(8), (uint8_t *)" PLAYING... changed by okwh at eeworld ", CENTER_MODE);
  9. sprintf((char*)volume_str, " VOL: %3ld ", uwVolume);
  10. BSP_LCD_DisplayStringAt(0, LINE(9), (uint8_t *)volume_str, CENTER_MODE);
  11. sprintf((char*)frequency_str, " FREQ: %6ld ", *AudioFreq_ptr);
  12. BSP_LCD_DisplayStringAt(0, LINE(10), (uint8_t *)frequency_str, CENTER_MODE);
  13. BSP_LCD_SetFont(&Font16);
  14. BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() - 40, (uint8_t *)"Write audio_sample_tdm.bin' in Binary to @0x08080000 of flash using ST-Link utility", CENTER_MODE);
  15. if(ts_status == TS_OK)
  16. {
  17. /* Set touchscreen in Interrupt mode and program EXTI accordingly on falling edge of TS_INT pin */
  18. ts_status = BSP_TS_ITConfig();
  19. BSP_TEST_APPLI_ASSERT(ts_status != TS_OK);
  20. Touchscreen_DrawBackground_Circles(16);
  21. }
  22. BSP_LCD_SetFont(&Font20);
  23. /* Audio is playing */
  24. BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
  25. BSP_LCD_FillPolygon(Points2, 3);
  26. BSP_LCD_SetTextColor(LCD_COLOR_BLACK);
  27. BSP_LCD_FillRect(100, 140, 25 , 80);
  28. BSP_LCD_FillRect(140, 140, 25 , 80);
  29. while (1)
  30. {
  31. ...........略,主要是处理user按键,实现播放速度、音量控制
此例使用BSP_AUDIO_OUT_Init初始化SAI, AUDIO_Start先读取复制缓冲区大小的数据到整个环形缓冲区,并用BSP_AUDIO_OUT_Play设置DMA从缓冲区传送数据到SAI开始播放,播放中将使用BSP_AUDIO_OUT_xxxTransfer_CallBack更新赋值缓冲区半满全空标志。
系统时钟中断SysTick_Handler用 AUDIO_Process判断缓冲区标志,用GetData读取在flash的声频数据到缓冲区,
使用环形缓冲区(AUDIO_BufferTypeDef buffer_ctl)逐步从flash取得后续声频数据填充缓冲区,如此保证播放,
视频: 触摸控制播放的音量和频率
AudioPlayerSamOkwhEEworld.mp4 (1.93 MB)
(下载次数: 31, 2017-1-5 13:46 上传)
本例代码
STM32F769DiscoAudioPlaySam.rar (380.29 KB)
(下载次数: 72, 2017-1-5 13:47 上传)
本系列:
点击此处,查看STM32F769I开发板官方资源。 本帖最后由 okwh 于 2017-1-5 13:48 编辑
熙熙攘攘的世界,我们不懈前行......

回复评论 (2)

性能很不错!   没有什么意义,价格高的离谱。谁家回去用呀!  国产MCU也是不错的性能。
点赞  2017-1-6 16:02
嵌入、应用、桌面,正在走向连接和融合,已经不象原来那么泾渭分明。 想当年(区区30多年前),一台8086的PC就超过10万了(那时的10万,可不是现在的虚胀钱),现在呢? 当年一部大哥大也数万,现在呢?当年,一部电视机重达30公斤,价格数万万,现在呢? 这不过一代人的时间啊。 这世界变化很快的,已经快过人的成长更替了 本帖最后由 okwh 于 2017-1-6 18:02 编辑
熙熙攘攘的世界,我们不懈前行......
点赞  2017-1-6 17:53
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复