单片机矩阵键盘扫描程序

合集下载

单片机控制的矩阵键盘扫描程序集

单片机控制的矩阵键盘扫描程序集

单片机控制的矩阵键盘扫描程序集各种各样的矩阵键盘扫描程序集矩阵键盘的扫描对初学者来说是不可避免的,然而也相对来说有点难度.鉴于此,我整理了一下,我所遇到的矩阵键盘扫描程序集,将相继贴上来,供大家参考! 说明:这些大多都是网上转贴来的,其所有权归原作者!谢谢合作.最简单矩阵键盘扫描程序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号键按下了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,#01111111bjb 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,k44MOV r1,#15k44:MOV p0,#01111111bjb p0.3,kendMOV r1,#16kend: ret行列扫描键盘可检测出双键按下#include <reg52.h>#define ulong unsigned long#define uint unsigned int#define uchar unsigned charextern void delay(unsigned int x);unsigned char Tab_key[]= //行列式键盘映射{0x00, //无键按下’’7’’,’’8’’,’’9’’,’’/’’,’’4’’,’’5’’,’’6’’,’’*’’,’’1’’,’’2’’,’’3’’,’’-’’,’’C’’,’’0’’,’’=’’,’’+’’,//下面为按’’C’’同时再按的键:’’7’’,’’8’’,’’9’’,’’/’’,’’4’’,’’5’’,’’6’’,’’*’’,’’1’’,’’2’’,’’3’’,’’-’’,’’0’’,’’=’’,’’+’’,};// P1口行列式键盘//#define KEYPIN_L P1 // 定义键扫描列端口为P1低四位输入//#define KEYPIN_H P1 // 定义键扫描行端口为P1高四位扫描输出//// P1口行列式键盘////公用函数unsigned char KeysCAN(void); // 键扫描函数// //内部私有函数unsigned char fnKeycode(unsigned char key); // 根据键盘映射表输出顺序键值///*// P1口行列式键盘//extern unsigned char KeysCAN(void); // 键扫描函数//*/// P1口行列式键盘////---------------------------------------------------------------------------//unsigned char KeysCAN(void) // 键扫描函数//{unsigned char sccode,recode,keytemp = 0;KEYPIN_L = KEYPIN_L|0x0f; // P1低四位为列线输入//KEYPIN_H = KEYPIN_H&0x0f; // P1高四位为行线发全零扫描码//if ((KEYPIN_L&0x0f) != 0x0f){delay(10); // 延时10 MS 消抖//if ((KEYPIN_L&0x0f) != 0x0f){sccode = 0xef; // 逐行扫描码初值(1110 1111) //while(sccode != 0xff) //将扫描4次,keytemp为每次键值相或的值//{KEYPIN_H = sccode; // 输出行扫描码//if ((KEYPIN_L&0x0f) != 0x0f) // 本行有键按下//{recode = (KEYPIN_L&0x0f)|0xf0; // 只要低位,高位置1 //keytemp |= (~sccode)+(~recode); //特征码(高位为列P3,低位为行KEYPIN_H) //}sccode = (sccode << 1)|0x01; // 扫描码0向高位移动//}}}KEYPIN_H = KEYPIN_H|0xf0;return(fnKeycode(keytemp));}//---------------------------------------------------------------------------//unsigned char fnKeycode(unsigned char key) // 根据键盘映射表输出顺序键值//{switch(key){case 0x11: // 1 键//key = 0x01;break;case 0x21: // 2 键// key = 0x02;break;case 0x41: // 3 键// key = 0x03;break;case 0x81: // 4 键// key = 0x04;break;case 0x12: // 5 键// key = 0x05;break;case 0x22: // 6 键// key = 0x06;break;case 0x42: // 7 键// key = 0x07;break;case 0x82: // 8 键// key = 0x08;break;case 0x14: // 9 键// key = 0x09;break;case 0x24: // 10 键// key = 0x0A;break;case 0x44: // 11 键// key = 0x0B;break;case 0x84: // 12 键// key = 0x0C;break;case 0x18: // 13 键// key = 0x0D;break;case 0x28: // 14 键// key = 0x0E;break;case 0x48: // 15 键// key = 0x0F;break;case 0x88: // 16 键// key = 0x10;break;//以下为功能键//case 0x19: // ’’C’’ +1 键//key = 0x11;break;ca se 0x29: // ’’C’’ +2 键//key = 0x12;break;case 0x49: // ’’C’’ +3 键//key = 0x13;break;case 0x89: // ’’C’’ +4 键//key = 0x14;break;case 0x1A: // ’’C’’ +5 键// key = 0x15;break;case 0x2A: // ’’C’’ +6 键// key = 0x16;break;case 0x4A: // ’’C’’ +7 键// key = 0x17;break;case 0x8A: // ’’C’’ +8 键// key = 0x18;break;case 0x1C: // ’’C’’ +9 键//key = 0x19;break;case 0x2C: // ’’C’’ +10 键// key = 0x1A;break;case 0x4C: // ’’C’’ +11 键// key = 0x1B;break;case 0x8C: // ’’C’’ +12 键// key = 0x1C;break;// case 0x18: // ’’C’’ +13 键// // key = 0x1D;// break;case 0x38: // ’’C’’ +14 键// key = 0x1D;break;case 0x58: // ’’C’’ +15 键// key = 0x1E;break;case 0x98: // ’’C’’ +16 键// key = 0x1F;break;default : // 无键//key = 0x00;break;}return(Tab_key[key]);}矩键查寻键值44程序与显示#include <reg52.h>//#include <math.h>#include <intrins.h>#define uchar unsigned char#define TURE 1#define FALSE 0int key;int del;void Tkey(void);void led(void);/************主程序*************/void main(void){void tkey(void);void led(void);void delay(int);SCON=0x00;TI=0;while(TURE){Tkey();led();delay(2000);}}/********矩键查寻键值4*4程序******/按键为P1.0---P1.7 void Tkey(void){uchar readkey;//rereadkey;uchar x_temp,y_temp;P1=0x0f;x_temp=P1&0x0f;if(x_temp==0x0f) goto keyout;P1=0xf0;y_temp=P1&0xf0;readkey=x_temp|y_temp;readkey=~readkey;switch(readkey){case 0x11:key=0; break;case 0x21:key=1; break;case 0x41:key=2; break;case 0x81:key=3; break;case 0x12:key=4; break;case 0x22:key=5; break;case 0x42:key=6; break;case 0x82:key=7; break;case 0x14:key=8; break;case 0x24:key=9; break;case 0x44:key=10;break;case 0x84:key=11;break;case 0x18:key=12;break;case 0x28:key=13;break;case 0x48:key=14;break;case 0x88:key=15;break;default: key=16;break;}keyout:_nop_();}/************显示程序*************/void led(void){uchar code LEDValue[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0-9 uchar data num[6];uchar k;num[0]=0;num[1]=0;num[2]=0;num[3]=0;num[4]=key/10;num[5]=key-(key/10)*10;for(k=0;k<=5;k++){SBUF=LEDValue[num[5-k]];while(TI==0);TI=0;}}/************延时程序*************/void delay(del){for(del;del>0;del--);;伪定义KEYBUF EQU 30H ;键值暂存单元,查表时用;*************************************;* *;* 主程序和中断程序入口*;* *;*************************************ORG 0000H ;程序执行开始地址AJMP MAIN ;跳至MAIN执行;*************************************;* *;* 主程序*;* *;*************************************ORG 0040HMAIN: MOV P1,#0FFHMOV P3,#0FFHLCALL KEYSCAN ;主体程序。

stm32键盘扫描电路原理

stm32键盘扫描电路原理

stm32键盘扫描电路原理
STM32键盘扫描电路原理是通过使用STM32微控制器的GPIO(通用输入/输出)功能和外部硬件电路,实现对键盘的扫描和检测。

1. 首先需要将键盘的按键连接到STM32微控制器的GPIO引脚上。

可以使用矩阵排列的方式来连接多个按键。

2. 然后将STM32微控制器的GPIO设置为输入模式,需要扫描的按键对应的GPIO引脚设置为输入。

3. 在代码中,设置一个循环,依次对每一个按键进行扫描。

可以使用GPIO外部中断来触发按键的扫描。

4. 在每次扫描过程中,将某一个按键对应的GPIO引脚设置为高电平,并读取引脚的状态。

5. 如果读取到的引脚状态为高电平,则表示该按键被按下。

6. 根据读取到的按键状态,可以执行相应的操作。

需要注意的是,如果使用矩阵排列的方式连接多个按键,还需要使用GPIO引脚的输出模式来控制矩阵的行和列。

总之,STM32键盘扫描电路原理是通过STM32微控制器的GPIO和外部硬件电路,实现对键盘的扫描和检测。

实验一 矩阵键盘检测

实验一  矩阵键盘检测

实验一矩阵键盘检测一、实验目的:1、学习非编码键盘的工作原理和键盘的扫描方式。

2、学习键盘的去抖方法和键盘应用程序的设计.二、实验设备:51/AVR实验板、USB连接线、电脑三、实验原理:键盘接口电路是单片机系统设计非常重要的一环,作为人机交互界面里最常用的输入设备。

我们可以通过键盘输入数据或命令来实现简单的人机通信。

1、按键的分类一般来说,按键按照结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点式开关按键,如电气式按键,磁感应按键等。

前者造价低,后者寿命长.目前,微机系统中最常见的是触点式开关按键(如本学习板上所采用按键)。

按键按照接口原理又可分为编码键盘与非编码键盘两类,这两类键盘的主要区别是识别键符及给出相应键码的方法。

编码键盘主要是用硬件来实现对键的识别,非编码键盘主要是由软件来实现键盘的识别.全编码键盘由专门的芯片实现识键及输出相应的编码,一般还具有去抖动和多键、窜键等保护电路,这种键盘使用方便,硬件开销大,一般的小型嵌入式应用系统较少采用。

非编码键盘按连接方式可分为独立式和矩阵式两种,其它工作都主要由软件完成.由于其经济实用,较多地应用于单片机系统中(本学习板也采用非编码键盘)。

2、按键的输入原理在单片机应用系统中,通常使用机械触点式按键开关,其主要功能是把机械上的通断转换成为电气上的逻辑关系。

也就是说,它能提供标准的TTL 逻辑电平,以便与通用数字系统的逻辑电平相容。

此外,除了复位按键有专门的复位电路及专一的复位功能外,其它按键都是以开关状态来设置控制功能或输入数据。

当所设置的功能键或数字键按下时,计算机应用系统应完成该按键所设定的功能。

因此,键信息输入是与软件结构密切相关的过程。

对于一组键或一个键盘,通过接口电路与单片机相连.单片机可以采用查询或中断方式了解有无按键输入并检查是哪一个按键按下,若有键按下则跳至相应的键盘处理程序处去执行,若无键按下则继续执行其他程序。

51单片机矩阵键盘扫描程序

51单片机矩阵键盘扫描程序
void Timer0_isr(void) interrupt 1
{
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

经典的矩阵键盘扫描程序

经典的矩阵键盘扫描程序

经典的矩阵键盘扫描程序查找哪个按键被按下的方法为:一个一个地查找。

先第一行输出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,0x8e}; //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端口。

单片机之矩阵键盘

单片机之矩阵键盘

单片机之矩阵键盘下面是一个stc89c52单片机下的矩阵键盘程序,P0口接键盘,显示在P2口.#include;#define uchar unsigned char#define uint unsigned intsbit key1=P3^2;sbit key2=P3^3;uchar codetab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x 7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; //定义八个灯的工作状态。

uchar codewep[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; void yanshi(uint t){while(--t);}void main(){uchar han,lei,key;while(1){P0=0xf0; //初始化为开关状态。

11110000han=P0; //han变量读取P0口的值。

第一次扫描键盘。

han=han&0xf0; //对han变量与0xf0与.//如果结果等于P0口初值(0xf0)说明没有键被按下. //如果结果不等于P0(0xf0)口初值,说明有键按下. if(han!=0xf0)yanshi(125*5); //延时消抖.if(han!=0xf0) //语句执行到这里说明真的有键按下.{ //例如按下S1键.则P0=1110 0000lei=P0&0xf0; //lei读取P0口的值.lei=lei|0x0f; //lei=11101111P0=lei; //P0=11101111han=P0; //han=11101110 第二次扫描键盘,//因为这里按键S1还是闭合的状态。

han=han&0x0f; //han=00001110lei=lei&0xf0; //lei=11100000key=han+lei;}switch(key){case 0xee: P2=tab[0]; break; case 0xde: P2=tab[1]; break; case 0xbe: P2=tab[2]; break; case 0x7e: P2=tab[3]; break; case 0xed: P2=tab[4]; break; case 0xdd: P2=tab[5]; break; case 0xbd: P2=tab[6]; break; case 0x7d: P2=tab[7]; break; case 0xeb: P2=tab[8]; break; case 0xdb: P2=tab[9]; break; case 0xbb: P2=tab[10]; break; case 0x7b: P2=tab[11]; break; case 0xe7: P2=tab[12]; break; case 0xd7: P2=tab[13]; break; case 0xb7: P2=tab[14]; break; case 0x77: P2=tab[15]; break; }}}。

矩阵键盘扫描汇编程序

4*4矩阵键盘扫描汇编程序(基于51单片机)// 程序名称:4-4keyscan.asm;// 程序用途:4*4矩阵键盘扫描检测;// 功能描述:扫描键盘,确定按键值。

程序不支持双键同时按下,;// 如果发生双键同时按下时,程序将只识别其中先扫描的按键;// 程序入口:void;// 程序出口:KEYNAME,包含按键信息、按键有效信息、当前按键状态;//================================================================== ====PROC KEYCHKKEYNAME DATA 40H ;按键名称存储单元;(b7-b5纪录按键状态,b4位为有效位,;b3-b0纪录按键)KEYRTIME DATA 43H ;重复按键时间间隔SIGNAL DATA 50H ;提示信号时间存储单元KEY EQU P3 ;键盘接口(必须完整I/O口) KEYPL EQU P0.6 ;指示灯接口RTIME EQU 30 ;重复按键输入等待时间KEYCHK:;//=============按键检测程序========================================= ====MOV KEY,#0FH ;送扫描信号MOV A,KEY ;读按键状态CJNE A,#0FH,NEXT1 ;ACC<=0FH; CLR C ;Acc等于0FH,则CY为0,无须置0NEXT1:; SETB C ;Acc不等于0FH,则ACC必小于0 FH,;CY为1,无须置1MOV A,KEYNAMEANL KEYNAME,#1FH ;按键名称屏蔽高三位RRC A ;ACC带CY右移一位,纪录当前按键状态ANL A,#0E0H ;屏蔽低五位ORL KEYNAME,A ;保留按键状态;//=============判别按键状态,决定是否执行按键扫描=================== =====CJNE A,#0C0H,NEXT2 ;110按键稳定闭合,调用按键检测子程序SJMP KEYSCANNEXT2:CJNE A,#0E0H,NEXT3 ;111按键长闭合,重复输入允许判断SJMP WAITNEXT3:CJNE A,#0A0H,EXIT ;101干扰,当111长闭合处理ORL KEYNAME,#0E0HWAIT:MOV A,KEYRTIMEJNZ EXIT ;时间没到,退出;//=============键盘扫描程序========================================= =====KEYSCAN:MOV R1,#0 ;初始化列地址MOV R3,#11110111B ;初始化扫描码LOOP:MOV A,R3RL AMOV R3,A ;保留扫描码MOV KEY,A ;送扫描码MOV A,KEY ;读键盘ORL A,#0F0H ;屏蔽高四位CJNE A,#0FFH,NEXT31 ;A不等于FFH,说明该列有按键动作INC R1 ;列地址加1,准备扫描下一列CJNE R1,#4,LOOP ;列地址不等于4,扫描下一列SJMP EXIT ;没有按键,退出;//=============按键判断对应位等于零,说明该行有按键按下============= =====NEXT31:JB ACC.0,NEXT32MOV R2,#0 ;第0行有按键SJMP NEXT5NEXT32:JB ACC.1,NEXT33MOV R2,#1 ;第1行有按键SJMP NEXT5NEXT33:JB ACC.2,NEXT34MOV R2,#2 ;第2行有按键SJMP NEXT5NEXT34:MOV R2,#3 ;第3行有按键NEXT5: ;计算按键地址MOV A,R1RL ARL A ;列地址乘4(每列对应4行)ADD A,R2 ;加行地址MOV DPTR,#KEYTABMOVC A,@A+DPTRANL KEYNAME,#0E0HORL KEYNAME,A ;送按键(送值的时候已经置按键有效)MOV KEYRTIME,#RTIME ;送重复按键等待时间CLR KEYPL ;打开指示灯MOV SIGNAL,#10 ;送信号提示时间(每次按键闪10 0ms)EXIT:MOV KEY,#0FFH ;置键盘接口高电平RET ;退出;//=============按键名称表=========================================== =====KEYTAB:DB 1AH ;扫描码0,对应A ************************************ ******DB 1BH ;扫描码1,对应B ** **DB 1CH ;扫描码2,对应C ** I/O口 PX.4 PX.5 PX.6 PX.7 **DB 1DH ;扫描码3,对应D ** **DB 11H ;扫描码4,对应1 ** PX.0 A(0) 1(4) 2(8) 3 (C) **DB 14H ;扫描码5,对应4 ** **DB 17H ;扫描码6,对应7 ** PX.1 B(1) 4(5) 5(9) 6 (D) **DB 1EH ;扫描码7,对应E ** **DB 12H ;扫描码8,对应2 ** PX.2 C(2) 7(6) 8(A) 9 (E) **DB 15H ;扫描码9,对应5 ** **DB 18H ;扫描码A,对应8 ** PX.3 D(3) E(7) 0(B) F(F) **DB 10H ;扫描码B,对应0 ** **DB 13H ;扫描码C,对应3 ************************************ ******DB 16H ;扫描码D,对应6DB 19H ;扫描码E,对应9DB 1FH ;扫描码F,对应FEND第二种解法ORG 0000HSTART: MOV R0,#00H ;初始化程序,开始的延时是为了使硬件能够准备好DJNZ R0,$LOOP: MOV SP,#60HCALL KEYDISPLAY:MOV A,R4MOV DPTR,#TABLE ;定义字形表的起始地址MOVC A,@A+DPTR ;TABLE为表的起始地址MOV P2,ASJMP LOOP;子程序内容,P1口的低四位为行线,高四位为列线KEY: PUSH PSWPUSH ACCMOV P1,#0F0H ;令所有的行为低电平,全扫描字-P1.0-P1.3,列为输入方式;这一段只是验证有键按下,并不能判断是哪一行MOV R7,#0FFH ;设置计数常数,作为延时KEY1: DJNZ R7, KEY1MOV A,P1 ;读取P1口的列值ANL A,#0F0H ;判别有键值按下吗(当有键按下时,P1口的高四位就不全为1了,底四位还是都为0的);这个地方进行相或的原因,是因为要把底四位的0000变成1111,以便下一步进行求反ORL A,#0FH //这个地方原版上没有,这是又加了,如果不加的的话,是不对的********CPL A ;求反后,有高电平就有键按下JZ EKEY;累加器为0则转移(意为求反后本来全为0的,如果有键按下时,求反后高四位就有1了),退出LCALL DEL20ms ;有键按下,进行处理;下面进行行行扫描,1行1行扫SKEY: MOV A,#00HMOV R0,A ;R0作为行计数器,开始初值为0MOV R1,A ;R1作为列计数器,开始初值为0MOV R2,#0FEH ;R2作为扫描暂存字,开始初值为1111 1110,(第四位作为行扫描字)SKEY2: MOV A,R2MOV P1,A ;输出行扫描字,1111 1110NOPNOPNOP ;3个NOP操作使P1口输出稳定MOV A,P1 ;读列值(和开始一样)MOV R1,A ;暂存列值(第一次为**** 1110,既高四位有一位"可能"会为0)ANL A,#0F0H ;取高四位,ORL A,#0FH ;使第四位全部置1CPL ABIAOZHI:JNZ SKEY3 ;累加器为非0则转移指令(意思是判断到按键在这一行),转去处理INC R0 ;如果按键没在这一行,行计数器加1SETB C ;进位标志位加1,为了在左移的时候开始的低位0不在出现在低(循环一圈后)MOV A,R2RLC A ;带进位左移1位(形成下一行扫描字,再次扫描)MOV R2,AMOV A,R0;把加1后的行计数器R0和总共扫描次数(4次比较)CJNE A,#04H,SKEY2 ;(扫描完了么)书本上这个地方也有错误,书本上写的是:SKEY1AJMP EKEY ;如果没有的话,退出;有键按下后行扫描过后,此为确列行SKEY3: MOV A,R1 ;JNB ACC.4,SKEY5 ;直接寻址位为0咋转移指令JNB ACC.5,SKEY6JNB ACC.6,SKEY7JNB ACC.7,SKEY8AJMP EKEY //我自己感觉到这命令没有用处SKEY5: MOV A,#00H ;存0列号MOV R3,AAJMP DKEYSKEY6: MOV A,#01H ;存1列号MOV R3,AAJMP DKEYSKEY7: MOV A,#02H ;存2列号MOV R3,AAJMP DKEYSKEY8: MOV A,#03H ;存3列号MOV R3,AAJMP DKEY;取出具体的行号,再加上列号,最终确认按键的号码DKEY: //MOV R4,#00HMOV A,R0MOV B,#04HMUL AB ;让行号*4,第四位放在A中(总共就4行,相乘后一定<16,也就是只有第四位有值)ADD A,R3 ;让行号和列号相加,最终确认任按键的具体号MOV R4,AEKEY: POP ACCPOP PSWRET ;按键扫描处理函数DEL20ms:MOV R7,#2DL2: MOV R6,#18DL1: MOV R5,#255DJNZ R5,$DJNZ R6,DL1DJNZ R7,DL2RET;此为共阴极数码管的数字表TABLE: DB 3FH ;0DB 06H ;1DB 5BH ;2DB 4FH ;3DB 66H ;4DB 6DH ;5DB 7DH ;6DB 27H ;7DB 7FH ;8DB 6FH ;9DB 77HDB 7CHDB 39HDB 5EHDB 79HDB 71HEND第三种PIC单片机键盘扫描汇编程序;本程序用于PIC外接键盘的识别,通过汇编程序,使按下K1键时第一个数码管显示1,按下K2键时第一;个数码管上显示2,按下K3键时第一个数码管上显示3,按下K4键时第一个数码管上显示4,;汇编程序对键盘的扫描采用查询方式LIST P=18F458INCLUDE "P18F458.INC";所用的寄存器JIANR EQU 0X20FLAG EQU JIANR+1 ;标志寄存器DEYH EQU JIANR+2DEYL EQU JIANR+3F0 EQU 0 ;FLAG的第0位定义为F0ORG 0X00GOTO MAINORG 0X30;*************以下为键盘码值转换表****************** CONVERT ADDWF PCL,1RETLW 0XC0 ;0,显示段码与具体的硬件连接有关RETLW 0XF9 ;1RETLW 0XA4 ;2RETLW 0XB0 ;3RETLW 0X99 ;4RETLW 0X92 ;5RETLW 0X82 ;6RETLW 0XD8 ;7RETLW 0X80 ;8RETLW 0X90 ;9RETLW 0X88 ;ARETLW 0X83 ;BRETLW 0XC6 ;CRETLW 0XA1 ;DRETLW 0X86 ;ERETLW 0X8E ;FRETLW 0X7F ;"."RETLW 0XBF ;"-"RETLW 0X89 ;HRETLW 0XFF ;DARKRETURN;***************PIC键盘扫描汇编程序初始化子程序***************** INITIALBCF TRISA,5 ;置RA5为输出方式,以输出锁存信号BCF TRISB,1BCF TRISA,3BCF TRISE,0BCF TRISE,1BSF TRISB,4 ;设置与键盘有关的各口的输入输出方式BCF TRISC,5BCF TRISC,3 ;设置SCK与SDO为输出方式BCF INTCON,GIE ;关闭所有中断LW 0XC0WF SSPSTAT ;设置SSPSTAT寄存器LW 0X30WF SSPCON1 ;设置SPI的控制方式,允许SSP方式,并且时钟下降;沿发送数据,与"74HC595当其SCLK从低到高电平;跳变时,串行输入数据(DI)移入寄存器"的特点相对应LW 0X01WF JIANR ;显示值寄存器(复用为键值寄存器)赋初值CLRF FLAG ;清除标志寄存器RETURN ;返回;**************显示子程序*****************DISPLAYCLRF PORTAWF SSPBUFAGAINBTFSS PIR1,SSPIFGOTO AGAINNOPBCF PIR1,SSPIFBSF PORTA,5 ;详细的程序语句请参考 pic教程语句部分,可在首页搜索。

单片机矩阵键盘扫描的两种方式

单片机矩阵键盘扫描的两种方式单片机矩阵键盘扫描的两种方式矩阵键盘扫描方式:第一种:逐行扫描法,就是一行一行的扫描。

实现代码如下(键盘连接P2口):#define NO_KEY 0XFF#define KEY_LO() P2 &= 0XF0#define KEY_HI() P2 |= 0X0F#define KEY_L(i) P2 &= ~(1<<i)#define KEY_RD() ((P2>>4) & 0x0f)UINT8 OnceKey(void){UINT8 line = 0;UINT8 key = NO_KEY;//key valueKEY_LO();if (KEY_RD() == 0X0F){KEY_HI();return NO_KEY;}for (line=0; line<4; line ++){KEY_HI();KEY_L(line);key = KEY_RD();switch (key){case ROW_FIRST:key = 4*line + 0;break;case ROW_SECOND:key = 4*line + 1;break;case ROW_THIRD:key = 4*line + 2;break;case ROW_FOURTH:key = 4*line +3;break;default :key = 0x0f;break;}if (key < 0x10){return key;}}return NO_KEY;}第二种,线性反转法。

就是行和列分别读出。

实现代码如下:#define CVT(i) ((i)==(~1)&0x0f)? 0: ((i)==(~2)&0x0f)? 1: ((i)==(~4)&0x0f)? 2: ((i)==(~8)&0x0f)? 3: 4;#define KEY0_3HI() P2 |= 0X0F#define KEY0_3LO() P2 &= 0XF0#define KEY4_7HI() P2 |= 0XF0#define KEY4_7LO() P2 &= 0X0F#define KEY0_3RD() (P2 & 0X0F)#define KEY4_7RF() ((P2>>4) & 0X0F)UINT8 OnceKey(void){UINT8 line = NO_KEY;UINT8 row = NO_KEY;UINT8 key;KEY0_3HI();KEY4_7LO();line = KEY0_3RD();//读入行的值if (0x0f == line){key = NO_KEY;}else{KEY0_3LO();KEY4_7HI();row = KEY4_7RD();//读入列的值if (0x0f == row){key = NO_KEY;}else{key = CVT(line)*4 + CVT(row);}}KEY0_3HI();KEY4_7HI();return key; }。

单片机矩阵按键课程设计

单片机矩阵按键课程设计一、课程目标知识目标:1. 学生能理解单片机矩阵按键的基础知识,掌握矩阵按键的原理及其在电路中的应用。

2. 学生能描述单片机I/O口操作方法,并运用此知识实现矩阵按键的编程控制。

3. 学生能解释并运用行、列扫描法进行按键识别,实现按键的消抖处理。

技能目标:1. 学生能够独立完成矩阵按键电路的连接,并进行调试。

2. 学生能够运用所学知识,编写程序实现矩阵按键的扫描与功能分配。

3. 学生能够通过实验,分析和解决矩阵按键编程过程中遇到的问题。

情感态度价值观目标:1. 学生培养对单片机技术的兴趣,增强对电子工程领域的认识。

2. 学生在学习过程中,培养解决问题的耐心和毅力,树立团队协作意识。

3. 学生能够认识到单片机技术在现实生活中的应用价值,增强创新实践能力。

课程性质:本课程为实践性较强的电子技术课程,要求学生在掌握理论知识的基础上,注重动手实践。

学生特点:学生具备一定的单片机基础知识,对电子技术有较高的兴趣,但编程和动手能力参差不齐。

教学要求:结合学生特点,课程注重理论与实践相结合,充分调动学生的积极性,提高学生的动手能力和创新能力。

通过课程学习,使学生在知识、技能和情感态度价值观方面均有所提升。

二、教学内容1. 矩阵按键原理:介绍矩阵按键的电路结构、工作原理以及其在单片机系统中的应用。

- 教材章节:第二章第二节《矩阵键盘的工作原理》2. 单片机I/O口操作:回顾并加深理解单片机I/O口的基本操作,为矩阵按键编程打下基础。

- 教材章节:第一章《单片机基础》3. 行列扫描法:讲解如何运用行列扫描法进行按键识别,包括消抖处理方法。

- 教材章节:第二章第三节《矩阵键盘的编程方法》4. 矩阵按键编程实践:指导学生编写程序,实现矩阵按键的扫描与功能分配。

- 教材章节:第二章第四节《矩阵键盘应用实例》5. 电路连接与调试:学生动手实践,完成矩阵按键电路的连接,并进行调试。

- 教材章节:实验指导书《矩阵键盘实验》6. 问题分析与解决:针对编程和调试过程中遇到的问题,引导学生进行分析和解决。

单片机矩阵键盘

单片机矩阵键盘
汇报人: 202X-01-04
contents
目录
• 单片机矩阵键盘概述 • 单片机矩阵键盘硬件设计 • 单片机矩阵键盘软件编程 • 单片机矩阵键盘调试与测试 • 单片机矩阵键盘优化与扩展
01 单片机矩阵键盘 概述
定义与特点
定义
单片机矩阵键盘是一种由行线和 列线组成的键盘,通过按键的行 和列交叉点来识别按键。
用于显示输入的信息或状态, 如数码管、液晶显示屏等。
电源模块
为整个系统提供稳定的电源, 保证系统的正常工作。
电路连接
01
矩阵键盘的行线和列线分别连接到单片机的输入/输出端口,通 过软件扫描方式检测按键状态。
02
单片机控制模块与显示模块连接,将需要显示的信息传输给显
示模块。
电源模块为整个系统提供稳定的电源,保证系统的正常工作。
在通讯设备领域,单片机矩阵键盘可以用 于手机、电话等设备的操作面板,实现拨 号、挂断等功能。
பைடு நூலகம்
02 单片机矩阵键盘 硬件设计
硬件组成
01
02
03
04
矩阵键盘模块
由行线和列线组成的键盘矩阵 ,按键被安排在行线和列线的
交叉点上。
单片机控制模块
用于接收和处理来自矩阵键盘 的信号,控制整个系统的运行

显示模块
软件编程
编写单片机程序,用于扫描矩阵键盘并识 别按键按下事件。
测试方法
按键响应时间测试
测试从按键按下到单片机响应 的时间,确保在合理范围内。
按键防抖测试
测试按键防抖功能是否正常, 即在按键按下和释放时是否能 够正确识别。
多键同时按下测试
测试在多个按键同时按下时, 单片机是否能够正确识别并处 理。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a,b=0;
if(hang == 1) a = 0x80;
{
P1 = Buffer[j];
temp = 0x10;
for(i=0; i<4; i++)
{
if(!(P1 & temp))
{
x= i+j*4;
switch(x)
{ case 0:return 1; break;
case 1:return 2; break;
case 2:return 3;break;
uint keyflag ; //键盘正在读取标志位,如果Keyflag为1,表示正在读取键盘,停止其他功能;
char x,y,m,n,c;
//Keyflag为0,读取键盘结束,恢复其他功能
char flag1=0;
//频率范围10~1000Hz
uchar Hrate = 0;//一个周期内高点平占据时间
E = 0;
delay();
P0 = del;
delay();
E = 1;
delay();
E = 0;
}
/********************************************************************
*名称: L1602_init()
*功能: 1602初始化,请参考16பைடு நூலகம்2的资料
bit Busy(void)
{
bit busy_flag = 0;
RS = 0;
RW = 1;
E = 1;
delay();
busy_flag = (bit)(P0 & 0x80);
E = 0;
return busy_flag;
}
/********************************************************************
*名称: getKeyNum()
*功能:读取一个键码值
*输入:无
*输出:无
***********************************************************************/
void getKeyNum()
{
//不停的检查有无键盘按下,若按下,则开始进行下面的操作。
*名称: L1602_char(uchar hang,uchar lie,char sign)
*功能:改变液晶中某位的值,如果要让第一行,第五个字符显示"b",调用该函数如下
L1602_char(1,5,'b')
*输入:行,列,需要输入1602的数据
*输出:无
***********************************************************************/
*名称: L1602_string(uchar hang,uchar lie,uchar *p)
*功能:改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef",调用该函数如下
L1602_string(1,5,"ab cd ef;")
*输入:行,列,需要输入1602的数据
*输出:无
}
/********************************************************************
*名称: bit Busy(void)
*功能:这个是一个读状态函数,读出函数是否处在忙状态
*输入:输入的命令值
*输出:无
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
wcmd(a);
wdata(sign);
}
/********************************************************************
uchar Lrate = 0;//一个周期内低电平占据时间
uint FREQ0; //定时器T0的计数变量//
uint FREQ1; //定时器T1的计数变量//
sbit P2_1=P2^0; //设置P2.1,作为信号输出口//
uint disbuf[3];
uint figure=0;
int sum2=0;
for(x=0;x<=148;x++);
}
/********************************************************************
*名称: Keyscan()
*功能:实现按键的读取。下面这个子程序是按处理矩阵键盘的基本方法处理的。
*输入:无
*输出:按键值
}
if(x<10)
{y=x+0x30;
L1602_char(1,11,' ');
L1602_char(1,12,y);
}
else
{
m=x/10+0x30;
n=x%10+0x30;
L1602_char(1,11,m) ;
L1602_char(1,12,n) ;
}
return x;
}
}
}
}
/*******************************************************************
*输入:无
*输出:无
***********************************************************************/
void L1602_init(void)
{
wcmd(0x38);
wcmd(0x0c);
wcmd(0x06);
wcmd(0x01);
}
/********************************************************************
*功能: 1602写数据函数
*输入:需要写入1602的数据
*输出:无
***********************************************************************/
void wdata(uchar del)
{
while(Busy());
RS = 1;
RW = 0;
RS = 0;
RW = 0;
E = 0;
delay();
P0 = del;
delay();
E = 1;
delay();
E = 0;
}
/********************************************************************
*名称: wdata(uchar del)
***********************************************************************/
uchar Keyscan(void)
{
uchar i,j,x, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};
for(j=0; j<4; j++)
*功能:延时,延时时间大概为5US。
*输入:无
*输出:无
***********************************************************************/
void delay()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
uchar ReadKey()
{
while(1)
{
P1 = 0xf0;
if(P1 != 0xf0)
{
Delay_1ms(20);//按键消抖
if(P1 != 0xf0)
{
Delay_1ms(20);//按键消抖
if(P1 != 0xf0)
{
x= Keyscan();
P1=0xf0;
while(P1!=0xf0) {;}
case 10:return 9;break;
case 11:return 15;break;
case 13:return 0;break;
default:return 18;
}
}
temp <<= 1;
}
}
}
/*****************************************************************/
*名称: wcmd(uchar del)
*功能: 1602命令函数
*输入:输入的命令值
*输出:无
***********************************************************************/
相关文档
最新文档