蜂鸣器播放《两只老虎》
文章目錄
- 前言
- 一、回顧蜂鳴器
- 二、樂譜知識
- 2.1 音符音頻
- 2.2 兩只老虎樂譜
- 三、系統框圖
- 四、模塊調用
- 五、模塊原理圖
- 六、工程源碼
- 6.1 音符選擇模塊代碼
- 6.2 pwm產生模塊代碼
- 6.3 頂層模塊代碼
- 七、仿真測試
- 7.1 測試代碼
- 7.2 仿真結果
- 八、管腳信息
- 九、運行效果
- 總結
前言
??通過往期的按鍵控制蜂鳴器課程,我們了解了蜂鳴器器件,本次課程將使用蜂鳴器,播放我小時候經常聽的《兩只老虎》音樂,來勾起我童年的回憶。
一、回顧蜂鳴器
??我們回顧一下蜂鳴器的知識:
??無源蜂鳴器需要輸入一定頻率的方波或者脈沖寬度調制(Pulse Width Modulation,PWM)信號,蜂鳴器就可以發出聲音。輸入不同頻率的信號,蜂鳴器可以發出不同音色的聲音。《紅樓夢》中“未見其人先聞其聲”指的是王熙鳳,就是因為每個人發出的聲音頻率不同,所以音色也會不同,我們可以通過音色就知道誰是誰。
二、樂譜知識
2.1 音符音頻
??音頻(Audio),指人耳可以聽到的聲音頻率在20HZ~20kHz之間的聲波。樂普是由音符組成的,不同的音符擁有不同的頻率。音頻和周期的關系如下公式所示。
T(周期)=1f(頻率)(1)T(周期) = \frac{1}{f(頻率)}\tag1T(周期)=f(頻率)1?(1)
??我們可以根據表中音符頻率用公式(1)計算出音符振動的周期,單位微秒。Cyclone IV開發板的晶振是50MHz,振動一次是20納秒,使用周期時間除以20納秒得出音符振動的次數。比如高音的DO計算方式如下公式(2)所示。
DO(高)=955×10320=47750(2)DO(高) = \frac{955\times10^3}{20}\tag2=47750DO(高)=20955×103?=47750(2)
2.2 兩只老虎樂譜
??兩只老虎樂譜一共有34個音符,1對應DO,2對應RE,3對應MI…。一個音符持續的時間很短,需要設置一個持續時間,重復播放該音符,這樣我們才能聽得出來。本實驗中設置音符持續時間(節拍)300毫秒,要想使兩只老虎聽起來更完美,同學們下去得學習樂譜中節拍知識,根據樂譜中節拍設置音符的持續時間。
圖2. 兩只老虎樂譜三、系統框圖
圖3. 系統框圖四、模塊調用
圖4. 模塊關系示意圖五、模塊原理圖
圖5. 模塊原理圖六、工程源碼
6.1 音符選擇模塊代碼
module freq_select (input wire clk ,//時鐘信號input wire rst_n,//復位信號output reg flag//pwm標志 ); parameter CNT_MAX = 24'd14_999_999;//300ms parameter NUM_FRE = 6'd33 ;//34個音符 parameter DO = 16'd47750 ;//1 parameter RE = 16'd42250 ;//2 parameter MI = 16'd37900 ;//3 parameter FA = 16'd37550 ;//4 parameter SO = 16'd31850 ;//5 parameter LA = 16'd28400 ;//6 parameter XI = 16'd25400 ;//7 reg [23:0] cnt_delay ;//300ms計數器 reg [5:0] lut_data ;//樂譜數據寄存器 reg [15:0] cnt_freq ;//音符音頻計數器 reg [15:0] freq_data ;//音符數據寄存器 wire [14:0] duty_data ;//占空比數據 wire end_note ;//音符結束標志 wire end_spectrum;//音譜結束標志 //單個音符持續時間計時模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_delay <= 24'd0;end else if(cnt_delay == CNT_MAX)begincnt_delay <= 24'd0;end else begincnt_delay <= cnt_delay + 1'd1;end end //音符計時模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_freq <= 16'd0;end else if(end_note)begincnt_freq <= 16'd0;end else begincnt_freq <= cnt_freq + 1'd1;end end //音譜計時模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)beginlut_data <= 6'd0;end else if(end_spectrum)beginlut_data <= 6'd0;end else if(cnt_delay == CNT_MAX)beginlut_data <= lut_data + 1'd1;end else beginlut_data <= lut_data;end end //音符查找表模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)beginfreq_data <= DO;end else begincase(lut_data)6'd0: freq_data <= DO;6'd1: freq_data <= RE;6'd2: freq_data <= MI; 6'd3: freq_data <= DO; 6'd4: freq_data <= DO; 6'd5: freq_data <= RE; 6'd6: freq_data <= MI; 6'd7: freq_data <= DO; 6'd8: freq_data <= MI; 6'd9: freq_data <= FA; 6'd10: freq_data <= SO;6'd11: freq_data <= MI;6'd12: freq_data <= FA;6'd13: freq_data <= SO;6'd14: freq_data <= SO;6'd15: freq_data <= LA;6'd16: freq_data <= SO;6'd17: freq_data <= FA;6'd18: freq_data <= MI;6'd19: freq_data <= DO;6'd20: freq_data <= SO;6'd21: freq_data <= LA;6'd22: freq_data <= SO;6'd23: freq_data <= FA;6'd24: freq_data <= MI;6'd25: freq_data <= DO;6'd26: freq_data <= RE;6'd27: freq_data <= SO;6'd28: freq_data <= DO;6'd29: freq_data <= DO;6'd30: freq_data <= RE;6'd31: freq_data <= SO;6'd32: freq_data <= DO;6'd33: freq_data <= DO;default:freq_data <= DO;endcase end end assign duty_data = freq_data >> 1;//占空比50%assign end_note = cnt_freq == freq_data; assign end_spectrum = lut_data == NUM_FRE && cnt_delay == CNT_MAX; //pwm信號產生模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 1'b0;end else beginflag <= (cnt_freq >= duty_data) ? 1'b1 : 1'b0; end end endmodule6.2 pwm產生模塊代碼
module gen_pwm (input wire clk ,//時鐘input wire rst_n,//復位信號input wire flag ,//pwm標志信號output reg beep//蜂鳴器信號 );//pwm控制蜂鳴器模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)beginbeep <= 1'b1;end else if(flag)beginbeep <= 1'b0;end else beginbeep <= 1'b1;end end endmodule6.3 頂層模塊代碼
module pwm_beep(input wire clk ,input wire rst_n,output wire beep );parameter CNT_MAX = 24'd14_999_999;//300ms parameter DO = 16'd47750 ;//1 parameter RE = 16'd42250 ;//2 parameter MI = 16'd37900 ;//3 parameter FA = 16'd37550 ;//4 parameter SO = 16'd31850 ;//5 parameter LA = 16'd28400 ;//6 parameter XI = 16'd25400 ;//7 wire flag;//實例化音頻選擇模塊 freq_select#( .CNT_MAX (CNT_MAX), .DO (DO) , .RE (RE) , .MI (MI) , .FA (FA) , .SO (SO) , .LA (LA) , .XI (XI) ) u_freq_select(.clk (clk) , .rst_n (rst_n),.flag (flag) ); //實例化pwm產生模塊 gen_pwm u_gen_pwm ( .clk (clk) , .rst_n (rst_n), .flag (flag) ,.beep (beep) ); endmodule七、仿真測試
7.1 測試代碼
`timescale 1ns/1ns module pwd_beep_tb();parameter CNT_MAX = 24'd21;//一個音符持續時間 parameter DO = 16'd7;//1 parameter RE = 16'd6;//2 parameter MI = 16'd5;//3 parameter FA = 16'd4;//4 parameter SO = 16'd3;//5 parameter LA = 16'd2;//6 parameter XI = 16'd1;//7 parameter CYCLE = 20; reg clk ; reg rst_n; wire beep ;always #(CYCLE/2) clk = ~clk;initial beginclk = 1'b0 ;rst_n = 1'b0 ;#(CYCLE) ;rst_n = 1'b1 ;#(7*CYCLE*CNT_MAX*34);$stop ;endpwm_beep#( .CNT_MAX (CNT_MAX), .DO (DO) , .RE (RE) , .MI (MI) , .FA (FA) , .SO (SO) , .LA (LA) , .XI (XI) ) u_pwm_beep( .clk (clk) , .rst_n (rst_n),.beep (beep) ); endmodule7.2 仿真結果
圖6. 仿真結果八、管腳信息
圖7. pin planner| KEY1 | E15 |
| KEY2 | E16 |
| KEY3 | M16 |
| KEY4 | M15 |
| CLOCK(時鐘) | E1 |
| BUZZER(蜂鳴器) | J1 |
九、運行效果
蜂鳴器播放兩只老虎
總結
??以上就是本期蜂鳴器播放兩只老虎的主要內容,通過本次的學習,同學們下去可以使用蜂鳴器播放其他音樂,只要你手里面有樂譜,原理上是可以編寫任何音樂。趕緊行動起來,成為一個會寫代碼的音樂家吧!謝謝你的觀看。
總結
以上是生活随笔為你收集整理的蜂鸣器播放《两只老虎》的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Delphi菜单栏背景色-转载收藏学习
- 下一篇: 空间点三维坐标计算