OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4633|回复: 0

[ALTERA] 《新起点之FPGA开发指南 V2.1》第九章 按键控制LED灯实验

[复制链接]

1107

主题

1118

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4615
金钱
4615
注册时间
2019-5-8
在线时间
1218 小时
发表于 2021-9-30 10:40:11 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2021-10-30 10:06 编辑

1)实验平台:正点原子新起点V2FPGA开发板
2)  章节摘自【正点原子】《新起点之FPGA开发指南 V2.1》
3)购买链接:https://detail.tmall.com/item.htm?id=609758951113
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_xinqidian(V2).html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:712557122 QQ群.png

原子哥.jpg

微信公众号.png






第九章 按键控制LED灯实验


按键是常用的一种控制器件。生活中我们可以见到各种形式的按键,由于其结构简单,成本低廉等特点,在家电、数码产品、玩具等方面有广泛的应用。本章我们将介绍如何使用按键控制多个LED的亮灭。
本章包括以下几个部分
99.1简介
9.2实验任务
9.3硬件设计
9.4程序设计
9.5下载验证


9.1简介
按键开关是一种电子开关,属于电子元器件类。我们的开发板上有两种按键开关:第一种是本实验所使用的轻触式按键开关(如图 9.1.1),简称轻触开关。使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时开关断开,其内部结构是靠金属弹片受力后发生形变来实现通断的;第二种是自锁按键(如图 9.1.2),自锁按键第一次按下后保持接通,即自锁,第二次按下后,开关断开,同时开关按钮弹出来,开发板上的电源键就是这种开关。
第九章 按键控制LED灯实验435.png
图 9.1.1 轻触式按键
第九章 按键控制LED灯实验494.png
图 9.1.2 自锁式按键
9.2实验任务
使用新起点开发板上的四个按键控制四个LED灯。不同按键按下时,四个LED灯显示不同效果。
9.3硬件设计
如图 9.3.1所示,本实验使用四个按键开关控制四个LED灯。
第九章 按键控制LED灯实验665.png
图 9.3.1 按键电路原理图
如上图所示,开发板上的5个按键未按下时,输出高电平,按下后,输出低电平。
本实验中,系统时钟、复位按键、按键和LED灯的管脚如下表所示。
表 9.3.1 触摸按键控制LED管脚分配图
表1.png
对应的TCL约束文件如下:
set_location_assignment PIN_M2 -to sys_clk
set_location_assignment PIN_M1 -to sys_rst_n
set_location_assignment PIN_E16 -to key[0]
set_location_assignment PIN_E15 -to key[1]
set_location_assignment PIN_M15 -to key[2]
set_location_assignment PIN_M16 -to key[3]
set_location_assignment PIN_D11 -to led[0]
set_location_assignment PIN_C11 -to led[1]
set_location_assignment PIN_E10 -to led[2]
set_location_assignment PIN_F9 -to led[3]
9.4程序设计
我们程序设计最终实现的效果为:无按键按下时,LED灯全灭;按键1按下时,LED灯显示自右向左的流水效果;按键2按下时,LED灯显示自左向右的流水效果;按键3按下时,四个LED灯同时闪烁;按键4按下时,LED灯全亮。
LED在流水效果和闪烁效果在时间间隔均为0.2秒,因此需要在程序中定义一个0.2s的计数器,即每隔0.2s,状态计数器加一。根据当前按键的状态选择不同的显示模式,不同的显示模式下四个led灯的亮灭随状态计数器的值改变,从而呈现出不同的显示效果。
第九章 按键控制LED灯实验1789.png
图 9.4.1 系统框图
按键控制led模块的代码如下所示:
  1. 1   module key_led(
  2. 2       input               sys_clk  ,    //50Mhz系统时钟
  3. 3       input               sys_rst_n,    //系统复位,低有效
  4. 4       input        [3:0]  key,          //按键输入信号
  5. 5       output  reg  [3:0]  led           //LED输出信号
  6. 6       );
  7. 7   
  8. 8   //reg define     
  9. 9   reg  [23:0] cnt;
  10. 10  reg  [1:0]  led_control;
  11. 11  
  12. 12  //用于计数0.2s的计数器
  13. 13  always [url=home.php?mod=space&uid=95564]@[/url] (posedge sys_clk or negedge sys_rst_n) begin
  14. 14      if(!sys_rst_n)
  15. 15          cnt<=24'd9_999_999;
  16. 16      else if(cnt<24'd9_999_999)
  17. 17          cnt<=cnt+1;
  18. 18      else
  19. 19          cnt<=0;
  20. 20  end
  21. 21  
  22. 22  //用于led灯状态的选择
  23. 23  always @(posedge sys_clk or negedge sys_rst_n) begin
  24. 24      if (!sys_rst_n)
  25. 25          led_control <= 2'b00;
  26. 26      else if(cnt == 24'd9_999_999)
  27. 27          led_control <= led_control + 1'b1;
  28. 28      else
  29. 29          led_control <= led_control;
  30. 30  end
  31. 31  
  32. 32  //识别按键,切换显示模式
  33. 33  always @(posedge sys_clk or negedge sys_rst_n) begin
  34. 34      if(!sys_rst_n) begin
  35. 35          led<=4'b 0000;
  36. 36      end
  37. 37      else if(key[0]== 0)  //按键1按下时,从右向左的流水灯效果
  38. 38          case (led_control)
  39. 39              2'b00   : led<=4'b1000;
  40. 40              2'b01   : led<=4'b0100;
  41. 41              2'b10   : led<=4'b0010;
  42. 42              2'b11   : led<=4'b0001;
  43. 43              default  : led<=4'b0000;
  44. 44          endcase
  45. 45      else if (key[1]==0)  //按键2按下时,从左向右的流水灯效果
  46. 46          case (led_control)
  47. 47              2'b00   : led<=4'b0001;
  48. 48              2'b01   : led<=4'b0010;
  49. 49              2'b10   : led<=4'b0100;
  50. 50              2'b11   : led<=4'b1000;
  51. 51              default  : led<=4'b0000;
  52. 52          endcase
  53. 53      else if (key[2]==0)  //按键3按下时,LED闪烁
  54. 54          case (led_control)
  55. 55              2'b00   : led<=4'b1111;
  56. 56              2'b01   : led<=4'b0000;
  57. 57              2'b10   : led<=4'b1111;
  58. 58              2'b11   : led<=4'b0000;
  59. 59              default  : led<=4'b0000;
  60. 60          endcase
  61. 61      else if (key[3]==0)  //按键4按下时,LED全亮
  62. 62          led=4'b1111;
  63. 63      else
  64. 64          led<=4'b0000;    //无按键按下时,LED熄灭     
  65. 65  end
  66. 66  
  67. 67  endmodule
复制代码


代码主要分为三个部分,第12至20行对系统时钟计数,当计数时间达0.2s时,计数器清零,同时使led_control在四个状态(00,01,10,11)内依次变化。第33至65行利用case语句实现对按键状态的检测,当不同的按键按下时,led随着led_control的变化,被赋予不同的值。
大家可以发现,本次实验和流水灯实验计数时间都是0.2s,本次实验的计数器最大可以计数到9_999_999,而流水灯实验中计数器的值最大可以计数到10_000_000。事实上,这两个实验计数器都是从0开始计数的,本次实验从0计数到9_999_999,需要10_000_000个时钟周期,而系统时钟为20ns,所以计数的时间为0.2s,而流水灯实验从0计数到10_000_000需要10_000_001个时钟周期,因此其计数时间实际上比0.2s要多出20ns。
为了验证我们的程序,我们在modelsim内对代码进行仿真。
Testbench模块代码如下:
  1. 1   `timescale 1 ns/ 1 ns
  2. 2   module tb_key_led();
  3. 3   
  4. 4   parameter T = 20;
  5. 5   
  6. 6   reg  [3:0]  key      ;
  7. 7   reg         sys_clk  ;
  8. 8   reg         sys_rst_n;
  9. 9   
  10. 10  wire [3:0]  led;
  11. 11  
  12. 12  initial begin   
  13. 13      key                <=4'b1111;//按键初始状态为全断开
  14. 14      sys_clk            <=1'b0;   //初始时钟为低电平
  15. 15      sys_rst_n          <=1'b0;   //复位信号初始为低电平
  16. 16  #T   sys_rst_n          <=1'b1;   //一个时钟周期后复位信号拉高
  17. 17  
  18. 18  #600_000_020 key[0]     <=0;      //0.6s时按下按键1
  19. 19  #800_000_000 key[0]     <=1;   
  20. 20  key[1]                  <=0;      //0.8s后松开按键1,按下按键2
  21. 21  #800_000_000 key[1]     <=1;   
  22. 22  key[2]                  <=0;      //0.8s后松开按键2,按下按键3
  23. 23  #800_000_000 key[2]     <=1;   
  24. 24  key[3]                  <=0;      //0.8s后松开按键3,按下按键4   
  25. 25  #800_000_000 key[3]     <=1;      //0.8s后松开按键4
  26. 26  
  27. 27  end
  28. 28  
  29. 29  always # (T/2) sys_clk <= ~sys_clk;
  30. 30  key_led   u_key_led(
  31. 31      .sys_clk(sys_clk),      
  32. 32      .sys_rst_n(sys_rst_n),     
  33. 33      .key(key),                  
  34. 34      .led(led)         
  35. 35      );
  36. 36  
  37. 37  endmodule
复制代码


第九章 按键控制LED灯实验5393.png
图 9.4.2 仿真图像
观察代码,结合波形分析可知。14至16行代码为对时钟信号、复位信号、按键信号赋初始值,默认为按键全断开。第0.6s时按下按键key0(kye[0]由高电平变为低电平),可观察到led3至led0依次点亮,呈现自右向左的流水效果;按键key1断开的同时按下按键key2,可观察到led0至led3依次点亮,呈现自左向右的流水效果;按键key2断开的同时按下按键key3s,可观察到led0至led3呈现闪烁效果;按键key3断开的同时按下按键key4,可观察到led0至led3保持全亮。
9.5下载验证
首先我们打开按键控制LED工程,在工程所在的路径下打开key_led/par文件夹,在里面找到“key_led.qpf”并双击打开。注意工程所在的路径名只能由字母、数字以及下划线组成,不能出现中文、空格以及特殊字符等。key_led工程打开后如图 9.5.1所示。
第九章 按键控制LED灯实验5858.png
图 9.5.1 打开工程
工程打开后通过点击工具栏中的“Programmer”图标(图中红框位置)打开下载界面。
下载界面如图 9.5.2所示,查看图中是否已经加载下载文件(sof文件)。如果没有,则需要通过点击“Add File”按钮添加流水灯工程中key_led/par/output_files目录下的“key_led.sof”文件。
第九章 按键控制LED灯实验6099.png
图 9.5.2 下载界面
如下图 9.5.3所示。将下载器一端连接电脑,另一端与开发板上的JTAG下载口相连接,如下图所示。然后连接电源线并打开电源开关。
第九章 按键控制LED灯实验6247.png
图 9.5.3 开发板按键
开发板电源打开后,在程序下载界面点击“Hardware Setup”,在弹出的对话框中选择当前的硬件连接为“USB-Blaster”。然后点击“Start”将工程编译完成后得到的sof文件下载到开发板中。
下载完成后,就可以利用按键来控制LED了,如图 9.5.3所示。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-10-3 22:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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