蜂鳴器。左邊的是有源蜂鳴器,右邊的無源。從外觀上看,無源蜂鳴器略矮(約1mm)。有源蜂鳴器觸發就會發聲,發聲頻率固定。無源蜂鳴器要用方波驅動,方波頻率即為其發聲頻率: 沒有像樣的規格書,頻率範圍未知。網店商品描述中提到一句2k-5k,that's all。一些關於聲音頻率的數據: 人耳的敏感範圍約為 ...
蜂鳴器。左邊的是有源蜂鳴器,右邊的無源。從外觀上看,無源蜂鳴器略矮(約1mm)。有源蜂鳴器觸發就會發聲,發聲頻率固定。無源蜂鳴器要用方波驅動,方波頻率即為其發聲頻率:
沒有像樣的規格書,頻率範圍未知。網店商品描述中提到一句2k-5k,that's all。一些關於聲音頻率的數據:
- 人耳的敏感範圍約為 20Hz - 20 kHz
- 鋼琴的頻率範圍約 16Hz - 5.6 kHz(參考)
- 標準音 A4 頻率為 440Hz
- 人耳/大腦對頻率呈倍數關係的兩個音感知為同一個音,但是音高不同。西方音樂使用的Chromatic Scale音階,將一個Scale平均分為12個pitch,每個pitch稱為一個semitone。因此,相鄰semitone之間的頻率相差12√2倍(2的12次方根,約1.0595) 。例如,標準音A4為440Hz,A#4 則為 440 x 12√2 = 466.164Hz
STM32 的 General Purpose Timer 可以工作在 Output Compare (OC)模式下,從pin腳輸出方波。控制輸出方波的頻率,即可驅動蜂鳴器發出不同的聲音。OC模式工作原理簡述如下。
先將OC置之不理,單看Timer的計數部分,主要是3個寄存器:CNT, ARR, PSC。Timer時鐘源頻率除以 PSC後才是Timer 的計數頻率。CNT從0開始往上依次計數,當達到 ARR時,將回到0重新開始。而OC部分則有寄存器CCR,每當CNT與CCR相等時,可以設置輸出pin的值,例如將其置高、置低或者toggle。輸出方波要使用toggle方式。
將CCR設固定值,例如0。OC頻率 = Timer時鐘源頻率 / PSC / (1+ARR)。對於toggle方式,2個OC周期才是1個方波周期,因此,輸出方波的頻率 = OC頻率 / 2 = Timer時鐘源頻率 / PSC / (1+ARR) / 2。
可見,輸出方波頻率取決於 PSC及 ARR。對16位 Timer,PSC及 ARR取值範圍為 0 - 65535。
若時鐘源頻率為72MHz,取PSC=36,則方波頻率 = 1MHz / (1+ARR)。當ARR取值範圍為 49-65535 時,可獲得的方波頻率範圍為 15Hz - 20kHz,覆蓋了人耳的敏感範圍和鋼琴的頻率範圍。
相關設置如下,其中時鐘源選擇內部72MHz:
計時器設置中的 Counter Period即為 PSC,設為36;而OC Channel設置中的 Pulse 則為 CCR,設為0:
演奏一首好聽的歌--可惜不是你-- 中的兩句:
簡譜音符對照到鋼琴琴鍵,再查詢得到其頻率:
演奏的實現如下。_App_music[] 數組包含曲子的所有音符,每個音符2個元素,一個是音符的頻率,另一個是時長:
static float _App_music[] = { // 440.000, 1, // (1) 783.991, 2, // 659.255, 2, // 523.251, 1, // 587.330, 3, // ... #define _App_GET_ARR(f) ( (uint32_t)(1000000/(float)(f) - 1) ) #define _App_TIME_UNIT 250 #define _App_IDLE_DELAY 10 void App_Init() { const size_t cnt = sizeof(_App_music) / sizeof(float); for (int i = 0; i < cnt; i += 2) { float f = _App_music[i]; uint32_t t = (uint32_t) (_App_TIME_UNIT * _App_music[i + 1]); __HAL_TIM_SET_AUTORELOAD(&htim3,_App_GET_ARR(f)) ; HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_1); HAL_Delay(t); HAL_TIM_OC_Stop(&htim3, TIM_CHANNEL_1); HAL_Delay(_App_IDLE_DELAY); } // for }
實測表明,蜂鳴器的有效頻率範圍約為 200Hz - 10 kHz。