STM8 开发故事--之蜂鸣器 BEEP设计简单的音乐(三)

STM8 开发故事--之蜂鸣器 BEEP设计简单的音乐(三)

虽然我也不识音律。但是不妨碍我欣赏音乐。

要让单片机和蜂鸣器发出音乐必须知道音调和节拍的概念。

音调就是声音的频率,节拍就是这个频率保持的时间。通过对音调和节拍的不同组合就会发出音乐,至于是否悦耳动听则另当别论。

频率可以通过TIM1_TimeBaseInit(2,TIM1_CounterMode_Up,240,0); 函数来设置。

节拍可以写一个delay程序来实现。如果在main里面用delay来实现时间控制,会占用大量CPU资源。一般的做法是创建一个时间中断。我一般会创建一个60hz的时间中断。在时间中断里面处理如按键读取及防抖,音乐播放等功能,其他可以后台处理的程序。我以前在51上用时间中断实现了多任务同时工作的效果。别人用3颗51才能完成的功能我1颗就实现了。

在stm8项目里我用timer2启动时间中断服务程序。先设置tmi2

//tim2 发起中断 中断服务程序在 INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler, 19)
 void TIM2_Config(void)
{
    TIM2_DeInit();
    CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE); 
    TIM2_TimeBaseInit(TIM2_Prescaler_16, TIM2_CounterMode_Up, 1014);
    TIM2_SetCounter(500);                                
    TIM2_ITConfig(TIM2_IT_Update, ENABLE);
    TIM2_ARRPreloadConfig(ENABLE);
    TIM2_Cmd(ENABLE);                                     //计数器使能,开始计数  
}

TIM2_Config是在main里执行的。中断程序是在INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler, 19)

里执行的。这个函数在我的工程里已经建立好了,在stm8l15x_it.c 文件里。我是通过IAR的find in file(shift+ctrl+f)功能找到的。是否启动了中断,可以通过在函数里面设断点来确认。stm8的所有中断都在里面。如果你们的工程和我的不一样 就只有自己找了。下面我贴一段代码供大家参考。

u8 music[14][2]={ {6,1},{6,1},{5,1},{7,1},{1,1},{2,1},{3,1},{2,1},{3,1},{2,1},{3,1},{4,1},{5,1},{6,1}};//乐谱第一位是音调第2是节拍
u16 tone[]={0,200,220,240,280,300,350,420};
u8 deat[]={20,30,60};
u8 music1[5][2]={ {1,1},{2,1},{3,1},{4,1},{5,1}};//乐谱第一位是音调第2是节拍
u8 music2[3][2]={ {2,1},{3,1},{4,1}};//乐谱第一位是音调第2是节拍
u8 music3[2][2]={ {2,1},{5,1}};//乐谱第一位是音调第2是节拍
u8 music4[1][2]={ {2,1}};//乐谱第一位是音调第2是节拍
u16 tone_c=0;//当前音调
u8 deat_c=0;//当前节拍长度
u8 music_c=0;//当前节拍
//u8 sw_bell=0;
u16 tone_key[]={100,1200,240};
u8 beat_key=0;//jy 按键发音长度(节拍)
u8 sw_tone=1;
INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler, 19)
{
  u8 val=0;
  u8 beat_long=10;//按键发音长度
   u8 aa;
  TIM2_ClearFlag( TIM2_FLAG_Update);
/****************************************/
    //蜂鸣器铃声,简单和旋 乐谱在music数组里
  if(sw_bell>0){ //sw_bell是铃声开关
    aa=sizeof(music)/sizeof(music[0]);
    music_c=aa;//当前节拍
    deat_c=deat[music[aa-music_c][1]];//当前节拍
    tone_c=tone[music[aa-music_c][0]];//当前音调
    TIM1_TimeBaseInit(2,TIM1_CounterMode_Up,tone_c,0); //tim1 pwm输出频率
    //    CLK_PeripheralClockConfig(CLK_Peripheral_TIM1,ENABLE);//开启TIM1时钟 蜂鸣器发声    
    TIM1_Cmd(ENABLE); //定时器开始计数?
    sw_bell=0;
  }
  if (music_c>0){   
    if ( deat_c>0){
      deat_c--;
    }else{
      music_c--; 
      if (music_c>0){
        aa=sizeof(music)/sizeof(music[0]);
        u8 x=music[aa-music_c][0];
        deat_c=deat[music[aa-music_c][1]];//当前节拍
        tone_c=tone[music[aa-music_c][0]];//当前音调
        if(tone_c!=0){
          TIM1_TimeBaseInit(2,TIM1_CounterMode_Up,tone_c,0); //tim1 pwm输出频率  
          TIM1_Cmd(ENABLE); //定时器开始计数?
        }else{
          sw_tone=tone_c;
          TIM1_Cmd(DISABLE); //定时器停止计数 蜂鸣器不发音
        }
      }else{
        TIM1_Cmd(DISABLE); //定时器停止计数 蜂鸣器不发音
      }
    }
  } 
}
嵌入式开发一定要通过善用中断来提高效率。高效的代码可以降低mcu主频,从而降低功耗,延长电池使用时间。

the end!

 

 

 

 

 

 

你可能感兴趣的:(中断,时间中断,蜂鸣器,stm,音乐)