键盘扫描程序
键盘扫描程序
#include<reg52.h>#define uint unsigned int#define uchar unsigned char#define IO P2uchar code wu[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位选择数据uchar code du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0到9的断模/******************************************函数名称:delayms;函数功能:延时z毫秒;形参:z (延时时间参数)*******************************************/void delayms(uchar z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/******************************************函数名称:display();函数功能:数码管显示子函数形参:d1 (选择第几位数码管)d2(数码管显示的数字)*******************************************/void display(uchar d1,uchar d2){P1=wu[d1]; //位选P0=du[d2]; // 段选delayms(1);P0=0xff;P1=0xff; // 关显示}/******************************************函数名称:display();函数功能:4*4矩阵键盘扫描子程序,16个键编号0到15,有键按下时返回按键编号(小于16),没键按下时返回16.形参:d1 (选择第几位数码管)d2(数码管显示的数字)*******************************************/uchar saom(void){uchar num,temp;num=17; //设定没键按下时返回17IO=0x7f; //扫描第一行temp=IO;temp&=0x0f;if(temp!=0x0f){delayms(1);temp=IO;temp=temp&0x0f;if(temp!=0x0f){temp=IO;switch(temp){case 0x77:num=1;break;case 0x7b:num=2;break;case 0x7d:num=3;break;case 0x7e:num=4;break;}temp&=0x0f;while(temp!=0x0f) //松手检测{temp=IO;temp&=0x0f;}}}IO=0xbf; //扫描第二行temp=IO;temp&=0x0f;if(temp!=0x0f){delayms(1);temp=IO;temp&=0x0f;if(temp!=0x0f){temp=IO;switch(temp){case 0xb7:num=5;break;case 0xbb:num=6;break;case 0xbd:num=7;break;case 0xbe:num=8;break;}temp&=0x0f;while(temp!=0x0f){temp=IO;temp&=0x0f;}}}IO=0xdf; //扫描第三行temp=IO;temp&=0x0f;if(temp!=0x0f){delayms(1);temp=IO;temp&=0x0f;if(temp!=0x0f){temp=IO;switch(temp){case 0xd7:num=9;break;case 0xdb:num=10;break;case 0xdd:num=11;break;case 0xde:num=12;break;}temp&=0x0f;while(temp!=0x0f){temp=IO;temp&=0x0f;}}}IO=0xef; //扫描第四行temp=IO;temp&=0x0f;if(temp!=0x0f){delayms(1);temp=IO;temp&=0x0f;if(temp!=0x0f){temp=IO;switch(temp){case 0xe7:num=13;break;case 0xeb:num=14;break;case 0xed:num=15;break;case 0xee:num=16;break;}temp&=0x0f;while(temp!=0x0f){temp=IO;temp&=0x0f;}}}return num; //返回键值}void main(void){uchar num_key1,num_key2;while(1){num_key1=saom(); //读按键值if(num_key1<17) //是否有按键按下,小于16时有按键按下{num_key2=num_key1;} //确实有键按下时值赋给num_key2display(0,num_key2%10); //显示按键编码的个位display(1,num_key2/10); //显示按键编码的十位}}。
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引脚输入,这样才能触发中断。
vhdl 4x4键盘扫描程序
WHEN "0100" =>
dyp_tmp <= "1100100";
WHEN "0101" =>
dyp_tmp <= "1001000";
BEGIN
row <= scan_key;
--dyp <= dyp_tmp;
ledct<="000001";
PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk = '1')THEN
div_cnt <= div_cnt + 1;
WHEN "0110" =>
dyp_tmp <= "0001000";
WHEN "0111" =>
dyp_tmp <= "1100011";
WHEN "1000" =>
WHEN "0001" =>
dyp_tmp <= "1100111";
WHEN "0010" =>
dyp_tmp <= "0010010";
WHEN "0011" =>
key_code <= "1101";
WHEN "1011" =>
key_code <= "1110";
4X4键盘扫描程序
4X4键盘扫描程序,采用查表方式,适用于AVR单片机。
此处为4X4键盘软件部分,硬件部分设计请参照:4X4键盘扫描电路分析。
此程序对应的键盘电路为:键盘状态扫描函数/*键盘扫描函数读取当前键盘的状态有按键按下返回相应按键值无按键按下返回"0x00"*/unsigned char key_read(void){unsigned char i;DDRA = 0x00;/*获取列地址*/PORTA = 0x0F;DDRA = 0xF0;此处应加入几uS延时;i = PINA;DDRA = 0x00;/*获取行地址*/PORTA = 0xF0;DDRA = 0x0F;此处应加入几uS延时;i |= PINA;DDRA = 0x00;/*输出复位*/PORTA = 0xFF;switch (i) {/*将按键码转换成键值*/ case 0x00: return 0x00;case 0xEE: return '1';case 0xDE: return '2';case 0xBE: return '3';case 0x7E: return 'A';case 0xED: return '4';case 0xDD: return '5';case 0xBD: return '6';case 0x7D: return 'B';case 0xEB: return '7';case 0xDB: return '8';case 0xBB: return '9';case 0x7B: return 'C';case 0xE7: return '*';case 0xD7: return '0';case 0xB7: return '#';case 0x77: return 'D';default : return 0x00;}}键盘读取函数/*按键获取函数获取按键信号,其中包含有状态记录及按键去颤抖。
键盘扫描程序实验报告
一、实验目的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. 实验结果:程序下载到单片机后,按键按下时,单片机能够正确读取按键值。
单片机键盘扫描程序(汇编)
MOV R7,#0FFH ;设置计数常数,作为延时
KEY1: DJNZ R7,KEY1
MOV A,P1 ;读取P1口的列值
ANL A,#0F0H ;判别有键值按下吗(当有键按下时,P1口的高四位就不全为1了,底四位还是都为0的)
MOV P2,A
SJMP LOOP
;子程序内容 ,P1口的第四位为行线,高四位为列线
KEY: PUSH PSW
PUSH ACC
MOV P1,#0F0H ;令所有的行为低电平,全扫描字-P1.0-P1.3,列为输入方式
AJMP DKEY
;取出具体的行号,再加上列号,最终确认按键的号码
DKEY: MOV R4,#00H
MOV A,R0
MOV B,#04H
MUL AB ;让行号*4,第四位放在A中(总共就4行,相乘后一定<16,也就是只有第四位有值)
DB 79H
DB 71H
END
LCALL DEL20ms ;有键按下,进行处理
;下面进行行行扫描,1行1行扫
SKEY: MOV A,#00H
MOV R0,A ;R0作为行计数器,开始初值为0
MOV R1,A ;R1作为列计数器,开始初值为0
;单片机键盘扫描程序(汇编)
;键盘扫描程序;此程序比较复杂,不过如果你坚持的理解下去的话,还是能够理解的,比较经典
;最终是按键的值输出到数码管中(接在P2口)
ORG 0000H
START: MOV R0,#00H ;初始化程序,开始的延时是为了使硬件能够准备好
;有键按下后行扫描过后,此为确列行
51单片机矩阵键盘扫描程序
{
TH0=(65536-2000)/256;//重新赋值2ms
TL0=(65536-2000)%256;
Display(0,8); //调用数码管扫描
}
/*------------------------------------------------
unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//显示段码值0~F
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
/*------------------------------------------------
uS延时函数,含有输入参数unsigned char t,无返回值
unsigned char是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5 uS
51单片机键盘扫描程序7294详细介绍
51单片机键盘扫描程序7294详细介绍1. 前言随着人们对电子产品的需求不断增加,微处理器成为现代电子设备中必不可少的一个组成部分。
其中,单片机作为一种嵌入式微处理器,由于其功能强大、价格低廉和易于编程等优点,被广泛应用于各个领域。
在单片机应用中,键盘扫描技术是常见的一种应用技术。
它既可以用于普通键盘,也可以用于定制键盘或遥控器等输入设备。
在51单片机中,键盘扫描程序7294是最为常用和经典的键盘扫描程序之一。
本文将详细介绍7294程序的原理、功能和实现方法。
2. 概述7294程序是一种基于矩阵扫描的键盘输入程序,也称为键盘扫描程序。
该程序主要由两个部分组成,即扫描部分和解码部分。
扫描部分是通过读取每个行端口和列端口的状态,得出当前按下的键位信息。
在实现过程中,通常采用交错式扫描,即先扫描行端口再扫描列端口。
这种方式可以避免多个键同时按下时无法识别的情况。
解码部分负责将扫描部分得到的行列矩阵转换成对应的键位信息。
这里我们可以采用查表法或者位运算法来实现。
3. 原理主要原理7294程序的主要工作原理如下:(1)行列扫描首先,程序将所有行端口设为输出,所有列端口设为输入。
接着,程序对每个行端口进行扫描,每次只将一个行端口输出高电平,同时读取所有列端口的状态。
如果任意一个列端口检测到低电平,说明该列与当前行对应的键被按下,程序将该键位信息保存下来。
反之,如果所有列端口均输出高电平,说明该行无按键按下。
(2)解码当扫描部分输出一个键位矩阵后,解码部分即开始工作。
首先,程序将每个键位的状态 (按下或放开)保存到一个矩阵中。
接着,程序通过查表法或者位运算法将该矩阵转换成对应的键位信息,然后提交给主程序进行后续处理。
4. 具体实现为了更好地理解7294程序的实现步骤,我们这里以4x4矩阵键盘为例展示其具体实现过程。
(1)硬件连接首先,将4个行端口 (行1~行4)和4个列端口 (列1~列4)分别连接到51单片机的IO口,如图所示:(2)扫描过程接着,通过编写程序实现键盘的扫描过程。
最简单的矩阵键盘扫描程序
这是站长初学单片机时写的最简单、最详细、效率最高的矩阵键盘扫描程序,只用了四条常用命令(MOV/送数、JB/高电平转移、JMP/直接转移、RET/子程序返回),保证初学者一看就懂!之所以称为最简单,是因为加上子程序返回指令(RET)一共只用了四条最常用的指令!本程序已经在本站电子实验板上验证通过,占用CPU时间少,效率高,被选作单片机的测试程序!(本站198元的单片机套件中还有一例子中采用了更新更简短的代码写成了另一个矩阵键盘扫描程序。
)矩阵按键扫描程序是一种节省IO口的方法,按键数目越多节省IO口就越可观,本程序的思路跟书上一样:先判断某一列(行)是否有按键按下,再判断该行(列)是那一只键按下。
但是,在程序的写法上,站长采用了最简单的方法,使得程序效率最高。
本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。
另外,本人认为键盘用延时程序来消除抖动,完全是浪费时间。
试想,如果不用中断执行(用中断执行需要更多的硬件资源)的方法来扫描键盘,每秒钟扫描20-100次,每次都要延时10-20MS的话,我们的单片机还有多少时间做正事呢?所以,很多人学会了单片机,最终确做不出产品(除非产品跟例子一样)。
其实,延时的这段时间,CPU可以做其它的事呀。
所以,本键盘扫描程序的前面后面都可以加入少少代码,既可以达到完美的消抖动效果,又可以扩展其它的功能(例如按键封锁、按键长按等按键功第 1 页能复用!)。
注意:以上都是当时的看法,不过,现在还是很有用。
本键盘扫描子程序名叫key,每次要扫描时用call key调用即可。
以下子程序内容:key:mov p0,#00001111b;上四位和下四位分别为行和列,所以送出高低电压检查有没有按键按下 jmp k10; 跳到K10处开始扫描,这里可以改成其它条件转移指令来决定本次扫描是否要继续,例如减1为0转移或者位为1或0才转移,这主要用来增加功能,确认上一按键功能是否完成?是否相当于经过了延时?是否要封锁键盘?goend:jmp kend; 如果上面判断本次不执行键盘扫描程序,则立即转到程序尾部,不要浪费CPU的时间k10:jb p0.0,k20; 扫描正式开始,先检查列1四个键是否有键按下,如果没有,则跳到K20检查列2k11:mov p0,#11101111b;列1有键按下时,P0.0变低,到底是那一个键按下?现在分别输出各行低电平jb p0.0,k12; 该行的键不按下时,p0.0为高电平,跳到到K12,检查其它的行mov r1,#1; 如果正好是这行的键按下,将寄存器R0写下1,表示1号键按下了k12:mov p0,#11011111bjb p0.0,k13mov r1,#2; 如果正好是这行的键按下,将寄存器R0写下2,表示2号键按下了第 2 页k13:mov p0,#10111111bjb p0.0,k14mov r1,#3; 如果正好是这行的键按下,将寄存器R0写下3,表示3号键按下了k14:mov p0,#01111111bjb p0.0,kend; 如果现在四个键都没有按下,可能按键松开或干扰,退出扫描(以后相同) mov r1,#4; 如果正好是这行的键按下,将寄存器R0写下4,表示4号键按下了jmp kend; 已经找到按下的键,跳到结尾吧k20:jb p0.1,k30; 列2检查为高电平再检查列3、4k21:mov p0,#11101111b;列2有健按下时,P0.0会变低,到底是那一行的键按下呢?分别输出行的低电平jb p0.1,k22; 该行的键不按下时p0.0为高电平,跳到到K22,检查另外三行mov r1,#5; 如果正好是这行的键按下,将寄存器R0写下5,表示5号键按下了(以后相同,不再重复了)k22:mov p0,#11011111bjb p0.1,k23mov r1,#6k23:mov p0,#10111111bjb p0.1,k24mov r1,#7k24:mov p0,#01111111b第 3 页jb p0.1,kendmov r1,#8jmp kend; 已经找到按下的键,跳到结尾吧(以后相同,不要重复了)k30:jb p0.2,k40k31:mov p0,#11101111bjb p0.2,k32mov r1,#9k32:mov p0,#11011111bjb p0.2,k33mov r1,#10k33:mov p0,#10111111bjb p0.2,k34mov r1,#11k34:mov p0,#01111111bjb p0.2,kendmov r1,#12jmp kendk40:jb p0.3,kendk41:mov p0,#11101111bjb p0.3,k42mov r1,#13k42:mov p0,#11011111bjb p0.3,k43mov r1,#14k43:mov p0,#10111111bjb p0.3,k44第 4 页mov r1,#15k44:mov p0,#01111111bjb p0.3,kendmov r1,#16kend: ret键盘扫描结束了,寄存器R1的值就直接表示了是那个键按下的,根据不同的键值去执行不同的程序,从而实现了十六个矩阵键盘扫描,同样原理,最多可以识别255个按键的矩阵扫描。
键盘扫描显示实验程序
OUTBIT equ 0e101h CLK164 equ 0e102h DAT164 equ 0e102h IN equ 0e103h LEDBuf equ 60h ljmp Start LEDMAP: db 3 , 06h, 5bh, 4 , 66h, 6dh, 7dh, 07h db 7 , 6 , 77h, 7ch, 39h, 5eh, 79h, 71h db 00H Delay: mov r7, #0 DelayLoop: djnz r7, DelayLoop djnz r6, DelayLoop ret DisplayLED: mov r0, #LEDBuf mov r1, #6 mov r2, #00100000b Loop: mov dptr, #OUTBIT mov a, #0 movx @dptr, a mov a, @r0 mov B, #8 DLP: rlc a mov r3, a mov acc.0, c mov dptr, #DAT164 anl a,#0fdh movx @dptr, a mov dptr, #CLK164 orl a,#02h movx @dptr, a anl a,#0fdh movx @dptr, a mov a, r3 djnz B, DLP mov dptr, #OUTBIT mov a, r2 movx @dptr, a mov r6, #1 call Delay mov a, r2 rr a mov r2, a inc r0 djnz r1, Loop ret TestKey: mov dptr, #OUTBIT mov a, #0 movx @dptr, a mov dptr, #IN movx a, @dptr cpl a anl a, #0 ret KeyTable: db 00h, 01h, 04h, 07h db 0 , 02h, 05h, 08h db 0eh, 03h, 06h, 09h db 0dh, 0ch, 0bh, 0ah db 10H,10H,10H,10H,10H, db 10H,10H,10H,10H,10H GetKey: mov dptr, #OUTBIT mov P2, dph mov r0, #Low(IN) mov r1, #00100000b mov r2, #6 KLoop: mov a, r1 cpl a movx @dptr, a cpl a rr a mov r1, a movx a, @r0 cpl a anl a, #0 jnz Goon1 djnz r2, KLoop mov r2, #0 sjmp Exit Goon1: mov r1, a mov a, r2 dec a rl a rl a mov r2, a mov a, r1 mov r1, #4 LoopC: rrc a jc Exit inc r2 djnz r1, LoopC Exit: mov a, r2 mov dptr, #KeyTable movc a, @a+dptr mov r2, a WaitRelease: mov dptr, #OUTBIT clr a movx @dptr, a mov r6, #10 call Delay call TestKey jnz WaitRelease mov a, r2 ret Start: mov sp, #40h mov dptr,#0e100h mov a,#03h movx @dptr,a mov LEDBuf, #0 mov LEDBuf+1, #0 mov LEDBuf+2, #0 mov LEDBuf+3, #0 mov LEDBuf+4, #0 mov LEDBuf+5, #0 MLoop: call DisplayLED call TestKey jz MLoop call GetKey anl a, #1 mov dptr, #LEDMap movc a, @a+dptr mov LEDBuf+5, a ljmp MLoop end 。
51单片机数码管显示及矩阵键盘扫描程序
51单片机数码管显示及矩阵键盘扫描程序硬件实验十一八段数码管实验一、实验任务1、在静态数码管上轮流显示数字0-9。
2、在两个4位数码管上动态显示数字0-9二、流程图及程序静态显示:流程图:程序代码:#include#define uchar unsigned chucharcodevalue[10]={0xC0,0xF9,0xA4,0xB0,0X99,0x92,0x82,0xF8,0 x80,0x90};//0 -9数码管显示段码void delay(char x) //延时子程序{uchar i;for(i=0;i<200;i++);}main() //主函数{int i;while(1){for(i=0;i<10;i++) //显示0-9{P0=codevalue[i];delay(500); //延时1秒}}}动态显示:#include#includetab1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f}; //数码管显示数字字段unsigned char tab2[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//片选字段unsigned char i,k,j,x;void delay(x); //声明延时子函数void main() //主函数{while(1){for(i=0;i<8;i++) //显示0-7{ P1=tab1[i];P0=tab2[i];delay(5); //延时}P1=tab1[8]; P0=tab2[0]; delay(5); //显示8-9P1=tab1[9]; P0=tab2[1]; delay(5);}}void delay(x) //延时函数定义{do{for(j=0;j<250;j++)for(k=0;k<250;k++);}}硬件实验十二矩阵键盘扫描显示一、实验任务1、把矩阵键盘上的按键输入的键码在静态数码管上显示出来。
4×4键盘扫描程序
键盘程序假设P2.0-P2.3为H0-H3,P2.4-P2.7为L0-L3 (列) L0 L1 L2 L3(行) H0 0 1 2 3H1 4 5 6 7H2 8 9 A BH3 C D E F首先,行为P2口的低四位,而列为高四位。
P0口为数码管输出口。
第一种思路就是逐行逐列判断法。
#include<reg51.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuchar code table[17] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf};//八段数码管对应0-F值. uchar temp;void Delay_1ms(uint i)//1ms延时{uint x, j;for(j=0;j<i;j++)for(x=0;x<=148;x++);}void delay()//消除按键抖动延时{int i,j;for(i=0; i<=10; i++)for(j=0; j<=2; j++);}uchar Keyscan(void){uchar i,j,row,col;temp=P2&0xf0;for(i=0; i<4; i++){if(!(temp&(0x10<<i)))row=i;}P2=0x0f;temp=P2&0x0f;for(j=0; j<4; j++){if(!(temp&(0x01<<j)))col=j;}return (row+col*4);}void Main(void){uchar Key_Value=16; //读出的键值uchar i=0;while(1){P2 = 0xf0;temp=P2;if(temp != 0xf0){Delay_1ms(80); //按键消抖if(temp != 0xf0){Key_Value = Keyscan();}Delay_1ms(350); //按键消抖}P0 = table[Key_Value];//P0口输出数据到数码管}次读取结果组合起来就可以得到当前按键的特征编码。
经典的矩阵键盘扫描程序
经典的矩阵键盘扫描程序查找哪个按键被按下的方法为:一个一个地查找。
先第一行输出0,检查列线是否非全高;否则第二行输出0,检查列线是否非全高;否则第三行输出0,检查列线是否非全高;如果某行输出0时,查到列线非全高,则该行有按键按下;根据第几行线输出0与第几列线读入为0,即可判断在具体什么位置的按键按下。
下面是具体程序:void Check_Key(void){unsigned char row,col,tmp1,tmp2;tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0for(row=0;row<4;row++) // 行检测{P1 = 0x0f; // 先将p1.4~P1.7置高P1 =~tmp1; // 使P1.4~p1.7中有一个为0tmp1*=2; // tmp1左移一位if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测{tmp2 = 0x01; // tmp2用于检测出哪一列为0for(col =0;col<4;col++) // 列检测{if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列{key_val =key_Map[ row*4 +col ]; // 获取键值,识别按键;key_Map为按键的定义表return; // 退出循环}tmp2*=2; // tmp2左移一位}}}} //结束这是一种比较经典的矩阵键盘识别方法,实现起来较为简单,程序短小精炼。
4*4矩阵键盘扫描程序/*设置行线为输入线,列线为输出线*/uchar KeyScan(); //按键扫描子程序void delay10ms(); //延时程序uchar key_free(); //等待按键释放程序void key_deal(); //键处理程序//主程序void main(){while(1){KeyScan();key_free();key_deal();}}//按键扫描子程序uchar KyeScan(){unsigned char key,temp;P1=0xF0;if(P1&0xF0!=0xF0){delay10ms(); //延时去抖动if(P1&0xF0!=0xF0){P1=0xFE; //扫描第一列temp=P1;temp=temp&0xF0;if(temp!=0xF0) //如果本列有键按下{switch(temp){case 0xE0: //第一行有键按下key=1;break;case 0xD0: //第二行有键按下key=4;break;case 0xB0: //第三行有键按下key=8;break;case 0x70: //第四行有键按下key=12;break;}}P1=0xFD; //扫描第二列temp=P1;temp&=0xF0;if(temp!=0xF0){switch(temp){case 0xE0: //第一行有键按下key=1;break;case 0xD0: //第二行有键按下key=5;break;case 0xB0: //第三行有键按下key=9;break;case 0x70: //第四行有键按下key=13;break;}}P1=0xFb; //扫描第三列temp=P1;temp&=0xF0;if(temp!=0xF0){switch(temp){case 0xE0: //第一行有键按下key=2;break;case 0xD0: //第二行有键按下key=6;break;case 0xB0: //第三行有键按下key=10;break;case 0x70: //第四行有键按下key=14;break;}}P1=0xF7; //扫描第四列temp=P1;temp&=0xF0;if(temp!=0xF0){switch(temp){case 0xE0: //第一行有键按下key=3;break;case 0xD0: //第二行有键按下key=7;break;case 0xB0: //第三行有键按下key=11;break;case 0x70: //第四行有键按下key=15;break;}}}return(key);}}//延时程序void delay10ms(){unsigned char i,j;for(i=0;i<10;b++)for(j=0;j<120;j++)//延时1ms{}}//等待按键释放程序uchar key_free(){key=key_scan(); //取扫描到的键值P1=0xF0;//置行线全为高电平,列线全为低电平wheile(P1&0xF0!=0xF0) //如果仍有键按下{}return(key);//返回键值}51单片机矩阵键盘扫描、数码管显示键值实验/***********************************************程序名称:矩阵键盘扫描显示键值简要说明:P1口接矩阵键盘:低四位列,高四位行使用共阳型数码管:P0口输出数码管段码,P2口输出数码管位码编写:***********************************************/#include <AT89x52.h>#define uchar unsigned char;uchar key_val=0; //定义键值,初始默认为0uchar code TAB[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xC6,0xa1,0x86,0x8 e}; //0~F共阳数码管显示段码/*****按键扫描*****/void Check_Key(void){unsigned char row,col,tmp1,tmp2;tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0for(row=0;row<4;row++) // 行检测{P1 = 0x0f; // 先将p1.4~P1.7置高P1 =~tmp1; // 使P1.4~p1.7中有一个为0tmp1*=2; // tmp1左移一位if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测{tmp2 = 0x01; // tmp2用于检测出哪一列为0for(col =0;col<4;col++) // 列检测{if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列{key_val = row*4 +col; // 获取键值,识别按键return; // 退出循环}tmp2*=2; // tmp2左移一位}}}}/*****主函数,显示键值*****/void main(){P2=0x00; //位码,这里全部置低,点亮8位数码管(见视频效果)while(1){Check_Key();P0=TAB[key_val]; //显示}}实验7 矩阵按键识别技术矩阵按键部分由16个轻触按键按照4行4列排列,连接到JP50端口。
键盘扫描程序第一步判断有无按键按...
第六章:汇编语言程序设计总结考试说明:要清楚考试的重点是什么。
程序设计题目的难度不大,算法的要求不高。
重点是程序的整体框架,也即书写格式要规范,注释最好是每一步都加上注释。
另外是把老师上课讲的例题(主要是幻灯片上的例题)彻底搞懂。
一、首先要知道整个程序的格式规范:1.ASM-86汇编语言中,有两种语句:(1)指令性语句一条指令性语句就是一条8086指令,例如 ADD AL,BL和MOV CX,1000;每一条指令性语句都会在汇编过程中产生相应的目标代码。
例如:START : MOV AX,1090 ;将16进制数1090H送入ALINC BX(2)指示性语句指示性语句又称为伪指令,例如 SEGMENT和ABC DB 50H。
伪指令用来为汇编程序提供某些信息,让汇编程序在汇编的过程中执行特定功能的信息,比如规定一个数据段从哪里开始到哪里结束等。
每一条伪指令在汇编的过程中都不会产生相应的目标代码。
例如:CR DB ODH ;在单元CR处存放数据0DHORG 200H ;目标程序的偏移量SEGMENT(3)指令性语句和指示性语句的最大区别:就是指示性语句在标号和伪指令助记符没有冒号2.书写格式模板:这是考试重点,后面的例子详解有实际的例子。
数据段名(一般:DATA) SEGMENT………数据段内容………数据段名(DATA) ENDS堆栈段名(一般:STACK)SEGMENT………堆栈段内容………堆栈段名(STACK)ENDS代码段名(一般:CODE) SEGMENTASSUME CS:代码段名, DS:数据段名, SS:堆栈段名………代码段内容………代码段名(CODE) ENDSEND3.标识符说明:主要是别把保留字和界符当做标识符。
“标识符”是字母,数字,下划线的组合,但不能用下划线开头,长度不能超过31个字符。
保留字和界符不能用作标识符。
“保留字”是汇编程序中预先保留下来具有特殊含义的符号,例如:MOV、ADD 等。
holtek HT48 HT4键盘扫描程序 说明书
HT48 & HT46键盘扫描程序文件编码:HA0011s简介:这是一个4×4 的键盘阵列,总共有16个键,如图所示每个键都有一个16进制的代码。
键盘扫描程序扫描键盘阵列确认是哪一个键被按下了,确定键后用LED显示它的2进制代码。
如图,这有4个LED,表示的值是从0000H 到 1111H。
在扫描过程中,如果同时有两个键被按下的话,那么只有第一个被扫描到的键会被检测到并显示。
使用这种方法的编码键盘可以把每一个值指定给键电路设计:PA0~PA3设置为输出口,PA4~PA7设置为输入口,这样组成了一个4×4的阵列,程序扫描哪一个键被按下,查表确定它的值。
PB0~PB3定义为输出口,它输出4位二进制码,16个值每个值对应一个键。
扫描过程:以第一行第一列为例。
先向PA口输出0FEH,既扫描第一行。
如果第一行有键按下,则读入的PA口键值的高位不会为F;如果PA口高位不为F,则第一行有键按下,转入列扫描。
如果第一列有键按下,则PA.4为0,否则为1。
这样可以确定按下键的行和列,确定其编码。
程序清单:#include ht48r10a-1.inc;----------------------------------------------------------datadata .section ‘datat’ ;数据段temp db ?;暂时数据寄存器temp2 db ? ;用于保存键盘扫描码以检测列值disp db ?;键值显示寄存器count1 db ?;延时计数指针mask db ?;屏蔽寄存器matrix db ?;键盘阵列寄存器r;----------------------------------------------------------codecode .section at 0 ‘code’ ;程序段org 00hjmp startstart: ;程序开始clr pbc ;设置PB口为输出口mov a,0f0h ;(1) ;设置PA高4位为输入口、低四位为输出口mov pac,aclr pa ;清PA 口clr pb ;清PB 口keyloop: ;键扫描循环mov a,0feh ;(2) ;扫描第一行是否被按下mov matrix,a ;将第一行的代码送matrixmov pa,a ;输出扫描码到PA 口mov a,pa ;读入PA口的状态到ACCxor a,0feh ;判断高4位有无0?如有,则有键按下,ACC值应改变sz acc ;第一行是否有键按下:如果有键按下,则ACC不为0 jmp get_key ;有键按下跳到读键值mov a,0fdh ;(2) ;扫描第二行是否被按下mov matrix,a ;将第二行的代码送matrixmov pa,amov a,paxor a,0fdhsz accjmp get_keymov a,0fbh ;(2) ;扫描第三行是否被按下mov matrix,a ;将第三行的代码送matrixmov pa,amov a,paxor a,0fbhsz accjmp get_keymov a,0f7h ;(2) ;扫描第四行是否被按下mov matrix,a ;将第四行的代码送matrixmov pa,amov a,paxor a,0f7hsz accjmp get_keyjmp keyloop ;跳回键循环扫描get_key: ;取键值call key_in ;(3) ;调用key_in 子程序mov pb,a ;(11) ;从PB口显示键值jmp keyloop ;跳回键循环扫描key_inproc ;键值读入子程序mov a,pa ;读取PA口数据mov temp,a ;(4) ;将PA口的状态读入的 temp寄存器中mov temp2,a ;扫描值送入temp2用于检测列值call delays ;(5) ;调用延时子程序get_release: ;等待键松开mov a,pa ;将PA口的主状态值送ACCand a,0f0h ;屏蔽ACC高四位,取按键状态xor a,0f0hsz acc ;(6) ;等键松开 , 键如松开则acc=0jmp get_releasemov a,0fh ;取屏蔽寄存器的低四位andm a,matrixmov a,0get_row: ;取行数rrc matrix ;(7) ;右移 matrix 指针status.0 ;检查并取键行szjmp get_column1 ;如果找到键行,跳到 get_next clr c ;如果还未找到键行,清carry_c add a,4h ;(8) ;加4到显示指针jmp get_row ;跳回get_rowget_colmn1:mov temp,amov a,0f0handm a,temp2 ;取键盘扫描码的高4位,检测列值swap temp2 ;交换,把列值放到低4位上mov a,0h ;(9)get_column:rrc temp2 ;逐位检测,到该位为0为止snz status.0 ;为0,则说明该列有键按下jmp nextclr cadd a,1hjmp get_column ;取出列值next:add a,tempxor a,0ffh ;计算键值并求出显示码key_in endpproc ;延时子程序delaysmov a,0ffhmov count1,ad1:sdz count1jmp d1retdelays endp程序说明:(1)段定义了哪些口是输入口,哪些口是输出口。
经典的矩阵键盘扫描程序
经典的矩阵键盘扫描程序矩阵键盘是一种常见的输入设备,广泛应用于电子产品中。
为了实现对矩阵键盘的扫描和输入响应,需要编写一个矩阵键盘扫描程序。
本文将详细介绍如何编写一个经典的矩阵键盘扫描程序。
1. 程序功能描述矩阵键盘扫描程序的主要功能是实现对矩阵键盘的扫描,并根据按键的状态进行相应的处理。
程序需要实现以下功能:- 扫描矩阵键盘的按键状态;- 根据按键状态进行相应的处理;- 输出按键的值或执行相应的操作。
2. 程序设计思路矩阵键盘通常由多行多列的按键组成,每个按键都有一个唯一的行列地址。
程序的设计思路如下:- 初始化矩阵键盘的引脚和状态变量;- 循环扫描矩阵键盘的按键状态;- 检测按键状态变化,并根据变化进行相应的处理;- 输出按键的值或执行相应的操作。
3. 程序代码示例下面是一个简单的矩阵键盘扫描程序的代码示例:```#include <stdio.h>#include <stdbool.h>// 定义矩阵键盘的行列数#define ROWS 4#define COLS 4// 定义矩阵键盘的引脚int rowPins[ROWS] = {2, 3, 4, 5}; int colPins[COLS] = {6, 7, 8, 9}; // 定义矩阵键盘的按键值char keys[ROWS][COLS] = {{'1', '2', '3', 'A'},{'4', '5', '6', 'B'},{'7', '8', '9', 'C'},{'*', '0', '#', 'D'}};// 初始化矩阵键盘void setup() {// 设置引脚模式为输入for (int i = 0; i < ROWS; i++) { pinMode(rowPins[i], INPUT); }// 设置引脚模式为输出for (int i = 0; i < COLS; i++) {pinMode(colPins[i], OUTPUT);}}// 扫描矩阵键盘void scanKeypad() {for (int i = 0; i < COLS; i++) {// 将当前列引脚设置为高电平digitalWrite(colPins[i], HIGH);for (int j = 0; j < ROWS; j++) {// 检测当前行引脚的状态bool state = digitalRead(rowPins[j]); // 如果按键状态发生变化if (state != lastState[i][j]) {// 更新按键状态lastState[i][j] = state;// 如果按键被按下if (state == LOW) {// 输出按键的值Serial.println(keys[j][i]);// 执行相应的操作switch (keys[j][i]) {case '1':// 执行操作1break;case '2':// 执行操作2break;// 其他按键的操作}}}}// 将当前列引脚设置为低电平 digitalWrite(colPins[i], LOW); }}void loop() {// 扫描矩阵键盘scanKeypad();// 延时一段时间,避免频繁扫描delay(10);}```4. 程序运行结果编写完成矩阵键盘扫描程序后,可以将程序上传到相应的开发板或单片机上进行测试。
51单片机的键盘扫描程序
一个51单片机的键盘扫描程序,算法简单有效/****************************************键盘_不采用定时器_不延时特点:按键在松手后有效,灵敏度高,消耗资源少,运行效率高独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7;矩阵键盘为:行(上到下)_P2.3_P2.2_P2.1_P2.0列(左到右)_P2.7_P2.6_P2.5_P2.4提供的操作函数://独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_keyextern unsigned char keyboard_self();//矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位extern unsigned char keyboard_matrix();****************************************/先看独立键盘(和矩阵键盘的算法一样)-----------------------------------------------------------------------#include<reg52.h>#include<intrins.h>//独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_keyextern unsigned char keyboard_self(){unsigned char num_key=0;//按键号unsigned char temp=0;//用于读取P2线上按键值static unsigned char temp_code=0;//保存按键值static unsigned char num_check=0;//低电平有效次数static unsigned char key_flag=0;//按键有效标识temp=P2&0xF0;//读取P2线数据if(temp!=0xF0)//低电平判断{num_check++;if(num_check==10)//连续10次(10ms)低电平有效,则认为按键有效{key_flag=1;//使能按键有效标识temp_code=temp;//保存按键值}}else//松手时判断{num_check=0;if(key_flag==1)//按键有效{key_flag=0;switch(temp_code)//读取按键号{case 0xE0: num_key=1;break;case 0xD0: num_key=2;break;case 0xB0: num_key=3;break;case 0x70: num_key=4;break;}}}return(num_key);}现在是矩阵键盘的-----------------------------------------------------------------------#include<reg52.h>#include<intrins.h>//矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位extern unsigned char keyboard_matrix(){unsigned char num_key=0;//按键号unsigned char temp=0;//读取P2口线数据static unsigned char temp_code=0;//用于保存按键值static unsigned char temp_circle=0xFE;//保存P2线上的循环扫描值static unsigned char num_check=0;//低电平计数static unsigned char key_flag=0;//按键有效标识P2=temp_circle;//0xFXtemp=P2;//读取P2口线数据if(temp!=temp_circle)//有按键动作{num_check++;//低电平计数|逢低电平加1if(num_check==10)//连续10次(10ms)低电平有效{key_flag=1;//按键有效标识置1temp_code=temp;//保存按键值}}else//松手OR无按键动作,此时应该改变扫描线{num_check=0;if(key_flag==1)//按键有效判断{key_flag=0;switch(temp_code)//读取按键号{//P2^0线case 0xEE: num_key=1;break;case 0xDE: num_key=2;break;case 0xBE: num_key=3;break;case 0x7E: num_key=4;break;//P2^1线case 0xED: num_key=5;break;case 0xDD: num_key=6;break;case 0xBD: num_key=7;break;case 0x7D: num_key=8;break;//P2^2线case 0xEB: num_key=9;break;case 0xDB: num_key=10;break;case 0xBB: num_key=11;break;case 0x7B: num_key=12;break;//P2^3线case 0xE7: num_key=13;break;case 0xD7: num_key=14;break;case 0xB7: num_key=15;break;case 0x77: num_key=16;break;}}temp_circle=_crol_(temp_circle,1);//改变扫描线if(temp_circle==0xEF){temp_circle=0xFE;}}return(num_key);//返回按键号}/************************************************************************* 未按键时,扫描线一直变化。
键盘扫描通用程序
} }
//i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void send(uchar key_num)
{
SBUF=key_num;
while(!TI);
TI=0;
}
void matrixkeyscan()
{
uchar temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
直接给你提供键盘扫描程序,你想怎么设定按键就怎么设2系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
if(temp!=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
} P3=0xfb; temp=P3; temp=temp&0xf0; if(temp!=0xf0) {
delayms(10); temp=P3; temp=temp&0xf0; if(temp!=0xf0) {
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
键盘扫描
OUTBIT EQU 08002H ; 位控制口
OUTSEG EQU 08004H ; 段控制口
IN EQU 08001H ; 键盘读入口
LEDBUF EQU 60H ; 显示缓冲
LJMP START
START:
MOV SP, #40H
MOV LEDBUF+0, #0FFH ; 显示8.8.8.8.
MOV LEDBUF+1, #0FFH
MOV LEDBUF+2, #0FFH
MOV LEDBUF+3, #0FFH
MOV LEDBUF+4, #0
MOV LEDBUF+5, #0
MLOOP:
CALL DISPLAYLED ; 显示
CALL TESTKEY ; 有键入?
JZ MLOOP ; 无键入, 继续显示
CALL GETKEY ; 读入键码
ANL A, #0FH ; 显示键码
MOV DPTR, #LEDMAP
MOVC A, @A+DPTR
MOV LEDBUF+5, A
LJMP MLOOP
; 延时子程序
DELAY:
MOV R7, #0
DELAYLOOP:
DJNZ R7, DELAYLOOP
DJNZ R6, DELAYLOOP
RET
;显示子程序
DISPLAYLED:
MOV R0, #LEDBUF
MOV R1, #6 ; 共6个八段管
MOV R2, #00100000B ; 从左边开始显示LOOP:
MOV DPTR, #OUTBIT
MOV A, #0
MOVX @DPTR, A ; 关所有八段管
MOV A, @R0
MOV DPTR, #OUTSEG
MOVX @DPTR, A
MOV DPTR, #OUTBIT
MOV A, R2
MOVX @DPTR, A ; 显示一位八段管
MOV R6, #1
CALL DELAY
MOV A, R2 ; 显示下一位
RR A
MOV R2, A
INC R0
DJNZ R1, LOOP
RET
;判断是否有键按下子程序
TESTKEY:
MOV DPTR, #OUTBIT
MOV A, #0
MOVX @DPTR, A ; 输出线置为0
MOV DPTR, #IN
MOVX A, @DPTR ; 读入键状态
CPL A
ANL A, #0FH ; 高四位不用
RET
;扫描键码程序
GETKEY:
MOV DPTR, #OUTBIT
MOV P2, DPH
MOV R0, #LOW(IN)
MOV R1, #00100000B
MOV R2, #6
KLOOP:
MOV A, R1 ; 找出键所在列
CPL A
MOVX @DPTR, A
CPL A
RR A
MOV R1,A ; 下一列
MOVX A, @R0
CPL A
ANL A, #0FH
JNZ GOON1 ; 该列有键入
DJNZ R2, KLOOP
MOV R2, #0FFH ; 没有键按下, 返回0FFH
SJMP EXIT
GOON1:
MOV R1,A ; 键值= 列X4 + 行
MOV A, R2
DEC A
RL A
RL A
MOV R2, A ; R2 = (R2-1)*4
MOV A, R1 ;R1中为读入的行值
MOV R1, #4
LOOPC:
RRC A ; 移位找出所在行
JC EXIT
INC R2 ;R2 =R2+ 行值
DJNZ R1, LOOPC
EXIT:
MOV A, R2 ; 取出键码
MOV DPTR, #KEYTABLE
MOVC A, @A+DPTR
MOV R2, A
WAITRELEASE:
MOV DPTR, #OUTBIT ; 等键释放
CLR A
MOVX @DPTR, A
MOV R6, #10
CALL DELAY
CALL TESTKEY
JNZ WAITRELEASE
MOV A, R2
RET
; 八段管显示码
LEDMAP:
DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H
DB 7FH, 6FH, 77H, 7CH, 39H, 5EH, 79H, 71H ; 键码定义
KEYTABLE:
DB 16H, 15H, 14H, 0FFH
DB 13H, 12H, 11H, 10H
DB 0DH, 0CH, 0BH, 0AH
DB 0EH, 03H, 06H, 09H
DB 0FH, 02H, 05H, 08H
DB 00H, 01H, 04H, 07H
END。