| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**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引脚电平为低。那么,判断按键是否按下的方法就是将与按键相连的引脚作为输入引脚,并检测此引脚的电平,当电平为低时,表示按键按下。 {{ :icore3l:icore3l_fpga_11_1.png?direct |图 11-1 按键及FPGA_LED原理图}} * 当检测到按键按下,设计代码功能为控制与LED相连的引脚电平为低,此时点亮LED。从而实现按键控制LED状态的功能。即通过检测FPGA·KEY引脚的电平变化,判断按键的状态,继而控制LED的亮灭。 * 在按键按下和松开的过程,电平并不是理想的立即从高到低或者从低到高变化的。在跳变的过程中,是有抖动的,持续大概10ms左右。抖动会影响FPGA对按键状态的正确判断,因此在设计中要对按键动作做消抖处理。处理方式分物理消抖和软件消抖。物理消抖则是通过并联电容,消除抖动噪声。软件处理则是通过延时处理,跳过抖动阶段,再读取按键状态,从而实现按键消抖操作。 {{ :icore3l:icore3l_fpga_11_2.png?direct&600 |图11-2 按键动作过程电平变化示意图}} * 如图11-2中所示,在实际的按键动作中,按下和松开的瞬间,电平跳变的过程中是有抖动存在的;在硬件设计中可以通过并联电容削减抖动造成的影响。在软件设计中可以采用延时消抖的方式进一步消除抖动的影响。 * 延时消抖的实现方式也较为简单,当FPGA检测到与按键相连的引脚出现下降沿之后开始计时,约40ms后再次检测与按键相连引脚的电平;如果电平与之前不同,则判别为有按键按下。这样通过延时的方式跳过抖动阶段,检测稳定后的电平状态,从而降低抖动对电平判断的影响,识别真正的按键动作。 * 同理,按键松开的动作也可以通过这种方式进行检测。在按键按下的状态,检测电平的上升沿,待出现上升沿后,开始计时;延时40ms后检测电平状态,从而判断按键是否松开。 ==== 四、 代码实现 ==== * 本实验代码较为简单,首先是对输入信号进行延迟1拍处理,是高低电平数字量处于稳定状态,便于进行沿跳变检测。检测到下降沿后开始计数,然后对时钟计数持续40ms后,采集按键输入引脚的电平,如果为低电平,表示按键按下,则控制三色LED颜色切换。这里请注意对延时计数器的控制,使其在按键按下期间持续计数。按键未按下时进行清零。代码如下: //---------------------按键动作检测---------------------------// 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颜色循环切换 ==== 五、 实验步骤 ==== * 1、新建工程,点击左侧栏中“新建工程”按钮,弹出“设置(S)”窗口中填写工程名称,选择目标器件为SL2S-25E8U213C,设置输入类型为RTL描述,然后点击“下一步”,弹出“RTL输入”界面,直接点击“完成”。 * 2、点击左侧栏“设计管理”按钮,新建源文件,或者通过点击左侧边栏的“工程属性”按钮,将例程下的源文件添加到工程中,并将key模块设置成顶层模块。 {{ :icore3l:icore3l_fpga_11_3.png?direct |11-3 添加源文件及设置顶层模块}} * 3、然后点击“RTL综合”按钮,进行初步编译;无报错后点击左侧栏里的“物理约束”按钮,将按键绑定到相应的引脚;然后点击保存并退出。 {{ :icore3l:icore3l_fpga_11_4.png?direct |图 11-4 添加物理约束,绑定引脚信息}} * 4、然后点击左侧栏“全部运行”按钮,进行全编译,生成下载用的bit文件;并将下载器连接到iCore3L双核心板上,给板子上电。 * 5、点击“下载/编程”按钮,将编译好的bit文件下载到FPGA中。 * 6、按下按键,观察LED状态的切换。 ==== 六、 实验现象 ==== * 按动iCore3L上的FPGA按键,iCore3L双核心板上的 FPGA·LED在每次按键按下后切换亮灭状态。