STM32 控制蜂鸣器播放音乐的原理和实例
本文通过将乐谱里的每个音符的声音频率和声音时长保存在两个数组里面。
1.使用通用定时器TIM4实现无中断的微秒级延时函数,控制每个音符的发声时长。
2.使用系统滴答时钟Systick实现带有中断的输出控制,在中断函数里实现蜂鸣器端口输出电平反转,并且根据当前播放音符的频率重新设置中断产生时间。
一、播放的原理
播放的乐谱:
1.1 C音调乐谱对应的音频(Hz):
根据乐谱的基础知识可知,低音的下面加点,高音的上面加点,普通的不加点。
//用枚举定义,记录所有的音频。
enum Low_frequency{
l_dao=262,l_re=286,l_mi=311,l_fa=349,l_sao=392,l_la=440,l_xi=494};
enum Normal_frequency{
dao=523,re=587,mi=659,fa=698,sao=784,la=880,xi=987};
enum High_frequency{
h_dao=1046,h_re=1174,h_mi=1318,h_fa=1396,h_sao=1567,h_la=1760,h_xi=1975};
1.2 乐谱对应的节拍-音长:
本次乐谱的节拍为每分钟72拍,可以算出每个节拍的时长:
然后看乐谱的第一小节:
最后将整个乐谱的音频和音长记录在两个数组里。
。
二、播放音乐的具体实现
2.1 无中断的毫秒延时函数
//TIM_4初始化函数
void TIM_4(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
TIM_TimeBaseStructure.TIM_Period = 1;
TIM_TimeBaseStructure.TIM_Prescaler=(72-1);
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Down;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
}
//延时n个us
void delay_us(unsigned int nus)
{
TIM4->CNT=nus-1;
TIM4->CR1|=TIM_CR1_CEN;
while((TIM4->SR & TIM_FLAG_Update) != SET)
;
TIM4->CR1&=(~TIM_CR1_CEN);
TIM4->SR &