跳到主要内容

3.4 实验原理

3.4.1 蜂鸣器介绍

蜂鸣器的分类:

按其结构主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型: 

  • 电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
  • 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。

按是否带有信号源分为有源蜂鸣器和无源蜂鸣器两种类型: 

  • 有源蜂鸣器只需要在其供电端加上额定直流电压,其内部的震荡器就可以产生固定频率的信号,驱动蜂鸣器发出声音。
  • 无源蜂鸣器可以理解成与喇叭一样,需要在其供电端上加上高低不断变化的电信号才可以驱动发出声音。

我们STEP BaseBoard V4.0底板上集成的蜂鸣器为无源电磁式蜂鸣器,接下来和大家一起学习无源蜂鸣器的驱动

3.4.2 蜂鸣器驱动电路

无源蜂鸣器没有集成振荡器,需要外部提供震荡激励,当震荡频率不同时发出不同的音调,对于数字系统来说,方波信号产生方便可靠,成为外部震荡激励的首选,方波信号输入谐振装置转换为声音信号输出,电磁式蜂鸣器需要的驱动电流较高,一般单片机和FPGA管脚驱动能力有限不能直接驱动,常用三极管增加驱动能力,另外电磁式蜂鸣器内部含有感应线圈,在电路通断瞬间会产生感应电势,为保证电路长期稳定的工作,最好增加续流二极管设计,STEP BaseBoard V4.0底板蜂鸣器驱动电路如下:

alt text
蜂鸣器驱动电路

注:不需要蜂鸣器工作时,控制器BEEP端口输出低电平,管脚配置下拉(pull down)模式

蜂鸣器使用NPN三极管(S8050)驱动,三极管当开关用,当基极电压拉高时,蜂鸣器通电,当基极电压拉低时,蜂鸣器断电,FPGA控制GPIO口给三极管的基极输出不同频率的脉冲信号,蜂鸣器就可以发出不同的音节。

3.4.3 蜂鸣器驱动设计

前面我们了解到电磁式无源蜂鸣器需要外部提供震荡激励才可以发出声音,且震荡频率不同产生的音调也不同,不同音节与蜂鸣器震荡频率的对应关系如下表:

音调频率对照表

音节名频率(Hz)音节名频率(Hz)音节名频率(Hz)
低音1261.6中音1523.3高音11045.5
低音2293.7中音2587.3高音21174.7
低音3329.6中音3659.3高音31318.5
低音4349.2中音4698.5高音41396.9
低音5392中音5784高音51568
低音6440中音6880高音61760
低音7493.9中音7987.8高音71975.5

FPGA要驱动蜂鸣器就需要给蜂鸣器模块输出《音调频率对照表》中不同频率的脉冲信号就可以了,我们在基础数字电路实验中学习过PWM产生原理,设计过一个PWM信号发生器模块,模块根据两个输入信号(cycle、duty)控制产生周期可控、占空比可控的脉冲信号(pwm_out),可以用来驱动无源蜂鸣器电路。

PWM模块端口程序如下:

module PWM #
(
parameter WIDTH = 32 //ensure that 2**WIDTH > cycle
)
(
input clk,
input rst_n,
input [WIDTH-1:0] cycle, //cycle > duty
input [WIDTH-1:0] duty, //duty < cycle
output reg pwm_out
);
  • cycle:基于系统时钟的计数器计数终值,与产生脉冲信号的周期有关
  • duty:脉冲信号产生机制中的比较器阈值,与产生脉冲信号的脉宽(占空比)有关

驱动蜂鸣器的脉冲信号对占空比没有太高的要求,我们默认产生50%占空比的脉冲信号,所以duty的输入取cycle的一半;cycle的值关乎蜂鸣器的音节,需要和《音调频率对照表》中对应,例如如果要蜂鸣器发出低音1的音节,脉冲信号频率控制为261.6Hz,系统时钟采用12MHz,计数器计数终值cycle就等于12M / 261.6 = 45872,即当我们给PWM模块中cycle信号的值为45872时,得到低音1的音节输出。这样我们将每个音节对应的cycle值计算出来,当按动不同按键时给PWM模块不同的cycle值就可以了,我们可以通过设计一个转码模块(tone)将按键信息转换成PWM需要的cycle信号,矩阵键盘共有16个按键,我们只能输出16个音节。

PWM周期转码程序实现如下:

always@(key_in) begin
case(key_in)
16'h0001: cycle = 16'd45872; //L1,
16'h0002: cycle = 16'd40858; //L2,
16'h0004: cycle = 16'd36408; //L3,
16'h0008: cycle = 16'd34364; //L4,
16'h0010: cycle = 16'd30612; //L5,
16'h0020: cycle = 16'd27273; //L6,
16'h0040: cycle = 16'd24296; //L7,
16'h0080: cycle = 16'd22931; //M1,
16'h0100: cycle = 16'd20432; //M2,
16'h0200: cycle = 16'd18201; //M3,
16'h0400: cycle = 16'd17180; //M4,
16'h0800: cycle = 16'd15306; //M5,
16'h1000: cycle = 16'd13636; //M6,
16'h2000: cycle = 16'd12148; //M7,
16'h4000: cycle = 16'd11478; //H1,
16'h8000: cycle = 16'd10215; //H2,
default: cycle = 16'd0; //cycle为0,PWM占空比为0,低电平
endcase
end

现在我们在Beeper模块中实例化tone和PWM模块,将tone的输出与PWM的cycle输入连线就实现了按键信息产生对应音节的输出了,想一想逻辑有问题吗?

  • 当我们按下按键,会得到按键信息,根据按键信息转码得到一个cycle值,连线传输给PWM模块,产生对应频率脉冲,听到对应音节输出;
  • 当我们松开按键,同样有按键信息,对应到转码模块中得到cycle值为0,连线传输给PWM模块,产生低电平信号,蜂鸣器不发声。

应该没错了,到这里我们就完成了蜂鸣器音节驱动部分。

3.4.4 系统总体实现

前次实验中我们学习了矩阵键盘的驱动原理及方法,这里就不再重复,不一样的是之前我们用的矩阵键盘模块的脉冲输出(key_pulse),本实验中简易电子琴在按键按下状态下一直发声,跟按键时间长短有关,这样我们就不能使用key_pulse了,而应该使用key_out信号,另外key_out按键有效输出为低电平,而PWM周期转码模块(tone)是高有效编码,所以在顶层模块(Electric_Piano)中矩阵键盘(Array_KeyBoard)与蜂鸣器音节驱动模块(Beeper)之间的key_out连线需要做按位取反操作。

总体设计程序实现如下:

//Array_KeyBoard 
Array_KeyBoard u1
(
.clk (clk ),
.rst_n (rst_n ),
.col (col ),
.row (row ),
.key_out (key_out ),
.key_pulse (key_pulse )
);

//beeper module
Beeper u2
(
.clk_in (clk_in ),
.rst_n_in (rst_n_in ),
.key_out (~key_out ),
.beeper (beeper )
);

综合后的设计框图如下:

alt text
RTL设计框图