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) 编写程序。
4X4键盘扫描实验
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; //定义输入行信号Rowinput scan; //定义数码管选择信号scaninput clock; //定义时钟信号clockreg[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; //将数码管选择信号赋值为1always@(posedge clock) //产生列信号if(cn==4)cn<=0; elsecn<=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;endcasealways@(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;endcasealways@(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;endcasealways@(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 //按其它键不计数endcasealways@(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; elseif (times1>100&&Code==4'hE) //加计数begincount<=count+4'b1;if (count==4'h9) count<=4'h0;endelseif (times2>100&&Code==4'hF) //减计数begincount<=count-4'b1;if (count==4'h0) count<=4'h9;endalways@(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;endcaseendmodule仿真波形:Col、Row、Code、show、show[17..10]为十六进制显示,times1、times2、count为十进制显示当Code为F(即按F键)时,show显示8E即F,表明此时按下的是F 键。
4×4矩阵键盘识别技术
实验课题:4×4矩阵键盘识别技术一实验目的1.熟悉和掌握AT89S51单片机相关的功能2.了解矩阵式键盘的内部结构,掌握至少一种常用的按键识别的方法3.利用AT89S51单片机和设计一个4×4矩阵键盘控制。
4.掌握子程序结构和子程序实际的基本知识。
二实验原理1. 4×4矩阵键盘的序列排列如图1-1,图1-12.如图1-2所示,用AT89S51的并行口P1接4×4矩阵键盘,以P1.0―P1.3作输入线,以p1.4-P1.7作输出线,在数码管上显示每个按键的“0-F”序号.每个按键有它的行值和列值,行值和列值的组合就是识别这个按键的编码。
矩阵的行线和列线分别通过两并行接口和CPU通信。
每个按键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。
键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。
两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。
3.程序框图三实验原理图四实验代码#include<AT89X51.H> unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsignedchartemp;unsignedcharkey;unsignedchari,j;voidmain(void){while(1){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f) {temp=P3;temp=temp&0x0f;switch(temp){case0x0e:key=7;break;case0x0d:key=8;break;case0x0b:key=9;break;case0x07:key=10;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3; temp=temp&0x0f; switch(temp){case0x0e:key=4;break;case0x0d:key=5;break;case0x0b:key=6;break;case0x07:key=11;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_6=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f; if(temp!=0x0f) {temp=P3;temp=temp&0x0f; switch(temp){ case0x0e:key=1;break;case0x0d:key=2;break;case0x0b:key=3;break;case0x07:key=12;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f; }}}P3=0xff;P3_7=0;temp=P3;temp=temp&0x0f; if(temp!=0x0f) {for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case0x0e:key=0;break; case0x0d:key=13;break;case0x0b:key=14;break;case0x07:key=15;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}}}五实验小结1.通过本次试验熟练的掌握了AT89S51单片机相关的功能。
数字系统设计大作业--4×4阵列键盘键信号检测电路设计
2014 ~ 2015学年第1 学期《数字系统设计》大作业题目:4×4阵列键盘键信号检测电路设计专业:电子信息工程班级:姓名:指导教师:电气工程学院2015 年12月摘要人类文明已进入到高度发达的信息化社会。
信息化社会的发展离不开电子信息产品开发技术、产品品质的提高和进步。
电子信息产品随着科学技术的进步,其电子器件和设计方法更新换代的速度日新月异。
实现这种进步的主要原因就是电子设计技术和电子制造技术的发展,其核心就是电子设计自动化(EDA,Electronic Design Automation)技术,EDA技术的发展和推广应用又极大地推动了电子信息产业的发展。
为保证电子系统设计的速度和质量,适应“第一时间推出产品”的设计要求,EDA技术正逐渐成为不可缺少的一项先进技术和重要工具。
目前,在国内电子技术教学和产业界的技术推广中已形成“EDA热”,完全可以说,掌握EDA技术是电子信息类专业学生、工程技术人员所必备的基本能力和技能。
本设计主要利用VHDL硬件描述语言在EDA平台xilinx.ise.7.1i上设计一个4×4阵列键盘扫描电路,将行扫描信号输入阵列键盘,读取列信号的值,输出按键编码,从而判断出按键按下的位置。
并且使用Modelsim软件进行模拟仿真,下载到EDA实验箱进行硬件验证。
关键词:EDA VHDL语言 4×4阵列键盘扫描目录《数字系统设计》 (1)数字系统设计.............................................................................. 错误!未定义书签。
摘要 (2)关键词:EDA VHDL语言 4×4阵列键盘扫描 (2)1、实验目的 (4)2、实验要求 (4)3、实验原理 (4)4、总体框图 (5)4.1.1方案一 (5)4.1.2方案二 (5)4.2设计思路 (6)5、功能模块介绍 (8)5.1键盘消抖模块 (8)5.2键盘模块 (8)5.3VHDL部分程序 (8)6、实验结果 (10)6.1综合电路图 (10)6.2时序仿真 (11)1、实验目的(1)通过常见基本组合逻辑电路的设计,熟悉EDA设计流程;(2)熟悉文本输入及仿真步骤;(3)掌握VHDL设计实体的基本结构及文字规则;(4)理解硬件描述语言和具体电路的映射关系;(5)用VHDL设计一个能识别4×4阵列键盘的实用电路。
4x4键盘
4x4键盘输入实验一、实验目的1.掌握4×4矩阵式键盘程序识别原理。
2.掌握4×4矩阵式键盘按键的设计方法。
二、实验原理:主要原理为扫描键盘矩阵时,每次只有一行电平拉低。
在逐次扫描拉低的这些行的同时,去读那些列的电平。
;被拉低的行上,按下的键对应的列的电平为0 ,其它为1. 用左移位的指令,在进位位CY里就可以检测出是0还是1.为1表示无按下,;为0表示该键按下。
在扫描按键时,如无按下,则取码指针R1加1后,继续扫描。
如有键按下,转按键处理子程序,按键按下标志位;F0清0(表示按下)。
此时,取码指针的值,就是按键的键名。
随后继续进入按键检测子程序重新扫描。
每个按键有它的行值和列值,行值和列值的组合就是识别这个按键的编码。
矩阵的行线和列线分别通过两并行接口和CPU通信。
每个按键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。
键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。
两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。
键盘连接成4×4的矩阵形式,占用单片机P1口的8根线,行信号是P1.0-1.3,列信号是P1.4-1.7。
三、实验内容及过程:1、流程图2、实验中碰到的问题编写程序时需要用到的共阳字形码,不能与共阴字形码混淆。
在仿真过程中,数码管下拉电阻起到分流作用,应该接地,但是却始终不能出结果,将下拉电阻与电源相连就可以显示正确了。
四、实验现象:按下一个键,在数码管上就会显示对应的数字或者字母。
五、程序:ORG 0000HAJMP MAINORG 0030H MAIN: MOV DPTR,#TABLCALL KEYMOVC A,@A+DPTRMOV P1,ALJMP MAIN KEY: LCALL KSJNZ K1LCALL DELAYAJMP KEYK1: LCALL DELAYLCALL KSJNZ K2AJMP KEYK2: MOV R2,#0EFHMOV R4,#0000HK3: MOV P1,R2L6: JB P2.0,L1MOV A,#0000HAJMP LKL1: JB P2.1,L2MOV A,#04HAJMP LKL2: JB P2.2,L3MOV A,#08HAJMP LKL3: JB P2.3,NEXTMOV A,#0CH LK: ADD A,R4PUSH ACCK4: LCALL DELAYLCALL K4POP ACCRETNEXT: INC R4MOV A,R2JNB ACC.7,KEYRL AMOV R2,AAJMP K3KS: MOV P2,#0FHMOV A,P2XRL A,#0FHRETDELAY:MOV R6,#0FEHLOOP1:MOV R7,#0FEHLOOP2:DJNZ R7,LOOP2DJNZ R6,LOOP1RETTAB: DB 0C0HDB 0F9HDB 0A4HDB 0B0HDB 99HDB 92HDB 82HDB 0F8HDB 80HDB 90HDB 088HDB 083HDB 0C6HDB 0A1HDB 086HDB 08EHEND六、实验心得通过本实验,懂得如何安装kell软件以及实验仿真板,懂得KEIL C51单片机仿真软件的调试,掌握了单片机矩阵键盘的基本知识。
4×4键盘扫描时序逻辑电路的VHDL模型实验
汕头大学实验报告实验三4×4键盘扫描时序逻辑电路的VHDL模型实验一、实验目的1、了解普通4×4键盘扫描的原理。
2、掌握组合逻辑电路和时序逻辑电路的混和设计。
3、进一步加深七段码管显示过程的理解。
二、硬件要求1、4×4键盘阵列。
2、FPGA主芯片。
3、可变时钟源。
4、七段码显示区。
5、LED显示模块。
三、实验原理本实验主要完成的实验是完成4×4键盘扫描的,然后获取其键值,并对其进行编码,从而进行按键的识别,并将相应的按键值进行显示。
键盘扫描的实现过程如下:对于4×4键盘,通常连接为4行、4列,因此要识别按键,只需要知道是哪一行和哪一列即可,为了完成这一识别过程,我们的思想是,首先固定输出4行为高电平,然后输出4列为低电平,在读入输出的4行的值,通常高电平会被低电平拉低,如果读入的4行均为高电平,那么肯定没有按键按下,否则,如果读入的4行有一位为低电平,那么对应的该行肯定有一个按键按下,这样便可以获取到按键的行值。
同理,获取列值也是如此,先输出4列为高电平,然后在输出4行为低电平,再读入列值,如果其中有哪一位为低电平,那么肯定对应的那一列有按键按下。
获取到行值和列值以后,组合成一个8位的数据,根据实现不同的编码在对每个按键进行匹配,找到键值后在7段码管和LED显示。
四、实验内容及步骤本实验内容是完成4×4键盘的扫描,然后将正确的键值进行显示,实验步骤如下:1、编写键盘扫描和显示的VHDL代码。
2、用MaxPlusII对其进行编译仿真。
3、在仿真确定无误后,选择芯片ACEX1K EP1K30QC208。
4、给芯片进行管脚绑定,在此进行编译。
5、根据自己绑定的管脚,在实验箱上对键盘接口、显示接口和FPGA之间进行正确连线。
6、给目标板下载代码,在4×4键盘输入键值,观看实验结果。
五、VHDL程序设计代码及结果1、4×4键盘扫描源程序LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY Vhdl1 ISPORT(CLK_1K : IN STD_LOGIC; --时钟输入1KHZCLK_40K : IN STD_LOGIC; --40K TimeClkKEY_LIE : IN STD_LOGIC_VECTOR(3 DOWNTO 0);-- 列输入START :OUT STD_LOGIC; --二-十进制数据输出标志KEY_HANG :OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --行输出DA TA_P : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--二-十进制数输出DISP_DA TA : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);--数码管显示译码输出DISP_SEL : OUT STD_LOGIC_VECTOR(1 downto 0));--数码管显示扫描输出END ;ARCHITECTURE RTL OF Vhdl1 ISSIGNAL INT : STD_LOGIC; --列与非信号SIGNAL CLK_SEL : STD_LOGIC;--键值控制1khz的时钟信号SIGNAL START_REG:STD_LOGIC; --数据输出标志信号SIGNAL DISP_SEL_REG:STD_LOGIC_VECTOR(1 DOWNTO 0);--数码管显示扫描信号SIGNAL DATA_L,DATA_H:STD_LOGIC_VECTOR(3 DOWNTO 0);--二-十进制低位、高位信号SIGNAL DATA_TMP:STD_LOGIC_VECTOR(3 DOWNTO 0);--二-十进制低位高位暂存信号SIGNAL KEY_HANG_TMP:STD_LOGIC_VECTOR(3 DOWNTO 0);--行输出信号SIGNAL DISP_DA TA_REG:STD_LOGIC_VECTOR(3 DOWNTO 0); --二-十进制低位、高位暂存信号(数码管用)SIGNAL KEY_CODE:STD_LOGIC_VECTOR(7 DOWNTO 0);--行列相并信号SIGNAL DATA_P_REG:STD_LOGIC_VECTOR(7 DOWNTO 0); --二-十进制数信号-------------------------------------------------------------------------------BEGINKEY_CODE<=KEY_HANG_TMP&KEY_LIE;--行、列相并DATA_P<=DATA_P_REG;START<= START_REG;KEY_HANG<=KEY_HANG_TMP;DISP_SEL<=DISP_SEL_REG;CLK_SEL<=CLK_1K AND ( NOT INT);--无键按下时有CLK-SEL时钟信号输出--------------------------------------------------PROCESS (CLK_SEL,CLK_40K , INT)V ARIABLE STA TE : INTEGER RANGE 0 TO 3 ;BEGINIF RISING_EDGE(CLK_40K) THEN --一个40K的脉冲上升沿到来输入一次列状态以判断是否有按键按下INT<= NOT (KEY_LIE(3) AND KEY_LIE(2) AND KEY_LIE(1) AND KEY_LIE(0));END IF;IF RISING_EDGE(CLK_SEL) THEN --一个1K的脉冲的上升沿到来输出一个带表行的状态CASE STATE IS--变量表示状态机,4循环WHEN 0=>KEY_HANG_TMP<="1110";STA TE :=1;WHEN 1 =>KEY_HANG_TMP<="1101";STATE :=2 ;WHEN 2 =>KEY_HANG_TMP<="1011";STATE :=3;WHEN 3 =>KEY_HANG_TMP<="0111";STATE :=0;END CASE;END IF;END PROCESS;PROCESS (CLK_40K , INT)--进程是并行的V ARIABLE STA TE :INTEGER RANGE 0 TO 3;V ARIABLE COUNTER : INTEGER RANGE 0 TO 31;BEGINIF INT='0' THENSTATE:=0;COUNTER:=0;ELSIF RISING_EDGE(CLK_40K) THENCASE STATE ISWHEN 0 =>DATA_TMP <= DATA_L;--低四位放入暂存信号内STATE:=1;WHEN 1 =>--再嵌套一个CASE语句CASE KEY_CODE IS--实现把像并数据译码十六进制的1到FWHEN "01110111" =>DA TA_L <="0001";--把1放入低四位DA TA_H <=DA TA_TMP;--把暂存信号的内容放入高四位,相相当于向左移位STA TE:=2;--跳出内嵌套CASE语句,转向外CASE语句的状态2 WHEN "01111011" =>DA TA_L <="0010";DA TA_H <=DATA_TMP;STATE:=2;WHEN "01111101" =>DA TA_L <="0011";DA TA_H <=DATA_TMP;STATE:=2;WHEN "01111110" =>DA TA_L <="0100";DA TA_H <=DATA_TMP;STATE:=2;WHEN "10110111" =>DA TA_L <="0101";DA TA_H <=DATA_TMP;STATE:=2;WHEN "10111011" =>DA TA_L <="0110";DA TA_H <=DATA_TMP;STATE:=2;WHEN "10111101" =>DA TA_L <="0111";DA TA_H <=DATA_TMP;STATE:=2;WHEN "10111110" =>DA TA_L <="1000";DA TA_H <=DATA_TMP;STATE:=2;WHEN "11010111" =>--9键DA TA_L <="1001";DA TA_H <=DATA_TMP;STATE:=2;WHEN "11011011" =>--0键DA TA_L <="0000";DA TA_H <=DATA_TMP;STATE:=2;WHEN "11011101" =>--A键,实现步进加一功能IF DA TA_H ="1001" THENIF DA TA_L="1001" THENDATA_H<="1001";DATA_L<="1001";ELSE DA TA_L<=DATA_L + 1;END IF;ELSIF DA TA_L="1001" THENDATA_L<="0000";DATA_H<=DATA_H+1;ELSEDATA_L<=DATA_L+1;DATA_H<=DATA_H;END IF;STATE:=2;WHEN "11011110" =>--B键,实现步键加十IF DA TA_H="1001" THENDA TA_H<="1001";ELSEDATA_L<=DATA_L;DATA_H<= DATA_H+1;END IF;STATE:=2;WHEN "11100111" =>--C键,实现步进减一IF DA TA_L="0000" AND DATA_H="0000" THENDATA_L<="0000";DATA_H<="0000";ELSIF DA TA_L="0000" THENDA TA_L<="1001";DA TA_H<= DATA_H-1;ELSEDATA_L <=DATA_L-1;DATA_H<=DATA_H;END IF;STA TE:=2;WHEN "11101011"=>--D键,实现步进减十IF DA TA_H="0000" THENDA TA_H<="0000";ELSEDATA_L<=DATA_L;DATA_H<=DATA_H-1;END IF;STATE:=2;WHEN "11101110" =>--E键,实现送数功能DA TA_L<=DATA_L;DA TA_H<=DATA_H;DATA_P_REG<=DATA_H&DATA_L;START_REG<='1';--数据输出标志信号置一STATE:=2;WHEN"11101101" =>--F键,实现清零功能DA TA_L<="0000";DA TA_H<="0000";STATE:=2;WHEN OTHERS =>--不可缺少STATE:=2;END CASE;WHEN 2 =>--状态2实现去抖动功能IF COUNTER=31 THEN --计数延时去抖COUNTER:=0;STA TE:=3;ELSECOUNTER:=COUNTER+1;STATE:=2;END IF;WHEN 3 =>-- 清除数据输出标志START_REG<='0';STA TE:=3;END CASE;END IF;END PROCESS;PROCESS (CLK_1K,DA TA_L,DATA_H)--数码管循环显示V ARIABLE STA TE: INTEGER RANGE 0 TO 1;BEGINIF RISING_EDGE(CLK_1K) THENCASE STATE ISWHEN 0 =>DISP_SEL_REG<="10";-- 输入10到数码管显示扫描信号DISP_DA TA_REG<=DATA_L;--二-十进制低高位暂存节点STATE:=1;WHEN 1 =>DISP_SEL_REG<="01";DISP_DA TA_REG<=DATA_H;STATE:=0;END CASE;END IF;END PROCESS;PROCESS(CLK_1K,DISP_DA TA_REG)--数码管译码BEGINIF RISING_EDGE(CLK_1K) THENCASE DISP_DA TA_REG ISWHEN "0000"=>DISP_DA TA<="1111110";--0WHEN "0001"=>DISP_DA TA<="0110000";--1WHEN "0010"=>DISP_DA TA<="1101101";WHEN "0011"=>DISP_DA TA<="1111001";WHEN "0100"=>DISP_DA TA<="0110011";WHEN "0101"=>DISP_DA TA<="1011011";WHEN "0110"=>DISP_DA TA<="1011111";WHEN "0111"=>DISP_DA TA<="1110000";WHEN "1000"=>DISP_DA TA<="1111111";WHEN "1001"=>DISP_DA TA<="1111011";WHEN OTHERS =>DISP_DA TA<="0000000";END CASE;END IF;END PROCESS;END;2、实验现象(1)38译码器六、思考题1、总结FPGA是如何识别按键的?与单片机读取键值有何不同?答:FPGA的所有I/O控制块允许每个I/O引脚单独配置为输入口,不过这种配置是系统自动完成的。
4x4矩阵键盘扫描原理
4x4矩阵键盘扫描原理
4x4矩阵键盘扫描原理是一种常用的键盘扫描方法,也称为矩阵键盘扫描。
它可以将多个按键连接在一起并使用较少的引脚来检测按键的状态。
4x4矩阵键盘由4行和4列组成,共有16个按键。
通常使用单片机或电路来进行扫描,以下是简要的原理:
1. 行扫描:首先,将行引脚设置为输出,同时将列引脚设置为输入,并将其上拉或下拉。
所有行引脚中只有一个为低电平,其余为高电平。
然后逐行检测按键状态。
2. 列检测:对于每一行,将对应的行引脚置为低电平后,检测列引脚的电平状态。
如果有按键按下,则相应的列引脚会变为低电平。
通过读取列引脚的状态,可以确定按键的位置。
3. 组合键:由于只能一次检测一行,因此当同时按下多个按键时,可能会导致误检。
为了解决这个问题,可以在检测到按键按下时,延迟一段时间,并再次检测按键的状态。
如果在第二次检测时仍然检测到按键按下,则确认按键有效。
4. 反向扫描:为了检测按键的释放状态,可以将行引脚设置为输入,列引脚设置为输出,并将其置为低电平。
然后逐列检测行引脚的电平状态,如果有按键释放,则相应的行引脚会变为高电平。
通过不断地循环扫描所有的行和列,可以实时检测按键的状态,并根据需要进行相应的处理。
矩阵键盘实验报告
自主学习用实验矩阵键盘识别实验
一、实验目的
1、掌握 4×4 矩阵键盘的工作原理和键盘的扫描方式。
2、掌握键盘的去抖方法和键盘应用程序的设计。
二、实验设备
1、PC 机一台;
2、开放式模块化单片机教学实验箱一台;
3、USB 下载线一根。
三、实验内容
自行编制程序,用 51 单片机实现 4×4 矩阵键盘扫描,采用线反转法;并实现当S11按下时在数码管上显值“0”,当S12按下时在数码管上显值“1”……,即依次将 S11 至S26按下,在数码管上依次显示十六进制数“0-F”,矩阵键盘原理图如图1-1 所示。
单片机与数码管接口电路原理图如图 1-2 所示。
图 1-1 矩阵键盘接口电路
图 1-2 数码管接口电路原理图
四、思考题
1.画出所编程序的流程图;
2.若要实现2×4 矩阵键盘,软硬件作如何修改。
答:将行线P2^3, P2^4接线去掉。
程序对应部分P2=0xfd; P2=0xfe;删掉。
3.实验中有何故障、问题出现,是否得到解决?如何解决的?问题:显示值对应出错。
原来是共阳段码和共阴段码弄相反了。
实验三 键盘扫描控制
实验三4*4键盘扫描显示控制一、实验目的实现一4×4键盘的接口,并在两个数码管上显示键盘所在的行与列。
即将8255单元与键盘及数码管显示单元连接,编写实验程序扫描键盘输入,并将扫描结果送数码显示,键盘采用4×4键盘,每个数码管值可以为0到F,16个数。
将键盘进行编号记作0—F当按下其中一个按键时将该按键对应的编号在一个数码管上显示出来,当按下下一个按键时便将这个按键的编号在下一个数码管上显示出来,且数码管上可以显示最近6次按下按键的编号。
二、实验要求1、接口电路设计:根据所选题目和所用的接口电路芯片设计出完整的接口电路,并进行电路连接和调试。
2、程序设计:要求画出程序框图,设计出全部程序并给出程序设计说明。
三、实验电路四、实验原理说明图2 数码管引脚图图1为AT89C51引脚图,说明如下:VCC:供电电压。
GND:接地。
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH 编程和校验时,P1口作为第八位地址接收。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
实验四、键盘扫描与数码管显示
特点:编码过程简单,编码复杂且不连续,不便处理
0、1、2、3 → 列号
0、4、8、C → 行首码
按键编码 = 列号+行首码
特点:编码过程复杂,编码简单且连续,便于处理
二进制组合编码键位识别:
(1)检测是否有键按下 ① 行线送全扫描字(P1=F0H),让P1.0~P1.3都为低电平; ② 读列线状态(P1?=F0H),若P1.4~P1.7全为高电平,则无键按下,反之则有键按下。
(2)确认键位
① 行线送全扫描字(P1=F0H),读出列线值;
② 列线送全扫描字(P1=0FH),读出行线值; ③ 行列值组合确认键位。
二进制组合编码 共阳极字段码 显示数字 二进制组合编码 共阳极字段码 显示数字
EEH DEH BEH 7EH EDH DDH BDH 7DH C0H F9H A4H B0H 99H 0 1 2 3 4 92H 82H 5 6 F8H 7 77H 8EH F
(2)键盘原理与按键消抖
前沿抖动
后沿抖动
机械式按键抖动时间 一般为5ms~10ms
抖动会引起一次按键被误读多次,必须消抖:
① 硬件消抖:利用RS触发器反馈形成双稳态电路
② 软件消抖:利用延时程序跳过抖动
(3)矩阵键盘与键位编码
独立键盘: ① 每个按键占用一根I/O线 ② 电路、程序简单 ③ 适合按键少 矩阵键盘: ① 按键采用行列结构复用I/O线 ② 电路、程序复杂 ③ 适合按键多
EBH DBH BBH 7BH E7H D7H B7H 80H 90H 88H 83H C6H A1H 86H 8 9 A B C D E
4×4矩阵键盘扫描与7段数码管显示
键盘采用二进制组合编码,数码管为7段共阳极
4 4键盘扫描实验
4*4键盘扫描实验目的:1. 熟悉51系列单片机矩形4*4键盘扫描的工作原理。
2. 掌握4*4键盘扫描的编程方法。
实验原理:键盘实际上是由排列成矩阵形式的一系列按键开关组成的,它是单片机系统中最常用的人机联系的一种输入设备。
用户通过键盘可以向CPU输入数据、地址和命令。
键盘按其结构形式可分为编码式键盘和非编码式键盘两大类。
编码式键盘是由其内部硬件逻辑电路自动产生被按键的编码。
这种键盘使用方便,但价格较贵。
4×4表示有4根行线和4根列线,在每根行线和列线的交叉点上均分布1个单触点按键,共有16个按键。
行扫描法所谓行扫描法,就是通过行线发出低电平信号,如果该行线所连接的键没有按下的话,则列线所连接的输出端口得到的是全“1”信号;如果有键按下的话,则得到的是非全“1”信号。
列扫描法所谓列扫描法,就是通过列线发出低电平信号,如果该列线所连接的键没有按下的话,则列线所连接的输出端口得到的是全“1”信号;如果有键按下的话,则得到的是非全“1”信号。
实验内容:1.编写一程序,4*4键盘扫描#include"reg51.h"#define uchar unsigned char#define uint unsigned intuchar keyno;uchar disp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c,0x39,0x5e,0x79,0x71}; uchar lieno;void delay1ms(uchar i){uchar j;while(i--)for(j=0;j<110;j++);}void main(){uchar tem;P0=0xff;while(1){P1=0x0f;if(P1!=0x0f)delay1ms(5);if(P1!=0x0f)tem=P1^0x0f;switch (tem){case 0x01:lieno=0;break;case 0x02:lieno=4;break;case 0x04:lieno=8;break;case 0x08:lieno=12;break;default :lieno=16;}P1=0xf0;tem=(P1>>4)^0x0f;switch (tem){case 0x01:keyno=lieno;break;case 0x02:keyno=lieno+1;break;case 0x04:keyno=lieno+2;break;case 0x08:keyno=lieno+3;}P0=disp[keyno];delay1ms(10);}}。
AT89C51单片机对4×4矩阵键盘进行动态扫描报告
【训练任务】:1、熟练掌握PROTEUS软件的使用;2、按照设计要求绘制电路原理图;3、能够按要求对所设计的电路进行仿真;【基本要求及说明】:1、按照设计要求自行定义电路图纸尺寸;2、设计任务如下:AT89C51单片机对4×4矩阵键盘进行动态扫描,当按键盘的键时,可将相应按键值(0~F)实时显示在数码管上;3、按照设计任务在Proteus 6 Professional中绘制电路原理图;4、根据设计任务的要求编写程序,画出程序流程图,并在Proteus下进行仿真,实现相应功能。
【按照要求撰写总结报告】:指导教师学生姓名班级、学号成绩评定表评语、建议或需要说明的问题:成绩指导教师签字:日期:目录1.任务说明 (1)2.原理图绘制说明 (1)3.流程图绘制以及说明 (2)4.PROTEUS仿真说明 (4)5.体会及合理化建议 (7)附录电路原理图 (8)参考文献 (9)电子设计应用软件训练总结报告一.任务说明AT89C51单片机对4×4矩阵键盘进行动态扫描,当按键盘的键时,可将相应按键值(0~F)实时显示在数码管上;按照设计任务在Proteus 6 Professional中绘制电路原理图;根据设计任务的要求编写程序,画出程序流程图,并在Proteus下进行仿真,实现相应功能。
二.原理图绘制说明1.原理图说明本实验是AT89C51单片机对4×4矩阵键盘进行动态扫描,当按键盘的键时,可将相应按键值(0~F)实时显示在数码管上。
4×4矩阵键盘是用4条I/O线作为行线,4条I/O线作为列线,在行线和列线的交叉点上设置一个按键,每个按键有它的行值和列值,用4条行线和列线分别接P2.0-P2.7,要进行数码管动态扫描,就要将数码管的七段a~f相应的与P1.0-P1.6相连接,即把输入端口P2.0-P2.7连接到4×4行列式按键上作为输入,P1.0-P1.6作为输出端口控制共阳级数码管a-g,对应的a-g 通过程序进行点亮或者熄灭来显示数值(0~F)。
- 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键开始加减计数。