4x4按键扫描前几贴介绍了时钟使用与反跳处理,本帖以4x4按键扫描一个具体的简单示例展示如何运用时钟与反跳处理。4x4按键电路简介4x4按键排列成4行4列结构共16个按键,8根引线。这8根引线分别是行线4根和列线4根。在FPGA连接电路中可以把行线作为输入,列线作为输出,或者相反。本示例选用列作为输入,行作为输出。作为输入的4条列线应该分别接10K上拉电阻,或者在FPGA内部设置列输入为弱上拉。VHDL定义行和列引脚如下: col_in : in std_vector(0 to 3); --列输入 ln_out : out std_vector(0 to 3); --行输出按键扫描方法ln_out循环输出0111, 1011, 1101, 1110,每次输出只有1行为0其他3行为1。同时每改变一次输出,读取col_in一次。那么一轮循环共读取16个比特的数值。这16个比特中值为0的表示对应按键被按下,如果全1说明没有按键按下。具体实现按键实现模块命名为Key4x4_scan,系统时钟采用50M。Entity Key4x4_scan is Port( clk50M : in std_logic; col_in : in std_vector(0 to 3); ln_out : out std_vector(0 to 3); qKey : out std_vector(0 to 3); kPress : out std_logic );End entity Key4x4_scan;引脚功能描述:clk50M:系统50M时钟。kPress:无按键按下时值为0,有按键按下时值为1。qKey:按键号的4比特编码,值0~15。kPress=0时不不关心qKey数值。模块实现全部代码Architecture myFavor of Key4x4_scan is attributealtera_attribute : string; alias clock : std_logic isclk50M; signal C1K : std_vector(0to 15); signal kDn : std_vector(0to 15); signal scan : std_vector(0to 1); signal P1K,smp : std_logic; signal k_rd,k_same : std_logic; signal kCode : std_vector(0 to 4); signal cn_bounce : std_vector(0 to 4); --128ms signal vKey,kBuf : std_vector(0 to 4); attributealtera_attribute of vKey : signal is "power_up_level=high";BeginProcess(clock) begin if rising_edge(clock)then1. RstIncDec(C1K,C1K=50e3-1, true);2. P1K <=b_nor(C1K);3. smp <=STDZ(C1K=40e3-1);4. IncDec(scan,P1K); end if; End process;With scan select ln_out<= "0111" when "00", "1011" when "01", "1101" when "10", "1110" when others;Process(clock) begin if rising_edge(clock)then5. LoadValue(kDn(0to 3), col_in, smp and scan=0);6. LoadValue(kDn(4to 7), col_in, smp and scan=1);7. LoadValue(kDn(8to 11), col_in, smp and scan=2);8. LoadValue(kDn(12to 15),col_in, smp and scan=3);9. k_rd <= P1Kand scan=3;10. kCode <=pri_encoder(not kDn);11. LoadValue(kBuf,kCode, k_rd);12. LoadValue(k_same,STDZ(kCode=kCode), k_rd);13. RstIncDec(cn_bounce,not k_same, k_rd);14. LoadValue(vKey,kBuf, b_and(cn_bounce&k_rd&k_same)); end if; End process;15. kPress <= not vKey(0);16. qKey <= vKey(1 to 4);End myFavor;行1:1ms计数器,用于定时每1ms扫描一行。行2:P1K为1KHz周期脉冲,010贴中提到用作使能下一行扫描,等效为1KHz时钟。行3:smp为扫描一行时采样列数据时刻。行4:scan扫描行计数,0到3循环。控制ln_out输出。行5~8:读取16个按键是否按下状态放入kDn。行9:k_rd指示4行扫描完毕,可以一次读取16键按下状态。k_rd周期是4ms。行10:pri_encoder(v)优先编码函数,返回从左到右v中第一个比特为1的位置,v全0时返回v的比特个数。由于kDn中比特为0表示按键按下,所以采用notkDn来判断第一个0的位置。所以kCode=16时表示无按键按下,kCode=0~15表示对应按键被按下。行11~14:对kCode值进行反跳处理,kCode持续128ms值保持不变则装载到vKey中。关于并行反跳处理已在012贴中论述。行15和16,最后输出。行15 中not vKey(0)取反目的是用1表示有键按下,更加符合常规思维习惯。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>