打印
[STM32F7]

STM32F769 Discovery板子音频播放之一:播放Wav文件

[复制链接]
3816|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhanzr21|  楼主 | 2016-12-15 18:10 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
这里以官方例子为基础,看看怎么播放wav文件,以及如何改吧改吧播放别的wav文件
这个例子:

建议最好拷贝一个出来,免得不能还原,我是整个目录都有备份,所以直接在这上面改了.
打开项目,主要看这几个点:
int main(void)
{
  uint32_t PlaybackPosition = PLAY_BUFF_SIZE + PLAY_HEADER;
  
  /* Enable the CPU Cache */
  CPU_CACHE_Enable();

  /* STM32F7xx HAL library initialization:
       - Configure the Flash prefetch
       - Systick timer is configured by default as source of time base, but user
         can eventually implement his proper time base source (a general purpose
         timer for example or other time source), keeping in mind that Time base
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
         handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Configure the system clock to have a frequency of 216 MHz */
  SystemClock_Config();

  /* Configure LED2 */
  BSP_LED_Init(LED2);
  /* Configure LED1 */
  BSP_LED_Init(LED1);

  /* Check if the buffer has been loaded in flash */
//  if(*((uint64_t *)AUDIO_FILE_ADDRESS) != 0x017EFE2446464952 ) Error_Handler();
这个上面最后一句,是检查wav文件头的,建议注释掉,因为wav文件头有几种变种, 如果用其他wav文件(非ST提供的),则这里很可能不通过,其实内容是可以播放的
main.c最上面几行有几个宏定义:
#define AUDIO_FILE_ADDRESS   0x08010000
//#define AUDIO_FILE_SIZE      (180*1024)
//#define AUDIO_FILE_SIZE      (270852)
#define AUDIO_FILE_SIZE      (176444)
#define PLAY_HEADER          0x2C
#define PLAY_BUFF_SIZE       4096
AUDIO_FILE_ADDRESS这个宏定义的是wav文件在flash的存储位置,这个只要不跟你代码重合就可以了
AUDIO_FILE_SIZE定义你烧录的wav文件大小,整个F769NIHx的Flash有2M,但要扣除掉前面的64K代码空间,本例子中wav文件要小于等于2M-64K=1984K,如果先用ST提供的文件,大小定为180K即可
PLAY_HEADER是开始的偏移量,就是wav文件的头,wav格式在后面的帖子中介绍,此处跳过它即可
PLAY_BUFF_SIZE是缓冲区的大小,因为是DMA传输,这里大小不是很重要,宜大不宜小,别超过512K的SRAM空间即可

播放的基本流程就是先初始化好buffer,DMA,指针后面不停地把Flash中的内容搬运到SAI接口上循环播放

看看Playback_Init这个函数: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_22K;
  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);
可以看出来,播放的设置是:22.05KHz, 双声道, 16bit每通道的音频数据. 官方提供的wav文件就这格式,如果你自己的wav文件不是这格式,这里要做相应修改
SAI初始化好之后还要设置外部Codec,这板子上就是WM8994片:
  /* Initialize audio driver */
  if(WM8994_ID != wm8994_drv.ReadID(AUDIO_I2C_ADDRESS))
  {
    Error_Handler();
  }
  
  audio_drv = &wm8994_drv;
  audio_drv->Reset(AUDIO_I2C_ADDRESS);  
  if(0 != audio_drv->Init(AUDIO_I2C_ADDRESS, OUTPUT_DEVICE_HEADPHONE, 100, AUDIO_FREQUENCY_22K))
  {
    Error_Handler();
  }
我的耳机是放在桌子上的,如果戴着耳机做实验,请把音量减小一些(100是最大,0是最小,20,30比较适合),不然会很伤耳朵的.
以下是DMA的设置,设置成half word传输,和前面一至即可
    hSaiDma.Init.Channel             = DMA_CHANNEL_10;
    hSaiDma.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    hSaiDma.Init.PeriphInc           = DMA_PINC_DISABLE;
    hSaiDma.Init.MemInc              = DMA_MINC_ENABLE;
    hSaiDma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hSaiDma.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
    hSaiDma.Init.Mode                = DMA_CIRCULAR;
    hSaiDma.Init.Priority            = DMA_PRIORITY_HIGH;
    hSaiDma.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;      
    hSaiDma.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
    hSaiDma.Init.MemBurst            = DMA_MBURST_SINGLE;         
    hSaiDma.Init.PeriphBurst         = DMA_PBURST_SINGLE;   
这个程序编译好烧进板子,之后烧录wav文件,这里先以官方提供的文件为例,他提供的文件在这里:

里面audio.bin在此,其实就是个22.05K的双声道wav文件,你把它改成audio.wav,什么播放器都能播放.但是STM32 ST-LINK Utility不支持任意文件名烧录,所以烧录的时还是要改成.bin

打开STM32 ST-LINK Utility,拖进文件audio.bin:

连接板子,Program时选择地址要跟之前AUDIO_FILE_ADDRESS要一样,千万不用默认的0x08000000,那样就跟程序重叠了,此例中使用0x08010000
烧写完复位,如果之前应用代码配置正确就可以听到播放了以上是用官方的wav文件,如果自己找wav文件,注意以下几点:

1.wav格式要22.05K采样, 双声道, 16bit,如果不是这格式请用工具转换成此格式
2.上述格式的文件大小不要超过1984K,官方文件180K大约2.04秒,所以这个例子最多播放22多秒内容,如果要改格式,改文件存放方式,跟代码有关,后面帖子再来说
3.改了文件后,这个宏要改 AUDIO_FILE_SIZE, 改成实际文件大小就可以了
4.如果直接用F769板上stlink烧写,文件后缀要改成.bin





沙发
userlin| | 2016-12-16 16:04 | 只看该作者
感谢分享

使用特权

评论回复
板凳
colin2135| | 2016-12-27 22:15 | 只看该作者
很不错啊,又学到的学东西。

使用特权

评论回复
地板
bd7qwmcu| | 2017-1-1 15:52 | 只看该作者
继续学习,2017.1.1

使用特权

评论回复
5
wsjzh| | 2017-1-5 12:18 | 只看该作者
感谢分享

使用特权

评论回复
6
萌baby| | 2017-1-8 17:13 | 只看该作者
发挥到宿舍

使用特权

评论回复
7
peng352603281| | 2017-1-11 08:54 | 只看该作者
真是很好的资料

使用特权

评论回复
8
nj21ic| | 2017-1-14 21:22 | 只看该作者
太好了

使用特权

评论回复
9
dawei360| | 2017-3-30 15:55 | 只看该作者
你这个怎么把音频bin 文件烧录到0x0801000 地址啊,用STLINK 就成未响应了

使用特权

评论回复
10
zhanzr21|  楼主 | 2017-3-30 16:24 | 只看该作者
本帖最后由 zhanzr21 于 2017-3-30 16:26 编辑
dawei360 发表于 2017-3-30 15:55
你这个怎么把音频bin 文件烧录到0x0801000 地址啊,用STLINK 就成未响应了

看清楚地址, 看了这帖子之后, 这个实验起码有100个人试过了, 不要随便怀疑ST做的工具

使用特权

评论回复
11
zhanzr21|  楼主 | 2017-3-30 16:28 | 只看该作者
没有反应, 应该是你程序与你写的地址重叠了
写在哪个地址其实无所谓, 只是你程序如果与数据重叠了肯定是跑飞, Hard_Fault

使用特权

评论回复
12
dawei360| | 2017-3-30 16:35 | 只看该作者
zhanzr21 发表于 2017-3-30 16:24
看清楚地址, 看了这帖子之后, 这个实验起码有100个人试过了, 不要随便怀疑ST做的工具
...

3Q,的确可以就是慢,进入假死状态

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:每天都進步

91

主题

1013

帖子

34

粉丝