首页 > 技术文章 > STEP模块——电子琴

tony-ning 2015-11-06 13:04 原文

电子琴原理

什么是声音?上过初中的朋友都知道声音是由震动所产生的。一定频率的震动就产生了一定频率的声音。

理论研究第一步,让喇叭发出do re mi fa sol la si的音,我们先不管do的频率是不是261hz,更重要的是我们必须知道,每个音之间的频率关系,初中老师说,do re mi这三个音相邻两个音是全音关系,mi 和 fa 是半音关系,fa sol la si 这四个音相邻两个音也是全音关系。全音关系意味着振动频率关系为2的开六次方,即1.12246,半音关系意味着频率关系为2的开16次方,即1.05946。什么意思呢?比如do为261hz,那么re 为261*1.12246=293hz,以此类推,mi为293*1.12246=329hz,fa和mi成半音关系,则fa为329*1.05946=348hz。这样算下去,可以得到所有音的频率了。

 

原理设计

通过产生脉冲信号驱动无源蜂鸣器来产生相应频率的声音,7个按键对应do re mi fa sol la si的音,蜂鸣器由三极管驱动

如图,按键需要加上拉电阻(由于FPGA内部可以设置为上啦,所以没有外接 )。蜂鸣器由三极管来驱动。使用小脚丫FPGA板

 

功能描述

模式一,通过按键来弹奏,同时按下do 和 si 键切换到自动播放模式

模式二,自动播放音乐,

 

verilog代码如下

 

  1 /*--------------------------------------------------------------------------------------
  2 -- Filename ﹕ piano.v
  3 -- Author ﹕tony-ning
  4 -- Description ﹕piano-based STEP PGGA board   
  5 -- Called by ﹕--
  6 -- Revision History ﹕15-10-26
  7 -- Revision 1.0
  8 -- 
  9 ---------------------------------------------------------------------------------------*/
 10 
 11 module piano
 12 (
 13     input CLK,
 14     input [7:1]key,
 15     output reg beep
 16 );
 17 /*-------------------------------define  --------------------------------------*/
 18     parameter    dao    =7'b1111110;        //261hz    countmax 47892
 19     parameter    ruai=7'b1111101;        //293hz    countmax 42662
 20     parameter    mi    =7'b1111011;        //329hz    countmax 37993
 21     parameter    fa    =7'b1110111;        //349hz    countmax 35816
 22     parameter    suo    =7'b1101111;        //392hz    countmax 31887
 23     parameter    la    =7'b1011111;        //440hz    countmax 28409
 24     parameter    xi    =7'b0111111;        //493hz    countmax 25354
 25 
 26     reg [6:0]sheet[0:32];
 27     
 28     initial
 29     begin
 30     sheet[0]<= 7'b1111110;
 31     sheet[1]<= 7'b1111110;
 32     sheet[2]<= 7'b1101111;
 33     sheet[3]<= 7'b1101111;
 34     sheet[4]<= 7'b1011111;
 35     sheet[5]<= 7'b1011111;
 36     sheet[6]<= 7'b1101111;
 37     sheet[7]<= 7'b1111111;
 38     sheet[8]<= 7'b1110111;
 39     sheet[9]<= 7'b1110111;
 40     sheet[10]<=mi;
 41     sheet[11]<=mi;
 42     sheet[12]<=ruai;
 43     sheet[13]<=ruai;
 44     sheet[14]<=dao;
 45     sheet[15]<=7'b1111111;
 46     sheet[16]<=7'b1101111;
 47     sheet[17]<=7'b1101111;
 48     sheet[18]<=7'b1110111;
 49     sheet[19]<=7'b1110111;
 50     sheet[20]<=mi;
 51     sheet[21]<=mi;
 52     sheet[22]<=ruai;
 53     sheet[23]<=7'b1111111;
 54     sheet[24]<=7'b1101111;
 55     sheet[25]<=7'b1101111;
 56     sheet[26]<=7'b1110111;
 57     sheet[27]<=7'b1110111;
 58     sheet[28]<=mi;
 59     sheet[29]<=mi;
 60     sheet[30]<=dao;
 61     sheet[31]<=7'b1111111;
 62     end
 63 /*-------------------------------use internal osc--------------------------------------
 64     // Internal Oscillator
 65      defparam OSCH_inst.NOM_FREQ = "2.08";// This is the default frequency
 66     //defparam OSCH_inst.NOM_FREQ = "24.18";
 67     OSCH OSCH_inst( .STDBY(1'b0), // 0=Enabled, 1=Disabled
 68     // also Disabled with Bandgap=OFF
 69     .OSC(osc_clk),
 70     .SEDSTDBY()); // this signal is not required if not
 71     // using SED
 72     
 73 -------------------------------piano --------------------------------------*/
 74     reg [15:0]rcount=0,countmax,mcount;
 75     reg run,state=0;
 76     reg [8:0]num=0;
 77     reg [6:0]rsheet;
 78     always@(posedge CLK)
 79         case(state)
 80         0:    begin
 81                 case(key)
 82                 dao    :    begin countmax<=47892; run<=1; if(countmax >47892)rcount<=0; end    //set the max count
 83                 ruai:    begin countmax<=42662; run<=1; if(countmax >42662)rcount<=0; end
 84                 mi    :    begin countmax<=37993; run<=1; if(countmax >37993)rcount<=0; end
 85                 fa    :    begin countmax<=35816; run<=1; if(countmax >35816)rcount<=0; end
 86                 suo    :    begin countmax<=31887; run<=1; if(countmax >31887)rcount<=0; end
 87                 la    :    begin countmax<=28409; run<=1; if(countmax >28409)rcount<=0;  end
 88                 xi    :    begin countmax<=25354; run<=1; if(countmax >25354)rcount<=0;  end
 89                 default : run<=0;
 90                 endcase
 91                 
 92                 if(rcount==countmax && run)            //produce the frequency
 93                     begin
 94                     rcount<=0;
 95                     beep<=~beep;
 96                     end
 97                 else rcount<=rcount+1;
 98                 
 99                 if(key==7'b0111110)                //push dao and xi keys will play the pre sound
100                     state<=1;
101             
102             end
103             
104         1:    begin
105                 if(mcount==12_500_000)            //meter produce
106                     begin
107                         mcount<=0;
108                         if(num==31)
109                             num<=0;
110                         else num<=num+1;
111                         rsheet<=sheet[num];
112                     end
113                 else mcount<=mcount+1;
114                 
115                 case(rsheet)
116                    dao    :    begin countmax<=47892; run<=1; if(countmax >47892)rcount<=0; end    //set the max count
117                    ruai :    begin countmax<=42662; run<=1; if(countmax >42662)rcount<=0; end
118                    mi    :    begin countmax<=37993; run<=1; if(countmax >37993)rcount<=0; end
119                    fa    :    begin countmax<=35816; run<=1; if(countmax >35816)rcount<=0; end
120                    suo    :    begin countmax<=31887; run<=1; if(countmax >31887)rcount<=0; end
121                    la    :    begin countmax<=28409; run<=1; if(countmax >28409)rcount<=0;  end
122                    xi    :    begin countmax<=25354; run<=1; if(countmax >25354)rcount<=0;  end
123                 default : run<=0;
124                 endcase
125                 
126                 if((rcount==countmax) && run)            //produce the frequency
127                     begin
128                     rcount<=0;
129                     beep<=~beep;
130                     end
131                 else rcount<=rcount+1;
132                 
133                 
134                 if(key==7'b0111101)                //push dao and la keys will back to make music
135                     state<=0;
136                 
137             end
138         endcase
139 
140 
141     
142         
143         
144         
145 
146 
147 
148 endmodule
149     
piano.v

 

 

PCB

实物图

推荐阅读