使用有源蜂鳴器,只能發出固定的”滴滴“聲,當然不能滿足于此呀。使用無源蜂鳴器m5彩票下载,只要輸出不同頻率的PWM波,即可發出不同的音符。不同的音符組合起來就是一個曲子了m5彩票下载。
1 樂譜簡析
1.1 音階
音階是音樂必不可少的要素,主要由聲音的頻率決定。通過給蜂鳴器不同頻率的音頻脈沖,可以產生不同的音階,而要產生某頻率的音頻脈沖,最簡單的辦法是算出該音頻的周期,然后將此周期除以2即為半周期的時間。通過程序控制單片機某引腳半周期為“高”m5彩票下载m5彩票下载、半周期為“低”,不斷交替變換,即可產生該頻率的矩形波,接到蜂鳴器上就可發出該頻率的聲音。若想改變音階,只需要改變半周期時間即可。下表為各音調音符頻率對照表,據此可產生不同音階的音符m5彩票下载。“#”表示半音,用于上升或下降半個音m5彩票下载,乘以2就提升該聲音一個8度音階m5彩票下载,減半則降一個8度。
1.2 節拍
若要構成音樂m5彩票下载,光有音階是不夠的,還需要節拍,也就是音符持續時間的長短m5彩票下载,一般用拍數表示。至于1拍是多少秒,沒有嚴格的規定,只要節拍適宜,聲音悅耳即可。假如某首歌曲的節奏是每分鐘120拍m5彩票下载,那么1拍為0.5 s,1/4拍為0.125 s,以此類推可得到其他節拍對應的時長。這樣,利用不同的頻率m5彩票下载,加上與拍數對應的延時,就構成了樂曲。
2 STM32中的定時器
音階的產生與聲音頻率有關,為了實現不同音階,必須能為蜂鳴器提供不同頻率的脈沖m5彩票下载。為此m5彩票下载,選擇STM32芯片m5彩票下载,利用其自帶的定時器,通過PWM產生脈沖信號。STM32中一共有11個定時器,包含2個高級控制定時器、4個普通定時器、2個基本定時器,以及2個看門狗定時器和1個系統滴答定時器SysTiek。其中,TIM1和TIM8是高級定時器m5彩票下载,時鐘由APB2的輸出產生。TIM2~TIM5是普通定時器,TIM6和TIM7是基本定時器,這6個定時器的時鐘由APB1的輸出產生。
2.1 定時時長的計算
定時器的一個主要功能就是到指定時間就會產生一個溢出事件,這個時間的設置與定時器時鐘有關,在定時器時鐘基礎上進行預分頻,設置計數溢出大小即可。
2.1.1 系統時鐘設置
要保證定時的準確性m5彩票下载m5彩票下载,必須先確保系統時鐘的設置是我們所預期的。定時器時鐘分配可查看數據手冊。通過編程使SYSCLK為72 MHz,APB1預分頻后得到PCLK1為36 MHz,再經TIM2~TIM7倍頻器得到TIM2~TIM7時鐘72 MHz。時鐘源多采用HSE(外部時鐘源),對于STM32F103,其外部時鐘為8 MHz,而STM32F107外部時鐘為25 MHz,因此,在使用HSE做時鐘源時,這兩種器件產生SYSCLK的分頻和倍頻方式不同,需要使用者引起注意m5彩票下载。
2.1.2 定時器相關參數設置
定時器的參數由結構體TimeBaselnitTypeDef定義,主要包括預分頻系數、時鐘分割、計數器模式、計數溢出大小等。例如m5彩票下载,要由TIM3(定時器3)產生一個時長為1 s的定時,首先m5彩票下载,應進行系統時鐘的設置,得到TIM3CLK=72MHz,然后進行定時器設置。其中,預分頻系數為35 999m5彩票下载,此時,TIM3時鐘為72 MHz/36 000=2 kHz,無時鐘分割。設置計數溢出大小為1 999,即每計2 000個數就產生一個更新事件m5彩票下载,輸出頻率為2 kHz/2 000=1 Hz。
2.2 STM32的PWM輸出
脈沖寬度調制(Pulse Width Modulationm5彩票下载,PWM)是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,簡而言之,就是實現對輸出信號脈沖寬度的控制,一般用來控制步進電機等m5彩票下载m5彩票下载。STM32的定時器除了TIM6和TIM7之外,其他的定時器都可以用來產生PWM輸出,其中,高級定時器TIM1和TIM8能夠產生3對PWM互補輸出,而TIM2~TIM5也能同時產生4路的PWM輸出。
2.2.1 PWM輸出引腳
STM32給不同的定時器分配了不同的輸出引腳,考慮到引腳復用功能,STM32還提出了一個“重映像”的概念m5彩票下载,就是通過設置某一些相關的寄存器,使得在其他非原始指定的引腳上也能輸出PWM波形,但是這種重映像不是隨意的m5彩票下载,使用方法可參照參考文獻。例如,TIM3的通道2,在沒有重映像的時候,指定的引腳是PA7。如果設置部分重映像之后,輸出就被映像到PB5上了;如果設置完全重映像的話m5彩票下载,輸出就被映像到PC7上。
2.2.2 占空比的計算
占空比(Duty Ratio)有如下含義:在一串理想的脈沖周期序列(如方波)中,正脈沖的持續時間與脈沖總周期的比值。
當TIM_Period為1 999時,若想得到占空比50%,則TIM_Pulse應設置為(1999+1)/2=1000。
3.2 程序設計
改變PWM的音調,可以輸出Do re mi fa so la si do這樣的7個音符,還可以輸出不同音調的Do re mi fa so la si do。
在實例程序里面,我定義了低中高三個音階。音符的頻率則是mbed提供的m5彩票下载。已經宏定義好了。
只要改變PWM的輸出周期,即可發出不同的音調(頻率是周期的倒數)m5彩票下载m5彩票下载。
為了方便起見m5彩票下载,寫了一個音階類(Pitch),虛基類。里面有一個perform函數m5彩票下载,參數是音符和持續時間。例如要發出Do這個聲音,持續0.5s,只要perform(1,0.5)就好。
還有一個Stop函數,停止響聲0.5s則stop(0.5),無參數則直接停止。后面的Lowm5彩票下载、Mid、High類則是派生類m5彩票下载,實現了Pitch的虛函數。
程序里面包括:
1、發出低中高三個聲調的Do re mi fa so la si do音m5彩票下载。
2m5彩票下载、中音版的小星星m5彩票下载。
3、低音版的小星星。
#include "mbed.h"
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
//7個音符組成了美妙的音樂
//低 Do re mi fa so la si do
int melody[] = { NOTE_C4, NOTE_D4,NOTE_E4, NOTE_F4, NOTE_G4,NOTE_A4,NOTE_B4,NOTE_C5};
//中 Do re mi fa so la si do
int melody2[] = { NOTE_C5, NOTE_D5,NOTE_E5, NOTE_F5, NOTE_G5,NOTE_A5,NOTE_B5,NOTE_C6};
//高
int melody3[] = { NOTE_C6, NOTE_D6,NOTE_E6, NOTE_F6, NOTE_G6,NOTE_A6,NOTE_B6,NOTE_C7};
//PWM輸出口
PwmOut m(PB_13);
//音調類
class Pitch{
public:
virtual void perfrom(int,double)=0;
void stop(double time = 0){
if(time==0)
m = 1;
else{
m = 1;
wait(time);
}//end else
}//end stop
};
class Low:public Pitch{
public:
void perfrom(int index,double time){
m.period_us(1000000/melody[index-1]);
m.write(0.5);
wait(time);
}
};
class Mid:public Pitch{
public:
void perfrom(int index,double time){
m.period_us(1000000/melody2[index-1]);
m.write(0.5);
wait(time);
}
};
class Hig:public Pitch{
public:
void perfrom(int index ,double time){
m.period_us(1000000/melody3[index-1]);
m.write(0.5);
wait(time);
}
};
int main()
{
//低音版
Low low;
//11 55 66 5
low.perfrom(1,0.5);
low.perfrom(1,0.5);
low.perfrom(5,0.5);
low.perfrom(5,0.5);
low.perfrom(6,0.5);
low.perfrom(6,0.5);
low.perfrom(5,0.8);
low.stop(0.2);
//44 33 22 1
low.perfrom(4,0.5);
low.perfrom(4,0.5);
low.perfrom(3,0.5);
low.perfrom(3,0.5);
low.perfrom(2,0.5);
low.perfrom(2,0.5);
low.perfrom(1,0.5);
low.stop(0.2);
//55 44 33 2
low.perfrom(5,0.5);
low.perfrom(5,0.5);
low.perfrom(4,0.5);
low.perfrom(4,0.5);
low.perfrom(3,0.5);
low.perfrom(3,0.5);
low.perfrom(2,0.5);
low.stop(0.2);
//55 44 33 2
low.perfrom(5,0.5);
low.perfrom(5,0.5);
low.perfrom(4,0.5);
low.perfrom(4,0.5);
low.perfrom(3,0.5);
low.perfrom(3,0.5);
low.perfrom(2,0.5);
low.stop(0.2);
//11 55 66 5
low.perfrom(1,0.5);
low.perfrom(1,0.5);
low.perfrom(5,0.5);
low.perfrom(5,0.5);
low.perfrom(6,0.5);
low.perfrom(6,0.5);
low.perfrom(5,0.5);
low.stop(0.2);
//44 33 22 1
low.perfrom(4,0.5);
low.perfrom(4,0.5);
low.perfrom(3,0.5);
low.perfrom(3,0.5);
low.perfrom(2,0.5);
low.perfrom(2,0.5);
low.perfrom(1,0.5);
low.stop();
}