一、前置知识
电容触摸按键主要由按键 IC 部分和电容部分构成。按键 IC 部分主要由元器件供应商提供,用于将电容的变化转换为电信号。手指接触到触摸按键时,按键和手指之间产生寄生电容,使按键的总容值增加。
电容式触摸按键 IC 在检测到按键的感应电容值改变,并超过一定的阈值后,将输出有效信号表示按键被按下。
二、原理图分析

触摸 IC 型号为 AR101,其引脚功能如下:
| 引脚标号 | 功能描述 |
|---|---|
| OP1 = 0 | OUT 引脚输出信号高电平有效 |
| OP1 = 1 | OUT 引脚输出信号低电平有效 |
| OP2 = 0 | 触摸 IC 工作在同步模式,即触摸时输出有效电平,松开后无有效电平输出。 |
| OP2 = 1 | 触摸 IC 工作在保持模式,即检测到触摸操作后输出有效电平,松开后,输出电平保持不变。当再次检测到触摸操作时,输出电平变化并继续保持。 |
原理图中,触摸 IC 的引脚 OP1 和 OP2 均拉低,因此当手指按在触摸按键上时,TOUT 管脚输出高电平,松开后输出低电平。
需要注意,TOUT是被连在了P4排针座的TOUT端口上,需要用跳线帽将TOUT与连接在FPGA的TPAD端口短接。
三、代码流程分析
方法一:直接检测按键上升沿
需要判断TOUT产生的上升沿位置,在每个TOUT的上升沿,切换LED的状态。
按上述分析,我写出了以下简单的代码,it’s work。
//---------------------- Copyright (c) ----------------------// Copyright(C) ZHJ0125 2022// All rights reserved//-----------------------------------------------------------// File Name : touch_led.v// Created Date : 2022-04-15 17:54// Modified Date : 2022-04-15 17:54// Created By : ZHJ0125// Last Version : V0.1// Descriptions : 使用触摸按键控制LED。// 开发板上电后LED为熄灭状态,手指触摸后LED点亮;// 再次触摸,LED熄灭,以此循环。//-----------------------------------------------------------module touch_led(input clk,input rst_n,input touch_key,output reg [3:0] led);always @(posedge touch_key or negedge rst_n) beginif(!rst_n)led <= 4'd0; // 复位后LED全灭elseled <= ~led;endendmodule
方法二:保留两个KEY状态来判断上升沿
在正点原子手册中提供了以下思路:使用系统时钟触发方式,保留两个时钟周期内的KEY状态,根据两状态是否为低→高,判断是否为触摸按键的上升沿。
//---------------------- Copyright (c) ----------------------// Copyright(C) ZHJ0125 2022// All rights reserved//-----------------------------------------------------------// File Name : touch_led.v// Created Date : 2022-04-15 17:54// Modified Date : 2022-04-15 18:25// Created By : ZHJ0125// Last Version : V0.1// Descriptions : 使用触摸按键控制LED。// 开发板上电后LED为熄灭状态,手指触摸后LED点亮;// 再次触摸,LED熄灭,以此循环。//-----------------------------------------------------------//module touch_led(// input clk,// input rst_n,// input touch_key,// output reg [3:0] led//);////always @(posedge touch_key or negedge rst_n) begin// if(!rst_n)// led <= 4'd0; // 复位后LED全灭// else// led <= ~led;//end////endmodulemodule touch_led(input clk,input rst_n,input touch_key,output reg [3:0] led);reg touch_key_d0; // 本周期即当前的按键状态reg touch_key_d1; // 上一个周期的按键状态wire key_en; // 上升沿触发标志assign key_en = (~touch_key_d1) && touch_key_d0;// 处理记录两个周期的按键状态always @(posedge clk or negedge rst_n) beginif(!rst_n) begintouch_key_d0 <= 1'b0;touch_key_d1 <= 1'b0;endelse begintouch_key_d0 <= touch_key;touch_key_d1 <= touch_key_d0;endend// 处理设置LED状态always @(posedge clk or negedge rst_n) beginif(!rst_n) beginled <= 4'd0; // 复位后LED全灭endelse beginif(key_en) // 出现上升沿led <= ~led;elseled <= led;endendendmodule
实验效果与我编写的代码效果一致。
正点原子的方法巧妙之处在于记录了两次周期中按键的状态,根据两次按键状态来判断上升沿;而我的方法是直接使用Verilog语法判断按键上升沿。


