|   银杏科技有限公司旗下技术文档发布平台   | 
	
	
		| 技术支持电话 | 0379-69926675-801 | 
	
	
		| 技术支持邮件 | Gingko@vip.163.com | 
	
	
		|   版本   |   日期   |   作者   |   修改内容   | 
	
	
		|   V1.0   |   2020-11-25  |   zgf   |   初次建立   | 
	
 
实验十一:GPIO输入实验——识别按键输入
一、 实验目的与意义
 了解按键特征和应用。
 
 学习按键动作的识别和判断。
 
 学习按键消抖的处理方法。
 
 
二、 实验设备及平台
 iCore3L 双核心板。
 
 XiST USB Cable(或相同功能)仿真器。
 
 Micro USB线缆。
 
 装有HqFpga开发软件的电脑一台。
 
 
三、 实验原理
 SL2S-25E的I/O单元包含1个双向I/O换从器和三个寄存器;可以使用I/O单元用于输入、输出或双向数据路径。
 
 iCore3L上有一个按键和FPGA相连,原理图如图11-1中所示。从原理图中可以看到,按键未按下时,FPGA引脚接3.3V,引脚电平为高。当按键按下后,FPGA引脚与地导通,此时FPGA引脚电平为低。那么,判断按键是否按下的方法就是将与按键相连的引脚作为输入引脚,并检测此引脚的电平,当电平为低时,表示按键按下。
 
 当检测到按键按下,设计代码功能为控制与LED相连的引脚电平为低,此时点亮LED。从而实现按键控制LED状态的功能。即通过检测FPGA·KEY引脚的电平变化,判断按键的状态,继而控制LED的亮灭。
 
 在按键按下和松开的过程,电平并不是理想的立即从高到低或者从低到高变化的。在跳变的过程中,是有抖动的,持续大概10ms左右。抖动会影响FPGA对按键状态的正确判断,因此在设计中要对按键动作做消抖处理。处理方式分物理消抖和软件消抖。物理消抖则是通过并联电容,消除抖动噪声。软件处理则是通过延时处理,跳过抖动阶段,再读取按键状态,从而实现按键消抖操作。
 
 如图11-2中所示,在实际的按键动作中,按下和松开的瞬间,电平跳变的过程中是有抖动存在的;在硬件设计中可以通过并联电容削减抖动造成的影响。在软件设计中可以采用延时消抖的方式进一步消除抖动的影响。
 
 延时消抖的实现方式也较为简单,当FPGA检测到与按键相连的引脚出现下降沿之后开始计时,约40ms后再次检测与按键相连引脚的电平;如果电平与之前不同,则判别为有按键按下。这样通过延时的方式跳过抖动阶段,检测稳定后的电平状态,从而降低抖动对电平判断的影响,识别真正的按键动作。
 
 同理,按键松开的动作也可以通过这种方式进行检测。在按键按下的状态,检测电平的上升沿,待出现上升沿后,开始计时;延时40ms后检测电平状态,从而判断按键是否松开。
 
 
四、 代码实现
//---------------------按键动作检测---------------------------//
	reg key_r;
	reg	key_rr;
 
	always@(posedge fpga_clkor negedge rst_n)
		if(!rst_n)
			begin
				key_r<=1'b0;
				key_rr<=1'b0;
			end
		else
			begin
				key_r<=key;			//输入信号延迟1拍
				key_rr<=key_r;		//输入信号延迟2拍
			end
 
	reg 	[19:0]cnt;
	reg		flag;
	always@(posedge fpga_clk or negedge rst_n)
		if(!rst_n)
			flag<=1'd1;
		else if((key_r==1'd0)&&(key_rr==1'd1))			//下降沿检测
				flag<=1'd0;
			else if((key_r==1'd1)&&(key_rr==1'd0))		//上升沿检测
				flag<=1'd1;
 
	always@(posedge fpga_clk or negedge rst_n)
		if(!rst_n)
			cnt<=20'd0;
		else if((cnt<20'd1000_000)&&(flag==1'b0))		//约40ms
			cnt<=cnt+1'd1;
		else if(flag==1'b1)
			cnt<=20'd0;
			else
				cnt<=20'd1000001;
 
	reg	[2:0]	led_r;
	always@(posedge fpga_clk or negedge rst_n)			//LED 状态切换
		if(!rst_n)
			led_r<=3'b110;
		else if(cnt==20'd1000_000)
			led_r<={led_r[1],led_r[0],led_r[2]};		//循环左移,三色LED颜色循环切换
 
五、 实验步骤
六、 实验现象