【正点原子FPGA连载】第八章 按键控制LED灯实验

2020-01-30 15:49发布

本帖最后由 正点原子 于 2019-5-20 22:37 编辑

1)实验平台:正点原子开拓者FPGA开发板2)平台购买地址:https://item.taobao.com/item.htm?id=5797492098203)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-281143-1-1.html4)对正点原子FPGA感兴趣的同学可以加群讨论:712557122  点击加入:5)关注正点原子公众号,获取最新资料更新

erweima.png


第八章 按键控制LED灯实验
按键是常用的一种控制器件。 生活中我们可以见到各种形式的按键,由于其结构简单,成本低廉等特点, 在家电、数码产品、玩具等方面有广泛的应用。 本章我们将介绍如何使用按键控制多个LED的亮灭。
本章包括以下几个部分:
8.1 按键简介
8.2 实验任务
8.3 硬件设计
8.4 程序设计
8.5 下载验证
8.1 按键简介
按键开关是一种电子开关,属于电子元器件类。 我们的开发板上有两种按键开关: 第一种是本实验所使用的轻触式按键开关(如图 8.1.1) ,简称轻触开关。 使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时开关断开,其内部结构是靠金属弹片受力后发生形变来实现通断的;第二种是自锁按键(如图 8.1.2) , 自锁按键第一次按下后保持接通,即自锁,第二次按下后,开关断开,同时开关按钮弹出来, 开发板上的电源键就是这种开关。
image217.jpg
图 8.1.1 轻触式按键
image218.png
图 8.1.2 自锁式按键
8.2 实验任务
使用开拓者开发板上的四个按键控制四个LED灯。不同按键按下时, 四个LED灯显示不同效果。
8.3 硬件设计
如图 8.3.1所示,本实验使用四个按键开关控制四个LED灯。
image219.png
8.3.1 按键电路原理图如上图所示, 开发板上的5个按键未按下时,输出高电平, 按下后,输出低电平。本实验中,系统时钟、 复位按键、 按键和LED灯的管脚如下表所示。
8.3.1 触摸按键控制LED管脚分配图
QQ截图20190520222825.png
QQ截图20190520222846.png
8.4 程序设计
我们程序设计最终实现的效果为: 无按键按下时, LED灯全灭; 按键1按下时, LED灯显示自右向左的流水效果;按键2按下时, LED灯显示自左向右的流水效果;按键3按下时,四个LED灯同时闪烁; 按键4按下时, LED灯全亮。
LED在流水效果和闪烁效果在时间间隔均为0.2秒, 因此需要在程序中定义一个0.2s的计数器, 即每隔0.2s,状态计数器加一。根据当前按键的状态选择不同的显示模式,不同的显示模式下四个led灯的亮灭随状态计数器的值改变,从而呈现出不同的显示效果。
系统框图.png
图 8.4.1 系统框图
按键控制led模块的代码如下所示:
1 module key_led (
2 input sys_clk , //50Mhz系统时钟
3 input sys_rst_n, //系统复位,低有效
4 input [3:0] key, //按键输入信号
5 output reg [3:0] led //LED输出信号
6 );
7 8
//reg define
9 reg [23:0] cnt;
10 reg [1:0] led_control;
11
12
//用于计数0.2s的计数器
13 always @ (posedge sys_clk or negedge sys_rst_n) begin
14 if(!sys_rst_n)
15 cnt<=24'd 9_999_999;
16 else if(cnt<24'd 9_999_999)
17 cnt<=cnt+1;
18 else
19 cnt<=0;
20 end
21
22
//用于led灯状态的选择
23 always @(posedge sys_clk or negedge sys_rst_n) begin
24 if (!sys_rst_n)
25 led_control <= 2'b00;
26 else if(cnt == 24'd9_999_999)
27 led_control <= led_control + 1'b1;
28 else
29 led_control <= led_control;
30 end
31
32
//识别按键,切换显示模式
33 always @(posedge sys_clk or negedge sys_rst_n) begin
34 if(!sys_rst_n) begin
35 led<=4'b 0000;
36 end
37 else if(key[0]== 0) //按键1按下时,从右向左的流水灯效果
38 case (led_control)
39 2'b00 : led<=4'b1000;
40 2'b01 : led<=4'b0100;
41 2'b10 : led<=4'b0010;
42 2'b11 : led<=4'b0001;
43 default : led<=4'b0000;
44 endcase
45 else if (key[1]==0) //按键2按下时,从左向右的流水灯效果
46 case (led_control)
47 2'b00 : led<=4'b0001;
48 2'b01 : led<=4'b0010;
49 2'b10 : led<=4'b0100;
50 2'b11 : led<=4'b1000;
51 default : led<=4'b0000;
52 endcase
53 else if (key[2]==0) //按键3按下时, LED闪烁
54 case (led_control)
55 2'b00 : led<=4'b1111;
56 2'b01 : led<=4'b0000;
57 2'b10 : led<=4'b1111;
58 2'b11 : led<=4'b0000;
59 default : led<=4'b0000;
60 endcase
61 else if (key[3]==0) //按键4按下时, LED全亮
62 led=4'b1111;
63 else
64 led<=4'b0000; //无按键按下时, LED熄灭
65 end
66
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 `timescale 1 ns/ 1 ns
2 module tb_key_led();
3 4
parameter T = 20;
5 6
reg [3:0] key ;
7 reg sys_clk ;
8 reg sys_rst_n;
9 reg key_value;
10
11
wire [3:0] led;
12
13
initial begin
14 key <=4'b1111;//按键初始状态为全断开
15 sys_clk <=1'b0; //初始时钟为低电平
16 sys_rst_n <=1'b0; //复位信号初始为低电平
17 #T sys_rst_n <=1'b1; //一个时钟周期后复位信号拉高
18
19
#600_000_020 key[0] <=0; //0.6s时按下按键1
20 #800_000_000 key[0] <=1;
21 key[1] <=0; //0.8s后松开按键1,按下按键2
22 #800_000_000 key[1] <=1;
23 key[2] <=0; //0.8s后松开按键2,按下按键3
24 #800_000_000 key[2] <=1;
25 key[3] <=0; //0.8s后松开按键3,按下按键4
26 #800_000_000 key[3] <=1; //0.8s后松开按键4
27
28
end
29
30
always # (T/2) sys_clk <= ~sys_clk;
31 key_led u_key_led(
32 .sys_clk(sys_clk),
33 .sys_rst_n(sys_rst_n),
34 .key(key),
35 .led(led)
36 );
37
38
endmodule
image221.png
图 8.4.2 仿真图像
观察代码,结合波形分析可知。 14至16行代码为对时钟信号、 复位信号、 按键信号赋初始值, 默认为按键全断开。 第0.6s时按下按键key0(kye[0]由高电平变为低电平) ,可观察到led3至led0依次点亮, 呈现自右向左的流水效果;按键key1断开的同时按下按键key2, 可观察到led0至led3依次点亮, 呈现自左向右的流水效果;按键key2断开的同时按下按键key3s, 可观察到led0至led3呈现闪烁效果;按键key3断开的同时按下按键key4, 可观察到led0至led3保持全亮。
8.5 下载验证
首先我们打开按键控制LED工程, 在工程所在的路径下打开key_led/par文件夹, 在里面找到“key_led.qpf” 并双击打开。注意工程所在的路径名只能由字母、 数字以及下划线组成,不能出现中文、空格以及特殊字符等。 key_led工程打开后如图 8.5.1所示。
image222.png
图 8.5.1 打开工程
工程打开后通过点击工具栏中的“Programmer” 图标(图中红框位置)打开下载界面。下载界面如图 8.5.2所示,查看图中是否已经加载下载文件(sof文件) 。如果没有,则需要通过点击“Add File” 按钮添加流水灯工程中key_led/par/output_files目录下的
“key_led.sof” 文件。
image223.png
图 8.5.2 下载界面
如下图 8.5.3所示。将下载器一端连接电脑, 另一端与开发板上的JTAG下载口相连接,如下图所示。然后连接电源线并打开电源开关。

image224.jpg
图 8.5.3 开发板实物图
开发板电源打开后,在程序下载界面点击“Hardware Setup” ,在弹出的对话框中选择当前的硬件连接为“USB-Blaster” 。 然后点击“Start” 将工程编译完成后得到的sof文件下载到开发板中。
下载完成后,就可以利用按键来控制LED了,如图 8.5.3所示
  

0条回答

一周热门 更多>