4X4键盘扫描实验
实验07:4X4键盘阵列扫描输入.pdf

键盘阵列扫描输入一、实验目的1. 进一步学习并掌握Quartus II设计的方法及步骤;2. 熟悉VHDL语言电路设计方法;3. 熟悉EACF型FPGA开发板,参见6.1节;4. 学习并掌握利用VHDL描述并设计电路的方法及步骤;5. 学习并掌握键盘阵列的扫描输入的方法及实现过程。
二、实验原理键盘阵列是一个由4×4的按键开关组成的阵列,可实现16种状态的输入。
4×4按键阵列的硬件连接原理如下图所示。
4X4键盘阵列其中VCC3.3为3.3V的正电源;BUTTON为4×4共16个按键,R为电阻。
而K_H_1、K_H_2、K_H_3、K_H_4为4×4按键阵列连接到FPGA通用IO引脚的行信号;K_V_1、K_V_2、K_V_3、K_V_4为4×4按键阵列连接到FPGA通用IO引脚的列信号,如下图所示。
键盘阵列与FPGA的连接另外,连接到FPGA的行列信号圴为3.3V的LVTTL电平标准:即电压小于0.8V为低电平,高于2.0V为高电平。
通过上述4×4按键阵列的硬件连接原理图可看出,行和列信号都通过10K的电阻上拉到3.3V的电源,也就是说如果FPGA通过对应的IO引脚来读取4×4按键阵列的行和列信号,得到的全部为高电平“1”,即使按键按下时,读到的依然是高电平“1”。
那么如何在FPGA中判断4×4按键阵列中的哪个键按下呢?当然我们要实现按键输入的功能,就不能全部读取行和列的信号。
而应通过不断地输出扫描行(或列),再通过读取列(或行)的信号来判断哪个按键按下。
即:通过对4×4键盘阵列的4个行(或列)控制信号循环输出”1110、1101、1011、0111”,来驱动键盘阵列,紧接着读取相应的4个列(或行)信号。
通过读取的数据或状态来判断16个按键中哪个键被按下,并对其状态做编码输出。
此电路不停的工作,以便实时准确地获取键盘的输入状态,以供其它电路使用,从而实现了键盘阵列的扫描输入。
4×4键盘扫描程序开启原理及实例(精心整理)

4×4键盘扫描程序开启原理及实例(精心整理)单片机4*4键盘扫描程序时如何开启的?按照行顺序,一行一行的开启,如下图:4*4共16键,假设P0.0-P0.3为H0-H3,P0.4-P0.7为L0-L3(列) L0 L1 L2 L3(行) H0 0 1 2 3H1 4 5 6 7H2 8 9 A BH3 C D E F首先让H0 = 0,然后依次检测L0-L3,看那个键按下了,则对应的L0-L3为0,这样第一行检测结束。
比如扫描H0行时第一个键按下了,则L0=0,获得的P0=0xee,你也可以返回一个值,比如就是0,来代表第一个键(0)被按下,这样依次检测就扫描满16个键就行了。
4*4键盘扫描程序#include //包含头文件#define uchar unsigned char#define uint unsigned intunsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};//0-Fuchar keyscan(void);void delay(uint i);void main(){uchar key;P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符while(1){key=keyscan();//调用键盘扫描,switch(key){case 0x7e:P0=dofly[0];break;//0 按下相应的键显示相对应的码值case 0x7d:P0=dofly[1];break;//1case 0x7b:P0=dofly[2];break;//2case 0x77:P0=dofly[3];break;//3case 0xbe:P0=dofly[4];break;//4case 0xbd:P0=dofly[5];break;//5case 0xbb:P0=dofly[6];break;//6case 0xb7:P0=dofly[7];break;//7case 0xde:P0=dofly[8];break;//8case 0xdd:P0=dofly[9];break;//9case 0xdb:P0=dofly[10];break;//acase 0xd7:P0=dofly[11];break;//bcase 0xee:P0=dofly[12];break;//ccase 0xed:P0=dofly[13];break;//dcase 0xeb:P0=dofly[14];break;//ecase 0xe7:P0=dofly[15];break;//f}}}uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法{uchar cord_h,cord_l;//行列值P3=0x0f; //行线输出全为0cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{delay(100); //去抖if(cord_h!=0x0f){cord_h=P3&0x0f; //读入列线值P3=cord_h|0xf0; //输出当前列线值cord_l=P3&0xf0; //读入行线值return(cord_h+cord_l);//键盘最后组合码值}}return(0xff); //返回该值}void delay(uint i)//延时函数{while(i--);}以下为详细解释:假设按下的是S1键进行如下检测(4*4键盘)先在P3口输出p3 00001111低四位行会有变化cord_h =00001111&00001110 =00001110if !=00001111延时0.1uscord_h=00001110&00001111=00001110if !=00001111P3再输出11111110P3 =00001110|11110000=11111110输出高四位cord_l=P3&0xf0 //此时P3口就是输入值01111110 而不是上面的11111110cord_l=01111110&11110000=01110000cord_h+cord_l=00001110+01110000=01111110=0x7e //此编码即为S1的编码#include //包含头文件#define uchar unsigned char#define uint unsigned intunsigned char const table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};//0-Fuchar keyscan(void);void delay(uint i);void main(){uchar key;P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符while(1){key=keyscan();//调用键盘扫描,switch(key){case 0x7e:P0=table[0];break;//0 按下相应的键显示相对应的码值case 0x7d:P0=table[1];break;//1case 0x7b:P0=table[2];break;//2case 0x77:P0=table[3];break;//3case 0xbe:P0=table[4];break;//4case 0xbd:P0=table[5];break;//5case 0xbb:P0=table[6];break;//6case 0xb7:P0=table[7];break;//7case 0xde:P0=table[8];break;//8case 0xdd:P0=table[9];break;//9case 0xdb:P0=table[10];break;//acase 0xd7:P0=table[11];break;//bcase 0xee:P0=table[12];break;//ccase 0xed:P0=table[13];break;//dcase 0xeb:P0=table[14];break;//ecase 0xe7:P0=table[15];break;//f}}}uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法{ uchar cord_h,cord_l;//行列值P3=0x0f; //行线输出全为0cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{delay(100); //去抖cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f){P3=cord_h|0xf0; //输出当前列线值cord_l=P3&0xf0; //读入行线值return(cord_h+cord_l);//键盘最后组合码值}}return(0xff); //返回该值}void delay(uint i)//延时函数{while(i--);}在P3口做的键盘你的去抖检测没有做好通过电平输入来引发中断,必须是由P3.2或P3.3引脚输入,这样才能触发中断。
实验四4×4键盘输入

实验四: 4 × 4键盘输入实验一、实验目的:1.学习非编码键盘的工作原理和键盘的扫描方式。
2.学习键盘的去抖方法和键盘应用程序的设计。
二、实验原理:键盘是单片机应用系统接受用户命令的重要方式。
单片机应用系统一般采用非编码键4*4矩阵盘,需要由软件根据键扫描得到的信息产生键值编码,以识别不同的键。
本板采用键盘,行信号分别为P1.0-P1.3 ,列信号分别为P1.4-P1.7 。
具体电路连接见下图对于键的识别一般采用逐行(列)扫描查询法,判断键盘有无键按下,由单片机I/O口向键盘送全扫描字,然后读入列线状态来判断。
程序及流程图:ORG 0000HAJMP MAINORG 0000HAJMP MAINORG 0030HMAIN:MOV P2,#0F7HMOV P1,#0F0HMOV R7,#100DJNZ R7,$MOV A,P1ANL A,#0F0HXRL A,#0F0HJZ MAINLCALL D10MSMOV A,#00HMOV R0,AMOV R1,AMOV R2,#0FEH SKEY0:MOV A,R2MOVP1,AMOVR7,#10DJNZ R7,$MOVA,P1ANLA,#0F0HXRLA,#0F0HJNZ LKEYINC R0MOVA,R2RL AMOVR2,AMOVA,R0CJNE A,#04H,SKEY0AJMP MAIN LKEY:JNB ACC,4,NEXT1MOVA,#00HMOVR1,AAJMP DKEYNEXT1:JNB ACC.5,NEXT2MOVA,#01HMOVR1,AAJMP DKEYNEXT2:JNB ACC.6,NEXT3MOVA,#02HMOVR1,AAJMP DKEYNEXT3:JNB ACC.7,MAINMOVA,#03HMOVR1,AAJMP DKEY DKEY:MOV A,R0MOVB,#04HMULABADDA,R1AJMP SQRSQR:MOVDPTR,#TABMOVC A,@A+DPTRMOVP0,AAJMP MAINTAB:DB0C0H,0F9H,0A4H,0B0H,99H, 92H, 82H, 0F8H DB 80H, 90H, 88H, 83H, 0C6H,0A1H,86H, 8EH D10MS:MOV R6,#10L1:MOV R5,#248DJNZ R5,$DJNZ R6,L1RETEND流程图:结束三、思考题:总结 FPGA是如何识别按键的?与单片机读取键值有何不同?答:FPGA的所有 I/O 控制块允许每个 I/O 引脚单独配置为输入口 , 不过这种配置是系统自动完成的。
键盘扫描程序实验报告

一、实验目的1. 理解键盘扫描的基本原理。
2. 掌握使用C语言进行键盘扫描程序设计。
3. 学习键盘矩阵扫描的编程方法。
4. 提高单片机应用系统的编程能力。
二、实验原理键盘扫描是指通过检测键盘矩阵的行列状态,判断按键是否被按下,并获取按键的值。
常见的键盘扫描方法有独立键盘扫描和矩阵键盘扫描。
独立键盘扫描是将每个按键连接到单片机的独立引脚上,通过读取引脚状态来判断按键是否被按下。
矩阵键盘扫描是将多个按键排列成矩阵形式,通过扫描行列线来判断按键是否被按下。
这种方法可以大大减少引脚数量,降低成本。
本实验采用矩阵键盘扫描方法,使用单片机的并行口进行行列扫描。
三、实验设备1. 单片机开发板(如51单片机开发板)2. 键盘(4x4矩阵键盘)3. 连接线4. 调试软件(如Keil)四、实验步骤1. 连接键盘和单片机:将键盘的行列线分别连接到单片机的并行口引脚上。
2. 编写键盘扫描程序:(1)初始化并行口:将并行口设置为输入模式。
(2)编写行列扫描函数:逐行扫描行列线,判断按键是否被按下。
(3)获取按键值:根据行列状态,确定按键值。
(4)主函数:调用行列扫描函数,读取按键值,并根据按键值执行相应的操作。
3. 调试程序:将程序下载到单片机,观察键盘扫描效果。
五、实验程序```c#include <reg51.h>#define ROW P2#define COL P3void delay(unsigned int ms) {unsigned int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 123; j++);}void scan_key() {unsigned char key_val = 0xFF;ROW = 0xFF; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值}void main() {while (1) {scan_key();if (key_val != 0xFF) {// 执行按键对应的操作}}}```六、实验结果与分析1. 实验结果:程序下载到单片机后,按键按下时,单片机能够正确读取按键值。
实验4 4×4键盘实验

实验程序流程框图
熄灭所有数码管 运用行扫描法发现按键并获得其扫描码 将扫描码转换为按键值显示码码表地址
ldr r0,= 0x20006000 ldr r1, =0xff str r1, [r0] ldr r0,=0x20007000 ldr r1,=0x0 str r1,[r0]
获取按键显示码并输出到数码管显示
; r2清零, r2用于加1计数至行号
;以r1内为1的位将r0内对应位清0 ;比较r0与r4的值 ;如果相等则跳转到LOOP4 ;r0左移一位 ;r2加1
;保存行号 ;r2清零, r2用于加1计数至列号
;r0左移r2位 ;r0与r3比较 ;相等则跳转到LOOP6 ;r2加1
;取seg7table的地址 ; 行号× 4 ;r4保存偏移地址 ;取键值的地址
实验目的
通过实验掌握行列式键盘工作原理及按键识别过 程。
掌握S3C2440处理器系统下行列式键盘识别程序 的设计思想及实现方法。
实验内容
一、验证实验
输入并调试实验教程提供的参考程序,实现当按下实验 箱小键盘时,在所有数码管上显示按键值。
二、设计实验
分别在小键盘键入自己学号后6位数字并在6位数码管上 顺序显示。
行列式键盘结构及工作原理
行列式键盘电路通常采用的按键识别方法有行列扫描 法和反转法。
行列反转法 (略)
行列扫描法 主要实现过程:
(1)输出 (写操作) 仅有一列为0的列数据, (2)输入 (读操作) 全部行数据,并判断4位行值是否全为1。 (3)如果4位行值全为1,则无键按下。
继续扫描:变换下一列为0,转移到 ( 1 ) 。 (4)如果4位行值不全为1,则有键按下。
LOOP2
ldr r3,=0x1
实验四4X4矩阵键盘实验

狀態S_2: 發出掃瞄column 1即col=4’b1101的狀態並讀回row值作比 較:
如果讀到row不等於f (4’b1111)就代表在column 1上的4個按鍵(3, 7, b, f)有其中一個被按下,於是跳至S_5做等待使用者放開按鍵的處 理。 如果讀到row等於f (4’b1111)就代表在column 1上的4個按鍵(3, 7, b, f)沒有被按下,於是跳至S_3做掃瞄column 2的按鍵。
按鍵掃瞄之狀態
狀態S_3: 發出掃瞄column 2即col=4’b1011的狀態並讀回
row值作比較:
如果讀到row不等於f (4’b1111)就代表在column 2上的4個按鍵(2, 6, a, e)有其中一個被按下,於是跳至S_5做等待使用者放開按 鍵的處理。 如果讀到row等於f (4’b1111)就代表在column 2上的4個按鍵(2, 6, a, e)沒有被按下,於是跳至S_4做掃瞄column 2的按鍵。 狀態S_4: 發出掃瞄column 3即col=4’b0111的狀態並讀回row值作比較: 如果讀到row不等於f (4’b1111)就代表在column 3上的4個按鍵(1, 5, g, d)有其中一個被按下,於是跳至S_5做等待使用者放開按 鍵的處理。 如果讀到row等於f (4’b1111)就代表在column 3上的4個按鍵(1, 5, g, d)沒有被按下,於是跳回至S_0,因此FSM跳回Idle state即掃 描完4個column 都沒有發現任何按鍵被按下。 狀態S_5: 等待使用者放開按鍵的狀態,如果使用者沒放開按鍵就一直停
實驗四 4X4矩陣鍵盤實驗
4X4矩陣鍵盤輸入並輸出至七段式顯示器
底板子4x4矩陣按鍵
数码管显示4×4键盘矩阵按键实验

5、4×4键盘矩阵按键实验一、实验目的及要求键盘实质上是一组按键开关的集合。
通常,键盘开关利用了机械触点的合、断作用。
键的闭合与否,反映在行线输出电压上就是呈高电平或低电平,如果高电平表示键断开,低电平则表示键闭合,反之也可。
通过对行线电平高低状态的检测,便可确认按键按下与否。
为了确保CPU对一次按键动作只确认一次按键有效,还必须消除抖动。
当按键较多时会占用更多的控制器端口,为减少对端口的占用,可以使用行列式键盘接口,本实验中采用的4×4键盘矩阵可以大大减少对单片机的端口占用,但识别按键的代码比独立按键的代码要复杂一些。
在识别按键时使用了不同的扫描程序代码,程序运行时LED灯组会显示相应按键的键值0~15的二进制数。
本实验中P2端口低4位连接是列线,高4位连接的是行线。
二、实验原理(图)三、实验设备(环境):1、电脑一台2、STC-ISP(V6.85I)烧写应用程序3、Keil应用程序四、实验内容(算法、程序、步骤和方法):#include<STC15F2K60S2.h> //此文件中定义了STC15系列的一些特殊功能寄存器#include"intrins.h"#define uint unsigned int#define uchar unsigned charuchar code dsy_code[]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0 F,0xff};uchar Pre_keyno=16,keyno=16;void delayMS(char x){uchar i;while(x--)for(i=0;i<120;i++) ;}void keys_scan(){uchar tmp;P2=0x0f;delayMS(5);tmp=P2^0x0f;switch(tmp){case 1:keyno=0;break;case 2:keyno=1;break;case 4:keyno=2;break;case 8:keyno=3;break;default:keyno=16;}P2=0xf0;delayMS(5);tmp=P2>>4^0x0f;switch(tmp){case 1:keyno+=0;break;case 2:keyno+=4;break;case 4:keyno+=8;break;case 8:keyno+=12;break;}}main(){P0=0x00;while(1){P2=0xf0;if(P2!=0xf0)keys_scan();if(Pre_keyno!=keyno){P0=~dsy_code[keyno];Pre_keyno=keyno;}delayMS(50);}}五、实验结论(结果):本实验实现了XXX功能,核心算法采用了XXX的方式,达到了预期目的。
实验四 4x4键盘输入

实验报告四实验名称:4*4键盘输入1、实验内容键盘扫描,求键值,并在LED上显示该键值。
2、实验目的(1) 掌握键盘和显示器的接口方法和编程方法。
(2) 掌握键盘扫描和LED八段码显示器的工作原理。
3、实验要求在上一个实验的基础上,利用实验仪提供的键盘扫描电路和显示电路,做一个扫描键盘和数码显示实验,把按键输入的键码在六位数码管上显示出来。
实验程序可分为三个模块。
1)键输入模块:扫描键盘、读取一次键盘并将键值存入键值缓冲单元。
2)显示模块:将显示单元的内容在显示器上动态显示。
3)主程序:调用键输入模块和显示模块。
4、实验器材(1) 计算机1台5、实验电路这里只是键盘草图,列为输出,行为输入。
图中电阻为上拉电阻。
(0e103H)图6 8155键盘电路原理图表2 键值表6、实验说明本实验仪提供了一个6×4的小键盘,向列扫描码地址(0e101H)逐列输出低电平,然后从行码地址(0e103H)读回。
如果有键按下,则相应行的值应为低,如果无键按下,由于上拉的作用,行码为高。
这样就可以通过输出的列码和读取的行码来判断按下的是什么键。
在判断有键按下后,要有一定的时延,进行第二读键盘,防止键盘抖动。
7、实验流程图注:LED显示程序框图见上个实验。
图7 键盘扫描主程序流程图图8 读键输入子程序流程图8、实验程序清单;****变量定义文件,文件名:para.lib****OUTBIT equ 0e101h ; 位控制口CLK164 equ OUTBIT+1 ; 段控制口(接164时钟位)DAT164 equ OUTBIT+1 ; 段控制口(接164数据位)IN equ OUTBIT+2 ; 键盘读入口LEDBuf equ 60h ; 显示缓冲; ***变量定义文件结束***;*****************************************************;****显示部分做成单独的文件,文件名为:dis.lib,在键盘扫描部分调用**** LEDMAP: ; 八段管显示码db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07hdb 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71hdb 00H;******* 延时子程序**************Delay: ; 延时子程序mov r7, #0DelayLoop:djnz r7, DelayLoopdjnz r6, DelayLoopret;*********LED显示***************DisplayLED:mov r0, #LEDBufmov r1, #6 ; 共6个八段管mov r2, #00100000b ; 从左边开始显示Loop: mov dptr, #OUTBITmov a, #0movx @dptr, a ; 关所有八段管mov a, @r0mov B, #8 ; 送164DLP: rlc amov r3, amov acc.0, cmov dptr, #DAT164anl a,#0fdh ;PB1=0,即时钟低电平movx @dptr, amov dptr, #CLK164orl a,#02h ;PB1=1,即产生时钟高电平movx @dptr, aanl a,#0fdh ;PB1=0,时钟低电平movx @dptr, amov a, r3djnz B, DLPmov dptr, #OUTBITmov a, r2movx @dptr, a ; 显示一位八段管mov r6, #1call Delaymov a, r2 ; 显示下一位rr amov r2, ainc r0djnz r1, Loopret;******八段管显示码程序文件dis.lib结束****;***************************************************** ;******键盘扫描程序文件,文件名:key.lib***** TestKey:mov dptr, #OUTBITmov a, #0movx @dptr, a ; 输出线置为0mov dptr, #INmovx a, @dptr ; 读入键状态cpl aanl a, #0fh ; 高四位不用ret;*******键值表**************KeyTable: ; 键码定义db 00h, 01h, 04h, 07hdb 0fh, 02h, 05h, 08hdb 0eh, 03h, 06h, 09hdb 0dh, 0ch, 0bh, 0ahdb 10H,11H,12H,13Hdb 14H,15H,16H,17H;********************************GetKey:mov dptr, #OUTBITmov P2, dphmov r0, #Low(IN)mov r1, #00100000b ;列扫描初值mov r2, #6 ;扫描6列Kloop:mov a, r1 ; 找出键所在列cpl amovx @dptr, acpl arr amov r1, a ; 下一列movx a, @r0 ;读行值cpl aanl a, #0fhjnz Goon1 ; 该列有键入djnz r2,Kloopmov r2,#0ffh ; 没有键按下, 返回 0ffhsjmp ExitGoon1:mov r1,a ; R1中为行值,键序号 = (列-1)* 4 + 行mov a,r2 ;R2中为列值dec arl arl amov r2,a ; r2 = (r2-1)*4mov a,r1 ; r1中为读入的行值mov r1,#4 ;共有4行LoopC:rrc a ; 移位找出所在行jc Exitinc r2 ; r2 = r2+ 行值djnz r1,LoopCExit: mov a,r2 ; 查表取出键值码mov dptr,#KeyTablemovc a, @a+dptrmov r2,aWaitRelease:mov dptr,#OUTBIT ; 等键释放clr amovx @dptr,amov r6,#10call Delaycall TestKeyjnz WaitReleasemov a,r2ret;****键盘程序文件key.lib结束****;************************;*******以下为另一文件:主程序***********$include (para.lib)ORG 0Ljmp StartStart:mov sp, #40hmov dptr,#0e100hmov a,#03hmovx @dptr,amov LEDBuf,#0ffh ; 显示 8.8.8.8.mov LEDBuf+1,#0ffhmov LEDBuf+2,#0ffhmov LEDBuf+3,#0ffhmov LEDBuf+4,#0mov LEDBuf+5,#0Mloop:call DisplayLED ; 显示call TestKey ; 有键入?Jz Mloop ; 无键入, 继续显示call GetKey ; 读入键码mov r2,aanl a, #0fh ; 显示键码低位mov dptr, #LEDMapmovc a, @a+dptrmov LEDBuf+5,amov a,r2swap aanl a, #0fh ; 显示键码高位mov dptr, #LEDMapmovc a, @a+dptrmov LEDBuf+4, aljmp Mloop$include (dis.lib)$include (key.lib)END9、实验步骤1) 编写程序。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
44
键盘扫描实验
实验目的
1、学习HDL程序的基本设计技巧;
2、掌握矩阵键盘的扫描原理和使用方法。
Verilog程序:
module hex_keypad(Col,Code,show,show1,count,scan,clock,Row); output[3:0] Code,Col,count; //定义列信号Col、行列信号共同决定的
输出代码Code、以及计数变量count output[7:0] show,show1; //定义七段显示变量show、show1 input[3:0] Row; //定义输入行信号Row
input scan; //定义数码管选择信号scan
input clock; //定义时钟信号clock
reg[3:0] Col,Code,count; //将输出信号定义为reg型
reg[7:0] show,show1;
reg[1:0] cn; //定义reg型变量cn,用于计数
reg reset,count_up,count_down; //定义变量reset用于计数清零,count_up
开始加计数,count_down开始减计数reg[15:0] times1,times2; //定义变量times1、times2用于决定开
始计数的时间
assign scan=1'b1; //将数码管选择信号赋值为1
always@(posedge clock) //产生列信号
if(cn==4)cn<=0; else
cn<=cn+1;
always@(cn)
case(cn)
2'b00:Col=4'b1110;
2'b01:Col=4'b1101;
2'b10:Col=4'b1011;
2'b11:Col=4'b0111;
endcase
always@(posedge clock) //行列信号共同决定输出代码Code case({Row,Col})
8'b1110_1110:Code=4'h0;
8'b1110_1101:Code=4'h1;
8'b1110_1011:Code=4'h2;
8'b1110_0111:Code=4'h3;
8'b1101_1110:Code=4'h4;
8'b1101_1101:Code=4'h5;
8'b1101_1011:Code=4'h6;
8'b1101_0111:Code=4'h7;
8'b1011_1110:Code=4'h8;
8'b1011_1101:Code=4'h9;
8'b1011_1011:Code=4'hA;
8'b1011_0111:Code=4'hB;
8'b0111_1110:Code=4'hC;
8'b0111_1101:Code=4'hD;
8'b0111_1011:Code=4'hE;
8'b0111_0111:Code=4'hF;
endcase
always@(posedge clock) //由输出Code决定数码管的显示,七段
用十六进制数表示
case(Code[3:0])
4'h0:show=8'hFC;
4'h1:show=8'h60;
4'h2:show=8'hDA;
4'h3:show=8'hF2;
4'h4:show=8'h66;
4'h5:show=8'hB6;
4'h6:show=8'h3E;
4'h7:show=8'hE0;
4'h8:show=8'hFE;
4'h9:show=8'hE6;
4'hA:show=8'hEE;
4'hB:show=8'hCE;
4'hC:show=8'h9C;
4'hD:show=8'h7A;
4'hE:show=8'h9E;
4'hF:show=8'h8E;
endcase
always@(posedge clock) //加减计数
case(Code)
4'h0:begin reset=1;count_up=0;count_down=0;end //按0键时清零4'hE:begin count_up=1;count_down=0;end //按E键加计数4'hF:begin count_down=1;count_up=0;end //按F键减计数default: begin count_down=0;count_up=0;reset=0; end //按其它键不计数endcase
always@(posedge clock)
if(times1==1000) times1<=101; else if (count_up) times1<=times1+1;
always@(posedge clock)
if(times2==1000) times2<=101; else if (count_down) times2<=times2+1; always@(posedge clock)
if(reset)count<=4'h0; else
if (times1>100&&Code==4'hE) //加计数
begin
count<=count+4'b1;
if (count==4'h9) count<=4'h0;
end
else
if (times2>100&&Code==4'hF) //减计数
begin
count<=count-4'b1;
if (count==4'h0) count<=4'h9;
end
always@(posedge clock) //计数显示
case(count[3:0])
4'h0:show1=8'hFC;
4'h1:show1=8'h60;
4'h2:show1=8'hDA;
4'h3:show1=8'hF2;
4'h4:show1=8'h66;
4'h5:show1=8'hB6;
4'h6:show1=8'h3E;
4'h7:show1=8'hE0;
4'h8:show1=8'hFE;
4'h9:show1=8'hE6;
endcase
endmodule
仿真波形:
Col、Row、Code、show、show[17..10]为十六进制显示,times1、times2、count为十进制显示
当Code为F(即按F键)时,show显示8E即F,表明此时按下的是F 键。
times2大于100时,count开始减计数。
当Code为E(即按E键),且times1大于100时开始加计数。
按其它键时保持,不计数。
按0键时清零。
对设计的分析:
在时钟控制下循环给出键盘扫描信号,根据列扫描信号和对应键盘响应信号确定键盘按键位置,直接对数码管给出相应的显示编码。
列扫描信号由变量cn控制,cn受时钟脉冲clock上升沿控制。
从00->01->10->11->00循环计数。
cn的四种状态决定了列扫描信号的四种状态: 1110->1101->1011->0111。
对应行信号的四种状态:1110->1101->1011->0111。
共同决定了Code的十六种状态,对应键盘上的十六个键,控制七段数码管的显示。
加减计数由变量由count_up和count_down控制。
变量count_up和count_down由键盘上的E键和F键控制。
长按E键或F键将开始计数。
开始计数后,按0键可以清零,按其它键可以使计数保持。
重按E键或F键开始加减计数。