搜索
bottom↓
回复: 0

《领航者ZYNQ之FPGA开发指南_V2》第十章 按键控制蜂鸣器实验

[复制链接]

出0入234汤圆

发表于 2021-11-6 16:16:46 | 显示全部楼层 |阅读模式
1)实验平台:正点原子领航者V2 ZYNQ开发板
2)  章节摘自【正点原子】《领航者ZYNQ之FPGA开发指南_V2 》
3)购买链接:https://detail.tmall.com/item.htm?id=609032204975
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-329957-1-1.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:905624739
1.png

2.jpg


3.png


第十章 按键控制蜂鸣器实验

       蜂鸣器(Buzzer)是现代常用的一种电子发声器,主要用于产生声音信号。蜂鸣器在生活中已经得到广泛使用,其典型应用包括医疗,消防等领域的各种报警装置以及日常生活中的各种警报器等。本章我们主要学习如何使用按键来控制蜂鸣器发声。
       本章包括以下几个部分:
       1.1蜂鸣器简介
       1.2实验任务
       1.3硬件设计
       1.4程序设计
       1.5下载验证

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

图 7.5.13.1 有源蜂鸣器(左)和无源蜂鸣器(右)

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

图 7.5.13.1 蜂鸣器控制电路原理图

       上图为蜂鸣器控制电路的原理图。由于ZYNQ的IO其电流驱动能力有限,所以我们在蜂鸣器的驱动电路中加入三级管Q1,以将ZYNQ的IO驱动电流放大,然后再驱动蜂鸣器。
       本实验的管脚分配如下表所示,其中时钟源位于核心板上,复位按键、用户按键、蜂鸣器都位于底板上:
3.png

表 10.3.1 按键控制蜂鸣器实验管脚分配


对应的XDC约束语句如下所示:
  1. set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports {beep}]
  2. set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {key}]
  3. set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
  4. set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
复制代码
1.4程序设计
       由实验任务可知,我们只需要在按键按下时改变蜂鸣器的鸣叫状态即可。但实际上在按键按下的过程中存在按键抖动的干扰,体现在数字电路中就是不断变化的高低电平。为避免在抖动过程中采集到错误的按键状态,我们需要对按键数据进行消除抖动处理。
       在这里我们先介绍一下按键消抖的原理。通常我们所使用的开关为机械弹性开关,当我们按下或松开按键时,由于弹片的物理特性,不能立即闭合或断开,往往会在断开或闭合的短时间内产生机械抖动,。消除这种抖动的过程即称为按键消抖。
       按键消抖可分为硬件消抖和软件消抖。硬件消抖主要使用RS触发器或电容等方法在硬件电路上实现消抖,一般在按键较少时使用。软件消抖的原理主要为按键按下或松开后,由处理器延时5ms至20ms,然后再对按键状态进行采样并判断。如下图所示:
第十章 按键控制蜂鸣器实验1758.png

图 7.5.13.1 按键消抖原理图

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

图 7.5.13.2 按键控制蜂鸣器系统框图

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

图 7.5.13.3 端口及信号连接图

       由上图系统框图可知,代码部分包括三个模块。顶层模块(top_key_beep),作用为完成对另外两个模块的例化。按键消抖模块(key_debounce),主要用于对按键进行抖动滤除。按键控制蜂鸣器模块(beep_control),识别按键按下的那一刻,并对蜂鸣器的鸣叫状态进行翻转。
       顶层模块代码如下:
  1. 1   module top_key_beep(
  2. 2       input    sys_clk ,
  3. 3       input    sys_rst_n ,
  4. 4   
  5. 5       input    key ,
  6. 6       output   beep
  7. 7   );
  8. 8   
  9. 9   //wire define
  10. 10  wire key_value ;
  11. 11  wire key_flag ;
  12. 12  
  13. 13  //*****************************************************
  14. 14  //**                    main code
  15. 15  //*****************************************************
  16. 16  
  17. 17  //例化按键消抖模块
  18. 18  key_debounce  u_key_debounce(
  19. 19      .sys_clk    (sys_clk),
  20. 20      .sys_rst_n  (sys_rst_n),
  21. 21  
  22. 22      .key        (key),
  23. 23      .key_value  (key_value),
  24. 24      .key_flag   (key_flag)
  25. 25      );
  26. 26  
  27. 27  //例化蜂鸣器控制模块
  28. 28  beep_control  u_beep_control(
  29. 29      .sys_clk    (sys_clk),
  30. 30      .sys_rst_n  (sys_rst_n),
  31. 31  
  32. 32      .key_value  (key_value),
  33. 33      .key_flag   (key_flag),
  34. 34      .beep       (beep)
  35. 35      );
  36. 36  
  37. 37  endmodule
复制代码

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

       代码中的第26行,每检测到按键被按下或松开,就让计数器从100_0000开始递减,时长20ms。在这20ms期间,每当有抖动产生,计数器就被重置回100_0000,即重新开始计时20ms。代码中的第46行,只有在计数器递减到1时,即此时计数器计时完了20ms,才会寄存按键的值。这样,每当按键被按下或松开,20ms内的抖动就被消除了。
       蜂鸣器控制模块的代码如下:
  1. 1   module beep_control(
  2. 2       input        sys_clk,
  3. 3       input        sys_rst_n,
  4. 4   
  5. 5       input        key_value,
  6. 6       input        key_flag,
  7. 7       output  reg  beep
  8. 8       );
  9. 9   
  10. 10  //*****************************************************
  11. 11  //**                    main code
  12. 12  //*****************************************************
  13. 13  
  14. 14  //每次按键按下时,就翻转蜂鸣器的状态
  15. 15  always @ (posedge sys_clk or negedge sys_rst_n) begin
  16. 16      if(!sys_rst_n)
  17. 17          beep <= 1'b1;
  18. 18      else if(key_flag && (key_value == 1'b0))
  19. 19          beep <= ~beep;
  20. 20  end
  21. 21  
  22. 22  endmodule
复制代码

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

图 7.5.13.1 实验现象



回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 09:45

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表