日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蜂鸣器播放《两只老虎》

發布時間:2023/12/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蜂鸣器播放《两只老虎》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、回顧蜂鳴器
  • 二、樂譜知識
    • 2.1 音符音頻
    • 2.2 兩只老虎樂譜
  • 三、系統框圖
  • 四、模塊調用
  • 五、模塊原理圖
  • 六、工程源碼
    • 6.1 音符選擇模塊代碼
    • 6.2 pwm產生模塊代碼
    • 6.3 頂層模塊代碼
  • 七、仿真測試
    • 7.1 測試代碼
    • 7.2 仿真結果
  • 八、管腳信息
  • 九、運行效果
  • 總結


前言

??通過往期的按鍵控制蜂鳴器課程,我們了解了蜂鳴器器件,本次課程將使用蜂鳴器,播放我小時候經常聽的《兩只老虎》音樂,來勾起我童年的回憶。


一、回顧蜂鳴器

??我們回顧一下蜂鳴器的知識:

  • 按照工作原理可分為:壓電式蜂鳴器和電磁式蜂鳴器。
  • 按照音源可分為:有源蜂鳴器和無源蜂鳴器。
  • 有源蜂鳴器:內部有振蕩源,直接通以直流電即可發出聲音。
  • 無源蜂鳴器:內部無振蕩源,需要通以方波、PWM信號才能發出聲音。
  • 圖1. 蜂鳴器原理圖

    ??無源蜂鳴器需要輸入一定頻率的方波或者脈沖寬度調制(Pulse Width Modulation,PWM)信號,蜂鳴器就可以發出聲音。輸入不同頻率的信號,蜂鳴器可以發出不同音色的聲音。《紅樓夢》中“未見其人先聞其聲”指的是王熙鳳,就是因為每個人發出的聲音頻率不同,所以音色也會不同,我們可以通過音色就知道誰是誰。


    二、樂譜知識

    2.1 音符音頻

    ??音頻(Audio),指人耳可以聽到的聲音頻率在20HZ~20kHz之間的聲波。樂普是由音符組成的,不同的音符擁有不同的頻率。音頻和周期的關系如下公式所示。
    T(周期)=1f(頻率)(1)T(周期) = \frac{1}{f(頻率)}\tag1T()=f()1?(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 endmodule

    6.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 endmodule

    6.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) ); endmodule

    7.2 仿真結果

    圖6. 仿真結果

    八、管腳信息

    圖7. pin planner 元件管腳
    KEY1E15
    KEY2E16
    KEY3M16
    KEY4M15
    CLOCK(時鐘)E1
    BUZZER(蜂鳴器)J1
    表2. 管腳信息表

    九、運行效果

    蜂鳴器播放兩只老虎


    總結

    ??以上就是本期蜂鳴器播放兩只老虎的主要內容,通過本次的學習,同學們下去可以使用蜂鳴器播放其他音樂,只要你手里面有樂譜,原理上是可以編寫任何音樂。趕緊行動起來,成為一個會寫代碼的音樂家吧!謝謝你的觀看。

    總結

    以上是生活随笔為你收集整理的蜂鸣器播放《两只老虎》的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。