kx3552驱动最佳连线图_定时器的设计以及驱动蜂鸣器

本次学习的是设计定时器来驱动蜂鸣器,并拓展一下电子琴的设计。定时器的核心单元本质就是一个计数器,设定一个预设值然后计数器开始计数,当计数达到我们想要的预设值时,启动标志位提示达到设定的时间。在本设计中,使用计数器来产生我们需要的PWM波,然后使用PWM波便能驱动蜂鸣器按照既定的频率鸣叫。

01

有源蜂鸣器与无源蜂鸣器

蜂鸣器是一种产生声音的电子元器件,采用DC直流稳压电源供电,广泛用于计算机、报警器、玩具车等电子产品中。蜂鸣器按照产品分类可分为两种,一种是有源蜂鸣器一种是无源蜂鸣器。

有源蜂鸣器:对于有源蜂鸣器其内部含有震荡源,对于有源蜂鸣器的驱动直接接上额定电源便可连续发声。

有源蜂鸣器的优点:程序控制简单方便,只需一个电平即可。

无源蜂鸣器:无源蜂鸣器内部不含震荡源,需要接在音频输出电路才能发声,所以用直流信号无法令其鸣叫,需用2K-5Khz的方波去驱动它。

无源蜂鸣器的优点:1、便宜;2、声音频率可控,不同的频率可以令蜂鸣器发出不同的声音,如电子琴就是使用的这一功能;

2d6870f1c368117c7d66585285326d1f.png

02

定时器的实现

首先第一步仍然是定义端口,以及定义端口类型。

2d4673f16407e505b74c6b70537a0cf1.png

首先我们得定义一个时钟信号clk,在AC620开发板上有一路板载50MHz的有源晶振提供一路时钟源。另外还需定义一路复位信号Rst_n。然后就是CNT_ACC用来设置目标值也就是期望值,期望计数多长。MODE用来设置计数模式,分为循环计数模式和单次计数模式。另外还需要一路启动信号Cnt_Go,当Cnt_Go为1时开始计时,当Cnt_Go为0时停止计时。CNT_NOW为当前的计数值。Full_Flag为标记信号,当一次计数满后,Full_Flag则置1。

对于这些端口类型,因为clk外接FPGA上的50M时钟源,所以定义为外部输入input型。对于复位信号Rst_n、计数启动信号Cnt_Go都由外部按键控制,所以也定义为input型。预设值信号CNT_ACC和模式选择信号MODE都由外部输入,所以都为input型。

对于当前计数值CNT_NOW以及标志信号Full_Flag则是由系统写入,所以定义为output输出类型。

接下来就要写逻辑时序。

f631d30e3b2b16c7a94ac5d619440a57.png

首先看第33行,总是关注clk时钟的上升沿和复位信号Rst_n的下降沿,当复位信号为0时if(!Rst_n)将计数寄存器cnt清零,如果复位信号不为零,则判断当前计数的模式,如果MODE为1循环模式,则继续判断计数信号Cnt_Go是否为1开始计数以及计数寄存器cnt是否计满,如果Cnt_Go为1且cnt小于目标值CNT_ACC则继续计数cnt加1,否则cnt清零。若计数模式MODE为0,则为单次计数模式,此时需要再定义一个标志位oneshot,用来标记单次计数的开始和结束,如第49行开始就是写标记信号oneshot的逻辑,当复位信号为0时,oneshot清零,复位信号不为0时且为单次计数模式则继续判断是否开始计数,若Cnt_Go为1,则将oneshot置1开始计数,当一次计满后cnt==CNT_ACC-1则将oneshot清零停止计数,其余时刻oneshot不变。这边是oneshot标记信号的逻辑。然后将oneshot标志信号写入第43行mode 0 的单次计数逻辑中,当oneshot为1时开始计数cnt自加否则cnt清零。

另外在这些时序逻辑的书写过程中还需要注意各端口的定义类型,在always@中运用的需要定义为reg型,比如cnt和oneshot。

cnt为计数的存储计数器,将cnt实时计数的值赋给定义的端口CNT_NOW(第27行)。然后就是标记信号(第28行)Full_Flag_r = (cnt == CNT_ACC-1)?1'b1:1'b0;这种写法是判断cnt是否等于CNT_ACC-1,是,则Full_Flag_r等于1'b1,否则Full_Flag_r等于1'b0(b表示2进制,最前面的1表示该变量为几位)。

到此基本的计时器逻辑就书写完了,然后可以书写仿真文件对其进行仿真。同样建立一个.v文件,

8f94ba1c7976ecc037d442b0e0ab3c12.png

定义仿真的时间间隔周期为1ns,第二行相当于c语言中的宏定义,让clk——period为20。然后定义仿真的端口与上一个.v文件里的端口连线进行仿真。

796cbd61fbc9ea33a1ad50ffa3bf64f0.png

这一步是仿真时钟信号,开始时让时钟信号clk为高电平1,然后每隔10ns让时钟信号clk翻转一次。这里的10ns是因为AC620 FPGA上的时钟源是50MHz换算成周期就是20ns,这样每一个时钟周期就是10ns的高电平和10ns的低电平。

e108cafdbf071106bcb905aeebe46881.png

然后就是对其功能进行仿真,开始时为了方便观察仿真现象,让其复位信号为0,预设值为0,模式为0,开始计数信号为0,延时20个周期,然后将复位信号置1,再延时20个周期。然后便可以设置想要的预设值和模式,并开始观察仿真现象。

下面几个为分别设置不同的预设值与循环模式来观察仿真现象。设置预设值为1000,模式为循环定时模式,延时12000个周期计数10次观察现象;设置预设值600,计数10次,模式为循环定时模式,延时8000个周期计数10次来观察现象;然后就是单次计数模式,同样分别设置预设值为1000和600。

接下来看一下仿真现象。

fe7936ef63ca87387785f15e6ee71a92.png

这是预设值1000,模式为循环计数模式,计满1000次处标记信号呈现了一次高电平,随后cnt计数信号又重新从0开始计数。

4f2224969497547a0402f649c3c9599a.png

这是预设值600,模式为循环计数模式,计满600次处标记信号呈现了一次高电平,随后cnt计数信号又重新从0开始计数。

6f9a8a9c9367cd45a9ef668292372f0a.png

这是预设值1000,模式为单次计数模式,计满1000次处标记信号呈现了一次高电平,随后cnt清零并不再变化。

f92d4d9945b54fd475b057b1515a18d8.png

这是预设值600,模式为单次计数模式,计满600次处标记信号呈现了一次高电平,随后cnt清零并不再变化。

在上述图中一直有一个问题,那就是标记信号并不是在cnt计满处上升,而总是提前一个周期到来,为此解决方案为设置一个变量过度一下。

8b60e8b119744d354e8a41b9bc2930a8.png

也就是这里为什么会突然增加一个Full_Flag_r的标记信号。然后再将Full_Flag_r的值赋给Full_Flag。

57aff961c64240278f7e5bbe0bc71eac.png

此处的Full_Flag_r因为不是在时序逻辑中使用所以定义为wire型。接下来看一下仿真结果。

90c16a739bf7705533c7a85c2cba7148.png

这是预设值1000,循环模式,设置一个过度后发现Full_Flag在计数达到1000时才升为高电平,在1000次计满之后降为低电平,实现标志提醒功能。

下面为600循环、1000单次和600单次的仿真图。

501c040c3e2197bbc5f51923b46d6b1c.png 5a167b765f7a9ac93a4ab54582433b4f.png 0b5db0eec8ffe0b90beaa357c97b5ece.png

03

触发蜂鸣器

对于定义端口这些此处就不再详细阐述,此处只需新加一个beep端口用来控制蜂鸣器,端口类型为output型。

4f8fee275d1564ffdd476b512f919177.png

然后就是引用前面的.v文件里的程序,然后和此处定义的端口进行连线。

70e35bb8354a3e23abc3ac51076a1729.png

对于预设值CNT_ACC处的32'd49999,此处是用来设置驱动蜂鸣器的频率,这里我给的是1KHz的频率,1KHz转化成周期就是1ms,而计数器每一个周期是20ns(FPGA上的50M时钟源对应周期是20ns),所以1ms=1000000ns,然后1000000ns/20ns=50000次[0:49999]。模式设置为循环模式,启动计数Cnt_Go连接到FPGA的按键上,用来控制蜂鸣器的鸣叫。

最后一步就是形成PWM波。

4fb856350f0130ef0842af32e7477be7.png

上面设置的是计数50000次,那就在他的中间值也就是25000次的时候做一个分界线,当当前计数值CNT_NOW大于25000时输出高电平,小于25000时输出低电平,从而形成方波。这就是这行代码的意思。

04

电子琴的设计

再建一个.v文件,同样的还是要先定义端口。

4a78d9d86af6b547442781683e56b5c5.png

然后再定义一个计数模块,就像前面的cnt一样,只不过这里的计数模块是用来切换频率的,不同的频率可以使蜂鸣器发出不同声音的鸣叫。

5cc7eca4f7e5c298ebbb61de92dcab24.png

index是设置用来计数的,每计20次循环一次,然后通过类似于c语言中的switch函数来给ACC赋值,当index取不同的值时便给ACC赋不同的值。也就是设置不同的频率,然后去驱动蜂鸣器。

bc317af39178935adf345cf56b9004ca.png

在驱动蜂鸣器的.v文件中引用并连线,此处需要注意的是需要再调用一个延时计数函数,因为原本的计数是用来计数频率的,此处电子琴的计数是需要计数周期,每隔一段时间切换一个频率,两者互不相同。

ec4bf94b43c1138fb9741adfbd8610c0.png

因此需要再写一个计数值,用来计时改变音调即计时改变频率,如此便实现了电子琴的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值