14. 触摸按键控制LED

14.1. 章节导读

触摸按键以具有坚固耐用、反应速度快、稳定、节省空间、易于操作等优点在我们的生活中已经随处可见,如遥控器、灯具、开关、各类家具等。本章节将带领大家了解触摸按键的工作原理以及完成利用触摸按键控制led灯的实验。

14.2. 理论学习

14.2.1. 触摸按键简介

触摸式按键可分为四大类:电阻式、电容式、红外线式以及表面波式感应按键。电阻式的工作原理就是使用人体迫压电阻,致使电阻大小改变。电阻的改变会致使整个电路信号出现变化,从而达到控制效果。但他的缺点也非常的大,迫压必须到一定程度,否则就无法达到其目的,这也是电阻式触摸按键的一大缺点,因此渐渐的被数码产品所 淘汰。红外则是利用光线对电流的影响,从而达到控制电路的作用,具体的工作原理为:每一个红外触摸按键都会发出光线,如果我们的手指将其中的红外光线遮挡,红外光线则会对电流进行控制从而达到对电路的控制。表面波式感应按键是利用声波扫描来识别是否按下。电阻式、红外线式于、表面波式触摸技术主要应用于触摸屏上,单个 按键很少使用。现在使用最为广泛的是电容式触摸按键,下面将着重介绍一下电容式触摸按键。

14.2.2. 电容式触摸按键

电容式触摸按键主要是为了克服电阻屏的耐用性提出的,电容式触摸按键的结构与电阻式的相似,但其是采用电容量为判断标准。电容式触摸按键可以穿透绝缘材料外壳20mm(玻璃、塑料等等)以上,能准确无误地侦测到手指的有效触摸。并能保证产品的灵敏度、稳定性、可靠性等,不会因环境条件的改变或长期使用而发生变化,并具 有防水和强抗干扰能力,超强防护,超强适应温度范围。其感应原理图如图 20‑1。

touchL002

图 20‑1 电容式触摸感应原理

如图 20‑1所示,左边为没触摸时按键的状态,右边为手指触摸按键时状态。电容感应原理是利用人体的感应电容来检测是否有手指存在,在没有手指按下时,按键上由于分布电容的存在,因此按键对地存在一定的静态电容,当人的手指按下或者接近按键时,人体的寄生电容将耦合到这个静态电容上,使按键的最终电容变大,该变化的 电容信号再输入到FPGA芯片内进行信号转换。

14.3. 实战演练

14.3.1. 实验目标

实验目标:使用触摸按键去控制led灯的亮灭,led灯初始状态为熄灭状态,当按下触摸按键时led灯点亮,当再次按下触摸按键时led灯熄灭。

14.3.2. 硬件资源

我们使用开发板上的一个触摸按键以及一个led灯去进行该实验的验证,如图 20‑2所示。

touchL003

图 20‑2 硬件资源

由原理图可知,征途Pro开发板的触摸按键未按下时为高电平、按下后为低电平;LED灯则为低电平点亮。如图 20‑3、图 20‑4所示。

touchL004

图 20‑3 触摸按键原理图

touchL005

图 20‑4 led灯原理图

14.3.3. 程序设计

硬件资源介绍完毕,我们开始实验工程的程序设计。

14.3.3.1. 模块说明

我们根据实验任务可以先画出我们的系统框图,根据框图我们可以更加明确的看到我们该如何完成这个实验。系统框图如图 20‑5所示。

touchL006

图 20‑5 触摸按键控制led灯系统框图

表格 20‑1 触摸按键控制led灯模块输入输出信号描述

信号

位宽

类型

功能描述

sys_clk

1Bit

Input

50MHz晶振时钟输入

sys_rst_n

1Bit

Input

复位信号,低电平有效

touch_key

1Bit

Input

触摸按键输入信号

led

1Bit

Output

led输出信号

由表格 20‑1可以看出我们输入时钟复位以及触摸按键输入信号即可,关键是怎么对这个触摸按键信号处理让其准确无误地去控制led灯输出。下面我们通过波形图去了解具体怎么控制led的输出。

波形图绘制

触摸按键控制led灯参考波形图,如图 20‑6所示。

touchL007

图 20‑6 触摸按键控制led灯波形图

如图 20‑6所示:触摸按键信号(touch_key)初始状态为高电平,当触摸按键时,触摸按键信号从高电平变为低电平了,松开后又变为高电平。如果我们用这个信号去直接控制led灯,不管我们用该触摸有效信号(低电平)去控制led灯亮还是灭,我们都需要持续作用在这个按键信号上才能使led灯亮或者灭,显然这 和我们的实验要求是不符合的。那么如何使触摸一次触摸按键,led灯状态就能变化一次呢?我们可以这样做:设计一个触摸有效的标志信号(touch_en),当我们的触摸信号由高电平变成了低电平(触摸按键的一瞬间)即表示触摸有效(也就是一个下降沿信号),即当触摸按键信号(touch_key)下降沿到来时按键有 效,所以我们只需对触摸输入信号的下降沿采样即可。

我们该如何准确找到这个下降沿呢?这就引入了另一个新的知识——边沿检测。边沿检测主要作用是能够准确的识别出单比特信号的上升沿或下降沿,也就是我们希望当上升沿或下降沿来到时,能够产生一个唯一标识上升沿或下降沿的脉冲信号来告诉我们上升沿或下降沿来了,我们就可以根据这个脉冲信号作为后续电路功能的启动。如图 20‑7所示,我们对同一信号打一拍后在①位置处就可以检测到上升沿,使之拉高一个时钟的脉冲;在②位置处可以检测到下降沿,使之拉高一个时钟的脉冲。要实现这个功能,我们该如何编写代码呢?

touchL008

图 20‑7 上升沿、下降沿采集

上升沿检测核心代码:在①处检测到data为高电平且data_reg为低电平时,表示有上升沿产生。

方法一:与逻辑实现

01 always@(posedge sys_clk or negedge sys_rst_n)

02 if(sys_rst_n == 1’b0)

03 podge <= 1’b0;

04 else if((data) && (~data_reg)) //核心逻辑

05 podge <= 1’b1;

06 else

07 podge <= 1’b0;

方法二:或逻辑实现

01 always@(posedge sys_clk or negedge sys_rst_n)

02 if(sys_rst_n == 1’b0)

03 podge <= 1’b0;

04 else if((~data) || (data_reg)) //核心逻辑

05 podge <= 1’b0;

06 else

07 podge <= 1’b1;

下降沿检测核心代码:在②处检测到data为低电平且data_reg为高电平时,表示有下降沿产生,和上升沿的情况刚好相反。

方法一:与逻辑实现

01 always@(posedge sys_clk or negedge sys_rst_n)

02 if(sys_rst_n == 1’b0)

03 nedge <= 1’b0;

04 else if((~data) && (data_reg)) //核心逻辑

05 nedge <= 1’b1;

06 else

07 nedge <= 1’b0;

方法二:或逻辑实现

01 always@(posedge sys_clk or negedge sys_rst_n)

02 if(sys_rst_n == 1’b0)

03 nedge <= 1’b0;

04 else if((data) || (~data_reg)) //核心逻辑

05 nedge <= 1’b0;

06 else

07 nedge <= 1’b1;

注:上面的例子是用时序逻辑实现的,和图 20‑7所示波形完全一致。其核心逻辑也可以结合三目运算符用组合逻辑assign来实现,会使podge和nedge检测到上升沿和下降沿的脉冲均会提前一拍。希望大家能够记住边沿检测的核心逻辑以方便使用,当看到类似的代码也可以反推出检测的是上升沿还是下降沿。

通过上面的分析,我们知道如何找到下降沿,并产生一个下降沿标志信号(touch_en)。后面大家对信号沿采样也可使用这种方法。产生下降沿信号后,通过该信号去控制led灯变化,来一次下降沿对led取反一次,这样就能满足我们的实验要求了。本设计思路只做参考,并非唯一方法,读者也可利用所学知识按照自己思路进 行设计。

代码编写

参照绘制波形图,编写模块代码。模块参考代码,具体见代码清单 20‑1。

代码清单 20‑1 触摸按键控制led灯参考代码(touch_ctrl_led.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module touch_ctrl_led
(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire touch_key , //触摸按键信号

output reg led //led输出信号

);

 ////
 //\* Parameter and Internal Signal \//
 ////

 //reg define
 reg touch_key_dly1 ; //touch_key延迟一个时钟信号
 reg touch_key_dly2 ; //touch_key延迟两个时钟信号

 //wire define
 wire touch_en ; //触摸使能信号

 ///
 //\* Main Code \//
 ////

 //根据触摸按键信号的下降沿判断触摸了触摸按键
 assign touch_en = touch_key_dly2 & (~touch_key_dly1);

 //对touch_key信号延迟两个时钟周期用来产生触摸按键信号
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 begin
 touch_key_dly1 <= 1'b0;
 touch_key_dly2 <= 1'b0;
 end
 else
 begin
 touch_key_dly1 <= touch_key;
 touch_key_dly2 <= touch_key_dly1;
 end

 //根据触摸使能信号控制led状态
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 led <= 1'b1;
 else if(touch_en == 1'b1)
 led <= ~led;

 endmodule

由于代码较为简单并且上面针对波形图已经对各个信号的逻辑关系进行了详细的讲解,代码上也有相应注释,在此就不再叙述。代码完成之后即可编写测试文件进行仿真测试。

14.3.3.2. 仿真验证

仿真代码编写

编写仿真代码,对参考代码进行仿真验证。仿真参考代码,具体见代码清单 20‑2。

代码清单 20‑2 触摸按键控制led灯仿真参考代码(tb_touch_ctrl_led.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
\`timescale 1ns/1ns
module tb_touch_ctrl_led();

////
//\* Parameter and Internal Signal \//
////

//wire define
wire led ;

 //reg define
 reg sys_clk ;
 reg sys_rst_n ;
 reg touch_key ;

 ////
 //\* Main Code \//
 ////

 //sys_clk,sys_rst_n初始赋值,模拟触摸按键信号值
 initial
 begin
 sys_clk = 1'b1 ;
 sys_rst_n <= 1'b0 ;
 touch_key <= 1'b1 ;
 #200
 sys_rst_n <= 1'b1 ;
 #200
 touch_key <= 1'b0 ;
 #2000
 touch_key <= 1'b1 ;
 #1000
 touch_key <= 1'b0 ;
 #3000
 touch_key <= 1'b1 ;
 end

 //clk:产生时钟
 always #10 sys_clk = ~sys_clk ;

 ////
 //\* Instantiation \//
 ////

 //-------------touch_ctrl_led_inst-------------
 touch_ctrl_led touch_ctrl_led_inst(
 .sys_clk (sys_clk ), //系统时钟,频率50MHz
 .sys_rst_n (sys_rst_n ), //复位信号,低电平有效
 .touch_key (touch_key ), //触摸按键信号

 .led (led ) //led输出信号
 );

 endmodule

仿真波形分析

配置好仿真文件,使用ModelSim对参考代码进行仿真,仿真结果如下图 20‑8所示。

touchL009

图 20‑8 触摸按键控制led仿真波形图

根据图 20‑8可以很清晰的看到当触摸按键按下时(touch_en=1)led的状态从高电平变为了低电平,再次按下时led的状态又从低电平变成了高电平,这与我们绘制的波形图是一致的,实现了我们的实验要求功能。

14.3.4. 上板调试

14.3.4.1. 引脚约束

仿真验证通过后,准备上板验证,上板验证之前先要进行引脚约束。工程中各输入输出信号与开发板引脚对应关系如表格 20‑2所示。

表格 20‑2 引脚分配表

信号名

信号类型

对应引脚

备注

sys_clk

input

E1

时钟

sys_rst_n

input

M15

复位

touch_key

input

K11

触摸按键

led

output

L7

LED灯

下面进行管脚分配,管脚的分配方法在前面章节已有所讲解,在此就不再过多叙述,管脚的分配如下图 20‑9所示。

touchL010

图 20‑9 管脚分配

14.3.4.2. 结果验证

管脚配置完成之后重新进行编译,编译完之后就可以进行下载验证了,在下载之前首先将电源与下载线与开发板连接好,如图 20‑10所示。

touchL011

图 20‑10 下载连线图

打开下载界面后,当检测到下载器(USB-Blaster)已连接之后,即可点击“Add File…”添加sof文件,添加好后点击“start”开始下载,随后界面会显示下载成功,如图 20‑11所示。

touchL012

图 20‑11 下载成功界面

下载成功后即可以开始验证了,当我们触摸开发板左边的触摸按键时led灯被点亮;再次触摸时led灯熄灭;则说明验证成功。

14.4. 章末总结

到这里,本章节讲解完毕,通过本章节相信大家对触摸按键有了更清晰的认识,以后应用起来会更加得心应手。

14.5. 拓展训练

更改代码,实现触摸按键触摸后led灯闪烁,再次触摸时led灯停止闪烁。