酒店客房服务员工装:STM32开发板上音频播放程序的设计之二 -- nthq2004's Blog

来源:百度文库 编辑:中财网 时间:2024/05/01 22:55:36

STM32开发板上音频播放程序的设计之二

 

 

二、音频播放程序设计

1、程序实现的方案

1)目的

添加一个命令msplay,后带一个参数,就是要播放的WAV文件的名称。

支持播放PCM格式的文件,其它编码方式暂不支持。

2)实现方案

参照李宁教授书上的《简易声波播放器的设计与实现》那一篇。

利用TIM4通道1定期产生的中断,从缓冲期中读取声音数据。这个中断频率就是WAV文件的采样频率。

声音数据通过TIM3的通道3产生不同频率方波输出。我这个板上的PB0接着扬声器,可以复用为TIM3_CH3

为了声音播放的连续性,采用两个数据缓冲区。在中断处理程序中,当一个缓冲区的数据读完后,自动切换到下一个缓冲区开头。而在主程序中,当发现一个缓冲区空以后,又很快读入声音数据。

 

3)程序执行流程分析

串口输入命令“msplay ***.wav”,进入音频播放命令处理程序。

首先读入文件头的44个字节,获取wav文件头信息,对比标志“RIFF”,“WAVE”“fmt ”,获取编码方式、声道、采样频率、位数,每次采样的字节数、每秒采样的字节数,根据“fmt ”后面的size字段定位 “DATA CHUNK”,获得数据区开始偏移。暂时不考虑有“fact CHUCK”的情况。

数据的读取通过设置几个结构体,定义一个指针让它指向缓冲区头部,将该指针前者类型转换成结构指针,取出缓冲区对应的属性数据。

若对应位置的数据不符合要求,则程序退出。

 

将重要的数据都保存到WavInfo结构体中。

根据采样率的要求,初始化TIM4。然后将TIM3进行初始化设置,并设置CH3输出通道。填充0号缓冲区,使能TIM4中断。置位播放标志。播放实际上就开始了。

 

2、程序代码设计

1)重点是先要把定时器的配置弄清楚

 

首先TIM2TIM3TIM4都位于APB1,最高频率36MHzTIM2已经被我使用,利用通道3产生方波,为液晶提供稳压电源驱动脉冲。它的输出是采用了输出比较模式。下面先回顾一下一个重要寄存器和工作模式。

 

预分频PSC控制计数的实际频率,定时器并不直接对36MHz的脉冲计数,而要先分频。计数频率 = 36MHz 除以 PSC +1)。

自动重装载ARR实际控制计数周期,相当于定时器的提前溢出值,比如设置成0x100,则当从0计数到0x100时,定时器自动复位到初始值。(我的理解不知道对不对)。或者在向下计数模式时,每次都从自动装载值开始计数,向下计数到0,然后又重新装载ARR的值。

 

其它的再看一下参考资料:

时钟选择:我现在是采用内部时钟源,所以要禁止从模式。CR1CEN使能内部时钟,开启定时器,DIR控制计数方向。

比较通道的预装载含义:如果不使能预装载,比较值总是立即写入当前比较寄存器。如果使能,则设定的比较值现在不起作用,等到一个更新事件发生时,才写入当前比较寄存器。

自动重装载寄存器也有同样的预装载的含义。

 

向上计数PWM模式1:初始化时,计数值为0,比较输出参考电平为高。当计数值大于比较值时,输出电平为低。所以ARR是控制PWM的频率,写CCR是控制脉冲的占空比。但是要特别注意OCREFOC输出极性之间的关系,要不然有可能你想增加占空比的时候反而减小了。

比较模式是在匹配时产生动作,如果利用比较匹配、输出翻转模式产生波形,只能产生方波。而且输出频率在除以周期值以后还得除以2

PWM才是真正的像是在比较大小,计数值小于比较值时输出高电平,大于比较值时输出低电平(OCREF引脚)。PWM中心对称模式是指所有输出引脚的波形中心对称,它内部实现是通过先向上计数、再向下计数实现的。其输出频率在相同周期值的情况下,为向上计数模式的一半

 

2)添加命令msplay,先设计出框架

1要使用定时器4,先要使能时钟。

2要使用定时器4的更新中断,必须设置NVIC

3)让定时器3工作于PWM1模式下,其频率设置为72000 000/256大概为280kHz,这就是PWM频率(要工作于高频下,我试着将频率降低,结果就只能听到噪音)。

因为测试文件是单声道、8位采样的,所以采样值小的时候,PWM占空比就小,PWM输出平均幅度就与波形文件中的数据大小成正比,因此扬声器可以将声音还原

 

void Speaker_Start( WAVINFO *WavInfo )

{

  GPIO_InitTypeDef GPIO_InitStructure;  //进行GPIO端口设置的数据结构

  NVIC_InitTypeDef NVIC_InitStructure;

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; //时基单元配置数据结构

  TIM_OCInitTypeDef  TIM_OCInitStructure; //输出模式设置数据结构

 

  /* PB0脚接着定时器3 CH3PWM脉冲输出,该输出控制扬声器 */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

 

  /* 时基单元配置:TIM3计数频率 =72MHz除以分频系数。*/

  TIM_TimeBaseStructure.TIM_Period = 255;    //写入自动装载寄存器,PWM频率大约36000000/256

  TIM_TimeBaseStructure.TIM_Prescaler = 0; //

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;//与什么采样相关,这里用不到

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

 

  /* TIM3 配置在PWM1模式, */

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能

  TIM_OCInitStructure.TIM_OutputNState =  TIM_OutputNState_Disable;

  TIM_OCInitStructure.TIM_Pulse = 0;  /* 占空比初始化为0*/

  TIM_OCInitStructure.TIM_OCPolarity =    TIM_OCPolarity_High;//高电平有效,因为PWM输出接三极管基极。

  TIM_OCInitStructure.TIM_OCIdleState =      TIM_OCIdleState_Reset;

  TIM_OC3Init(TIM3, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

 

  /* TIM4 配置为定时中断,其频率为WAV文件采样频率 */

  TIM_TimeBaseStructure.TIM_Period = 72000000/WavInfo->SampFreq;

  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;   

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;  

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;      

  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

 

  /* Enable the TIM4 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);  //刚开始时忘了这个。

  /* Start TIM3 */

  TIM_Cmd(TIM3, ENABLE);

  /* Start TIM4 */

  TIM_Cmd(TIM4, ENABLE);

  /* Enable TIM4 update interrupt */

  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

}

 

程序下载,已经可以听到音乐了,但是声音比较小。