FPGA实战篇(按键控制蜂鸣器实验)

1.蜂鸣器简介
蜂鸣器按照驱动方式主要分为有源蜂鸣器和无源蜂鸣器,其主要区别为蜂鸣器内部是否含有震荡源。 一般的有源蜂鸣器内部自带了震荡源,只要通电就会发声。而无源蜂鸣器由于不含内部震荡源,需要外接震荡信号才能发声。

如上图所示,从外观上看,两种蜂鸣器很相似,如将两种蜂鸣器的引脚都朝上放置,能看到绿色电路板的是无源蜂鸣器,没有电路板而用黑胶封闭的一种是有源蜂鸣器。
相较于有源蜂鸣器,无源蜂鸣器成本更低,且发声频率可控。而有源蜂鸣器控制相对简单,由于内部自带震荡源,只要加上合适的直流电压即可发声。本次实验使用的蜂鸣器为有源蜂鸣器。
2.实验任务
本节实验任务是使用启明星上的 PL KEY0 按键来控制蜂鸣器发声。初始状态为蜂鸣器鸣叫,按下按键后蜂鸣器停止鸣叫,再次按下开关,蜂鸣器重新鸣叫。
3.硬件设计

上图为蜂鸣器控制电路的原理图。由于 ZYNQ 的 IO 其电流驱动能力有限,所以我们在蜂鸣器的驱动电路中加入三级管 Q1 ,以将 ZYNQ 的 IO 驱动电流放大,然后再驱动蜂鸣器。
管脚分配如下:



4.程序设计
由实验任务可知,我们只需要在按键按下时改变蜂鸣器的鸣叫状态即可。但实际上在按键按下的过程中存在按键抖动的干扰,体现在数字电路中就是不断变化的高低电平。为避免在抖动过程中采集到错误的按键状态,我们需要对按键数据进行消除抖动处理。
在这里我们先介绍一下按键消抖的原理。通常我们所使用的开关为机械弹性开关,当我们按下或松开按键时,由于弹片的物理特性,不能立即闭合或断开,往往会在断开或闭合的短时间内产生机械抖动,。
消除这种抖动的过程即称为按键消抖。
按键消抖可分为硬件消抖和软件消抖。硬件消抖主要使用 RS 触发器或电容等方法在硬件电路上实现消抖,一般在按键较少时使用。软件消抖的原理主要为按键按下或松开后,由处理器延时 5ms 至 20ms ,然后再对按键状态进行采样并判断。如下图所示:

由上面的分析可知,本次实验中的系统至少包含按键消抖模块和蜂鸣器控制两个模块。系统框图如下图所示:

按键消抖模块用于消除按键的抖动,消抖之后的信号用于控制蜂鸣器的鸣叫状态。程序中各模块端口及信号连接如下图所示:

由上图系统框图可知,代码部分包括三个模块。顶层模块(top_key_beep ),作用为完成对另外两个模块的例化。按键消抖模块(key_debounce ),主要用于对按键进行抖动滤除。按键控制蜂鸣器模块 (beep_control ),识别按键按下的那一刻,并对蜂鸣器的鸣叫状态进行翻转。
顶层模块代码如下:

python 复制代码
1 module top_key_beep(
2 input sys_clk ,
3 input sys_rst_n ,
4 
5 input key ,
6 output beep
7 );
8 
9 //wire define
10 wire key_value ;
11 wire key_flag ;
12 
13 //*****************************************************
14 //** main code
15 //*****************************************************
16 
17 //例化按键消抖模块
18 key_debounce u_key_debounce(
19 .sys_clk (sys_clk),
20 .sys_rst_n (sys_rst_n),
21 
22 .key (key),
23 .key_value (key_value),
24 .key_flag (key_flag)
25 );
26 
27 //例化蜂鸣器控制模块
28 beep_control u_beep_control(
29 .sys_clk (sys_clk),
30 .sys_rst_n (sys_rst_n),
31 
32 .key_value (key_value),
33 .key_flag (key_flag),
34 .beep (beep)
35 );
36 
37 endmodule

在顶层模块中例化了按键消抖模块和按键控制蜂鸣器模块。
按键消抖模块代码如下:

python 复制代码
1 module key_debounce(
2 input sys_clk ,
3 input sys_rst_n ,
4 
5 input key , //外部输入的按键值
6 output reg key_value , //消抖后的按键值
7 output reg key_flag //消抖后的按键值的效标志
8 );
9 
10 //reg define
11 reg [19:0] cnt ;
12 reg key_reg ;
13 
14 //*****************************************************
15 //** main code
16 //*****************************************************
17 
18 //按键值消抖
19 always @ (posedge sys_clk or negedge sys_rst_n) begin
20 if(!sys_rst_n) begin
21 cnt <= 20'd0;
22 key_reg <= 1'b1;
23 end
24 else begin
25 key_reg <= key; //将按键值延迟一拍
26 if(key_reg != key) begin //检测到按键状态发生变化
27 cnt <= 20'd100_0000; //则将计数器置为 20'd100_0000,
28 //即延时 100_0000 * 20ns(1s/50MHz) = 20ms
29 end
30 else begin //如果当前按键值和前一个按键值一样,即按键没有发生变化
31 if(cnt > 20'd0) //则计数器递减到 0
32 cnt <= cnt - 1'b1; 
33 else
34 cnt <= 20'd0;
35 end
36 end
37 end
38 
39 //将消抖后的最终的按键值送出去
40 always @ (posedge sys_clk or negedge sys_rst_n) begin
41 if(!sys_rst_n) begin
42 key_value <= 1'b1;
43 key_flag <= 1'b0;
44 end
45 //在计数器递减到 1 时送出按键值
46 else if(cnt == 20'd1) begin
47 key_value <= key;
48 key_flag <= 1'b1;
49 end
50 else begin
51 key_value <= key_value;
52 key_flag <= 1'b0;
53 end
54 end
55 
56 endmodule

代码中的第 26 行,每检测到按键被按下或松开,就让计数器从 100_0000 开始递减,时长 20ms 。在这20ms 期间,每当有抖动产生,计数器就被重置回 100_0000 ,即重新开始计时 20ms 。代码中的第 46 行,只有在计数器递减到 1 时,即此时计数器计时完了 20ms ,才会寄存按键的值。这样,每当按键被按下或松开,
20ms 内的抖动就被消除了。
蜂鸣器控制模块的代码如下:

python 复制代码
1 module beep_control(
2 input sys_clk,
3 input sys_rst_n,
4 
5 input key_value,
6 input key_flag,
7 output reg beep
8 );
9 
10 //*****************************************************
11 //** main code
12 //*****************************************************
13 
14 //每次按键按下时,就翻转蜂鸣器的状态
15 always @ (posedge sys_clk or negedge sys_rst_n) begin
16 if(!sys_rst_n)
17 beep <= 1'b1;
18 else if(key_flag && (key_value == 1'b0))
19 beep <= ~beep;
20 end
21 
22 endmodule

beep 初始状态为高电平,蜂鸣器鸣叫。当 key_flag 拉高表明消抖之后的按键数据有效,此时若检测到按键值为 0 (即按键被按下),就将 beep 状态取反,以改变蜂鸣器的鸣叫状态。
5.下载验证
连接开发板的电源和下载器,并打开电源开关。在工程编译之后,将生成的 bit 文件下载到开发板中。 下载完成后,蜂鸣器处于鸣叫状态。然后按下按键 PL_KEY0 ,蜂鸣器停止鸣叫。再次按下按键,蜂鸣器再次开始鸣叫。如下图所示:

相关推荐
仲南音1 天前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner2 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20202 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy2 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia2 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20202 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子3 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
9527华安3 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi
千寻xun4 天前
二、实战篇-NVME SSD控制之ZYNQ实现(六)-读写NVME SSD硬盘数据
fpga开发·nvme·nvme ssd
千寻xun4 天前
二、实战篇-NVME SSD控制之ZYNQ实现(三)
fpga开发·nvme ssd·nvme协议