单片机按键扫描通用程序(绝对原创)
单片机控制的矩阵键盘扫描程序集
单片机控制的矩阵键盘扫描程序集各种各样的矩阵键盘扫描程序集矩阵键盘的扫描对初学者来说是不可避免的,然而也相对来说有点难度.鉴于此,我整理了一下,我所遇到的矩阵键盘扫描程序集,将相继贴上来,供大家参考! 说明:这些大多都是网上转贴来的,其所有权归原作者!谢谢合作.最简单矩阵键盘扫描程序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 ;主体程序。
51单片机矩阵键盘行扫描
51单⽚机矩阵键盘⾏扫描————————————————————————————————————————————分类:按结构原理分:触点式开关按键⽆触点开关按键接⼊⽅式独⽴式按键矩阵式键盘————————————————————————————————————————————矩阵式键盘识别⽅法(⾏扫描法)检测列线的状态:列线Y4~Y7置⾼电平,⾏线Y0~Y3置低电平。
只要有⼀列的电平为低,则表⽰键盘该列有⼀个或多个按键被按下。
若所有列线全为⾼电平,则键盘中⽆按键按下。
判断闭合按键所在的位置:⾏线置⾼电平,列线置低电平。
检测⾏线的状态。
举例:当按下第⼀⾏第⼀列的按键时⾏扫描,⾏线为低电平,列线为⾼电平,得到 1110 0000列扫描,⾏线为⾼电平,列线为低电平,得到 0000 1110将得到的结果进⾏或运算,得到 1110 1110,对应第⼀⾏第⼀列,⼗六进制为0xEE按键表⾏列bin hex111110 11100xEE121101 11100xDE131011 11100xBE140111 11100x7E211110 11010xED221101 11010xDD231011 11010xBD240111 11010x7D311110 10110xEB321101 10110xDB331011 10110xBB340111 10110x7B411110 01110xE7421101 01110xD7431011 01110xB7440111 01110x77————————————————————————————————————————————矩阵式键盘应⽤实例实现结果:通过4*4矩阵键盘对应数码管显⽰0~F设计思路:当检测到按键被按下时,将此时⾏扫描的结果存⼊临时变量,再进⾏列扫描,得到的结果和临时变量进⾏或运算。
通过数组存放按键和数码管编码,⾏列扫描得到结果后遍历数组,找到对应的编码位置并显⽰数码管编码实现代码:1 #include <reg52.h>2 typedef unsigned char uchar;3 typedef unsigned int uint;4 uchar code KEY_TABLE[] =5 {60xEE, 0xDE, 0xBE, 0x7E,70xED, 0xDD, 0xBD, 0x7D,80xEB, 0xDB, 0xBB, 0x7B,90xE7, 0xD7, 0xB7, 0x7710 };11 uchar code TABLE[] =12 {130x3F, 0x06, 0x5B, 0x4F,140x66, 0x6D, 0x7D, 0x07,150x7F, 0x6F, 0x77, 0x7C,160x39, 0x5E, 0x79, 0x71,17 };18void Delay(uchar m)19 {20 --m;21 }22void main()23 {24 uchar temp, key, i;25while(1)26 {27 P3 = 0xF0;28if (P3 != 0xF0)29 {30 Delay(2000);31if (P3 != 0xF0)32 {33 temp = P3;34 P3 = 0x0F;35 key = temp | P3;36for (i = 0; i < 16; ++i)37if (key == KEY_TABLE[i])38break;39 P2 = TABLE[i];40 }41 }42 }43 }。
单片机实验--键盘扫描
实验4 键盘实验一、实验目的:1.掌握8255A编程原理。
2.了解键盘电路的工作原理。
3.掌握键盘接口电路的编程方法。
二、实验设备:CPU挂箱、8031CPU模块三、实验原理:1.识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如所读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
本实验例程采用的是行反转法。
行反转法识别键闭合时,要将行线接一并行口,先让它工作于输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口往各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上的输入值,那么,在闭合键所在的行线上的值必定为0。
这样,当一个键被按下时,必定可以读得一对唯一的行线值和列线值。
2.程序设计时,要学会灵活地对8255A的各端口进行方式设置。
3.程序设计时,可将各键对应的键值(行线值、列线值)放在一个表中,将要显示的0~F字符放在另一个表中,通过查表来确定按下的是哪一个键并正确显示出来。
实验题目利用实验箱上的8255A可编程并行接口芯片和矩阵键盘,编写程序,做到在键盘上每按一个数字键(0~F),用发光二极管将该代码显示出来。
四、实验步骤:将键盘RL10~RL17接8255A的PB0~PB7;KA10~KA12接8255A的PA0~PA2;PC0~PC7接发光二极管的L1~L8;8255A芯片的片选信号8255CS接CS0。
五、实验电路:六、程序框图7.程序清单八、附:8251/8255扩展模块该模块由8251可编程串行口电路和8255可编程并行口电路两部分组成,其电源、数据总线、地址总线和片选信号均由接口挂箱上的接口插座提供。
一、8251可编程串行口电路(1)8251可编程串行接口芯片引脚及功能8251A是通用同步/异步收发器USART,适合作异步起止式数据格式和同步面向字符数据格式的接口,其功能很强。
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)扫描过程接着,通过编写程序实现键盘的扫描过程。
简单的按键扫描&读取程序
/*GPIOA的置位复位定义*/
#define PA0_BSRR (*(uint32_t *)0x42010a00)
#define PA1_BSRR (*(uint32_t *)0x42010a04)
//
char get_key_riseedge(char keynum)
{
char val;
u32 mid = 0;
val = (key_riseedge >> keynum) & 0x01;//将该位上升沿取出送到val
mid = ~( 1 << keynum );
key_riseedge &= mid;//该上升沿清零
key_falledge &= ~(redge);//同上
key_riseedge |= redge;//将上升沿取到寄存器中待读
key_falledge |= fedge;//同上
}
//别的函数查询某个键的键值=========================================
#define PA3_OUT (*(uint32_t *)0x4221018c)
#define PA4_OUT (*(uint32_t *)0x42210190)
#define PA5_OUT (*(uint32_t *)0x42210194)
#define PA6_OUT (*(uint32_t *)0x42210198)
//
char get_key_val(char keynum)
PIC单片机键盘扫描汇编程序
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;*************以下为键盘码值转换表******************CONVERTADDWF PCL,1RETLW 0XC0 ;0,显示段码与具体的硬件连接有关RETLW0XF9 ;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 ;HRETLW0XFF ;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 ;关闭所有中断MOVLW 0XC0MOVWF SSPSTAT ;设置SSPSTAT 寄存器MOVLW0X30MOVWF SSPCON1 ;设置SPI 的控制方式,允许SSP 方式,并且时钟下降;沿发送数据,与”74HC595当其SCLK 从低到高电平;跳变时,串行输入数据(DI)移入寄存器”的特点相对应MOVLW 0X01 MOVWF JIANR ;显示值寄存器(复用为键值寄存器)赋初值CLRF FLAG ;清除标志寄存器RETURN ;返回;。
单片机实验--键盘扫描
实验4 键盘实验一、实验目的:1.掌握8255A编程原理。
2.了解键盘电路的工作原理。
3.掌握键盘接口电路的编程方法。
二、实验设备:CPU挂箱、8031CPU模块三、实验原理:1.识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如所读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
本实验例程采用的是行反转法。
行反转法识别键闭合时,要将行线接一并行口,先让它工作于输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口往各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上的输入值,那么,在闭合键所在的行线上的值必定为0。
这样,当一个键被按下时,必定可以读得一对唯一的行线值和列线值。
2.程序设计时,要学会灵活地对8255A的各端口进行方式设置。
3.程序设计时,可将各键对应的键值(行线值、列线值)放在一个表中,将要显示的0~F字符放在另一个表中,通过查表来确定按下的是哪一个键并正确显示出来。
实验题目利用实验箱上的8255A可编程并行接口芯片和矩阵键盘,编写程序,做到在键盘上每按一个数字键(0~F),用发光二极管将该代码显示出来。
四、实验步骤:将键盘RL10~RL17接8255A的PB0~PB7;KA10~KA12接8255A的PA0~PA2;PC0~PC7接发光二极管的L1~L8;8255A芯片的片选信号8255CS接CS0。
五、实验电路:六、程序框图7.程序清单八、附:8251/8255扩展模块该模块由8251可编程串行口电路和8255可编程并行口电路两部分组成,其电源、数据总线、地址总线和片选信号均由接口挂箱上的接口插座提供。
一、8251可编程串行口电路(1)8251可编程串行接口芯片引脚及功能8251A是通用同步/异步收发器USART,适合作异步起止式数据格式和同步面向字符数据格式的接口,其功能很强。
PIC单片机键盘扫描程序
//3*3键盘扫描程序,键盘为3个行上拉电阻,扫描函数完全自主知识产权//数码管扫描函数据说是华为的程序员编写的,本人稍加改动#include <pic.h>#define uchar unsigned char#define uint unsigned int__CONFIG(PWRTDIS&HS&WDTDIS&LVPDIS&BORDIS);const uchar table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//共阴极数码管段表const uchar keycode[9][2]={{0x1E,1},{0x2E,2},{0x36,3},{0x1D,4}, {0x2D,5},{0x35,6},{0x1B,7},{0x2B,8},{0x33,9}};//矩阵键盘键值码void delayms(uint delay){uint i;for(;delay>0;delay--)for(i=0;i<453;i++);}void init(){ADCON1=0x8E;TRISD=0x00;TRISA&=0xE1;PORTD=0x00;PORTA=0x00;}uchar scankey(){uchar key3H,key3L,scancode;TRISB=0x38;//高3位置为输入,低3位为输出PORTB=0x00;//低3位输出低电平key3H=PORTB;//读取D口状态key3H=PORTB&0x38;if(key3H!=0x38){key3H=PORTB;delayms(5);if(key3H!=0x38){TRISB=0x07;//低3位输入,高3位输出PORTB=0x00;//高3位输出低电平key3L=PORTB;key3L=PORTB&0x07;if(key3L!=0x07){scancode=key3H|key3L;while(PORTB!=0x07);//等待按键松开return(scancode);}}}elsereturn(0xFF);}uchar getvalue(){uchar myvalue=0,i=0;myvalue=scankey();if(myvalue!=0xFF){while(myvalue!=keycode[i][0])i++;return(keycode[i][1]);}elsereturn(0xFF);}void display(uchar data){uchar i,j,k,num[5]={0,0,0,0,0};num[1]=data/1000;//千位num[2]=(data%1000)/100;//百位num[3]=data%100/10;//十位num[4]=data%10;//十位for(i=0;i<10;i++){PORTA=~(0x02);k=0x02;for(j=1;j<=4;j++){PORTA=~k;PORTD=table[num[j]];delayms(2);k=k<<1;}}}void main(){uchar mynum=0,i=0;init();//初始化while(1){i=getvalue();if(i!=0xFF)mynum=i;display(mynum);}}。
单片机经典长短按程序
新型的按键扫描程序不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。
我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为C语言强大的可移植性。
同时,这里面用到了一些分层的思想,在单片机当中也是相当有用的,也是本文的另外一个重点。
对于老鸟,我建议直接看那两个表达式,然后自己想想就会懂的了,也不需要听我后面的自吹自擂了,我可没有班门弄斧的意思,hoho~~但是对于新手,我建议将全文看完。
因为这是实际项目中总结出来的经验,学校里面学不到的东西。
以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。
当然,我自己也是在多个项目用过,效果非常好的。
好了,工程人员的习惯,废话就应该少说,开始吧。
以下我以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。
用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。
核心算法:unsigned char Trg;unsigned char Cont;void KeyRead( void ){unsigned char ReadData = PINB^0xff; // 1Trg = ReadData & (ReadData ^ Cont); // 2Cont = ReadData; // 3}完了。
有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!!下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。
1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。
2:算法1,用来计算触发变量的。
一个位与操作,一个异或操作,我想学过C 语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。
单片机按键扫描程序
case 3:y=14;break;
case 4:y=4; break;
case 5:y=5; break;
case 6:y=6; break;
case 7:y=13;break;
case 8:y=1; break;
case 9:y=2; break;
for(j=0; j<4; j++)
{
if(!(P3 & temp))//判断P1口高4位某一行为低电平
x=i+j*4;//使用中间变量X
temp <<= 1;
}
}
}
}
if(P3!=0xf0) goto dingwei;//判断是否松开按键,防止重复赋值
switch(x)
{
case 0:y=7; break;
int aa[]={0xf7,0xfb,0xfd,0xfe,};
dingwei:
P3=0xf0;
if(P3!=0xf0)//判断是否有输入
{
delay(5);//防抖(延时10ms)
if(P3!=0xf0)//再判断是否有输入
{
for(i=0; i<4; i++)
{
P3 = aa[i];
temp=0x10;
}//符号点+-*/=分别为10,11,12,13,14,15。
case 10:y=3;break;
case 11:y=12;break;
case 12:y=10;break;
case 13:y=0; break;
case 14:y=15;break;
case 15:y=11;break;
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);//返回按键号}/************************************************************************* 未按键时,扫描线一直变化。
单片机按键扫描数码管显示C语言程序
单片机按键扫描数码管显示C语言程序按键扫描数码管显示程序共定义了6个键的功能:K1、K2、K3、K4以及K5、K8组成的一对复合键,其中K2,K3为连击键,K5为上档键。
在正常工作模式下按K1则切换至状态,在设定模式下按K1键循环选择4个数码管中的某个,被选中的数码管闪烁,此时单按K2键显示数值加1;常按K2显示数值以一定速度递增,同时数码管停止闪烁,当K2松开,数码管恢复闪烁,显示数值停留在K2松开前的值上。
K3完成的功能和K2类似。
其完成减操作。
这2个键只有在设定状态才有效,可以有效防止误操作。
K4为确认键,按下该键回到正常显示状态,所有指示灯熄灭,数码管显示刚刚设定的数值。
K5+K8这对复合键执行复位操作,任何情况下同时按下K5和K8或先按下K5再按下K8,所有数码管的显示全为0,指示灯全灭,进入正常显示状态。
同时程序还对如下几个异常操作进行了处理:1. 2个或多个功能键同时按下2. 一个功能键按下未释放,又按另一个功能键,然后再松开其中一个功能键3. 先按下功能键再按下上档键4. 多个上档键和一个功能键同时按下,此时不做处理。
等到松开其他上档键,只剩下一个上5. 档键和一个功能键时才执行这对复合键;或松开所有上档键,处理单一功能键。
/****************************************************************************** */#include <iom8v.h>#include <macros.h>#define uchar unsigned char#define uint unsigned int#define RCtrl 0x20 //定义上挡键第5键#define RConti 0xfe //定义连击键第6键#define N 2 //去抖年龄下限#define MaxRate 50 //重复前的延迟值 600ms#define MinRate 20 //重复速度 240ms#define leddark 83 //闪烁时灭时间1s#define ledshow 83 //闪烁时亮时间1s#define decimal 0x80 //小数点的段数#define KEY_DDR DDRC#define KEY_PORTO PORTC#define KEY_PORTI PINC#define OUT 0x3f#define IN 0xc0#define KeyValue 0x3f#define LEDD_DDR DDRB#define LEDD_PORTO PORTB#define LEDS_DDR DDRD#define LEDS_PORTO PORTD#define LEDS_MASK 0xfc#define LEDS_NUM 0x06#define TRUE 1#define FALSE 0/*定义键盘扫描程序返回数据类型*/typedef struct{uchar shiftcnt; //上档键的个数值uchar funcnt; //功能键的个数值uchar shiftval; //最后扫描到的上档键的值uchar funval; //最后扫描到的功能键的值} keyret;/*定义显示字符段码*/uchar const led_stroke[19] ={//0,1,2,3,4,5,6,7,8,90x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,//a,b,C,d,e,F,P,0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x73,//all on all off0xff, 0x00};/*定义位选码*/uchar const led_cs[LEDS_NUM] ={0xfb, //111110110xf7, //111101110xef, //111011110xdf, //110111110xbf, //101111110x7f //01111111};uchar led_buf[LEDS_NUM] ={0x73, 0x81, 0x82, 0x83, 0x84,0x85};uchar *pb = &led_buf[1]; //定义指向数码管数据缓冲区的指针/*定义全局变量*/uchar task, state; //task:按键状态,0:去抖 1,重复的延迟 2,重复//state:显示位置变量uchar keydone, keyprocess; //keydone: 按键任务完成标志,为1表示已完成//keyprocess: 按键有效标志,为1时表示对按键执行uchar keypre[2] ={0x00, 0x00}; //存放上次功能键和上档键的键值//keypre0存放功能键uchar blink, ledtime; //blink:闪烁控制寄存器,某位为1时闪烁//d7d6d5d4d3d2d1d0//xxxx1111//ledtime:累计闪烁时已点亮和已熄灭的时间uchar ledtask; //ledtask: 当前的闪烁状态,0代表亮uchar keymark; //keymark:只是当前工作状态,为1时处于设定状态,为0时正常工作uchar enflash; //enflash:闪烁使能标志,1闪烁#define shut_dis() LEDS_PORTO|=LEDS_MASK; //shut display/****************************************************************************** **函数原型: uchar _crol_(uchar data,uchar shiftbit);*功能:字节左移shiftbit*参数:*说明:****************************************************************************** */uchar _crol_(uchar data,uchar shiftbit){data &=0xff;if(shiftbit>8)return 0;return ((~data)<<shiftbit);}/****************************************************************************** **函数原型: uchar _cror_(uchar data,uchar shiftbit);*功能:字节右移shiftbit*参数:*说明:****************************************************************************** */uchar _cror_(uchar data,uchar shiftbit){data &=0xff;if(shiftbit>8)return 0;return ((~data)>>shiftbit);}/****************************************************************************** **函数原型: void send_shift(uchar d);*功能: 将显示数据由B口送出****************************************************************************** */void send_shift(uchar data){LEDD_PORTO = data;}/****************************************************************************** **函数原型: void lflash();*功能:闪烁处理。
单片机部队式键盘扫描程序
单片机部队式键盘扫描程序单片机部队式键盘扫描程序一、部队扫描法矩阵式键盘的构造与作业原理:在键盘中按键数量较多时,为了削减I/O口的占用,一般将按键摆放成矩阵方法,如图1所示。
在矩阵式键盘中,每条水平线和笔直线在穿插处不直接连通,而是通过一个按键加以联接。
这么,一个端口(如P1口)就能够构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,并且线数越多,差异越显着,比方再多加一条线就能够构成20键的键盘,而直接用端口线则只能多出一键(9键)。
由此可见,在需求的键数比照多时,选用矩阵法来做键盘是合理的。
矩阵式构造的键盘显着比直接法要杂乱一些,辨认也要杂乱一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O 口作为输出端,而列线所接的I/O口则作为输入。
这么,当按键没有按下时,悉数的输出端都是高电平,代表无键按下。
行线输出是低电平,一旦有键按下,则输入线就会被拉低,这么,通过读入输入线的情况就可得知是不是有键按下了。
详细的辨认及编程方法如下所述。
矩阵式键盘的按键辨认方法断定矩阵式键盘上何键被按下介绍一种行扫描法。
行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键辨认方法,如上图所示键盘,介绍进程如下。
差异键盘中有无键按下将悉数行线Y0-Y3置低电平,然后查看列线的情况。
只需有一列的电平为低,则标明键盘中有键被按下,并且闭合的键坐落低电平线与4根行线相穿插的4个按键傍边。
若悉数列线均为高电平,则键盘中无键按下。
差异闭合键地址的方位在供认有键按下后,即可进入断定详细闭合键的进程。
其方法是:顺次将行线置为低电平,即在置某根行线为低电往常,其它线为高电平。
在断定某根行线方位为低电平后,再逐行查看各列线的电平情况。
若某列为低,则该列线与置为低电平的行线穿插处的按键即是闭合的按键。
下面给出一个详细的比方:8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。
51单片机按键扫描程序
51单片机按键扫描程序#include#define uint unsigned int#define uchar unsigned charvoid delay(uint z);sbit LE=P1^4;uchar code table[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e};void main(){uchar temp;uint num;while(1){P2=0xfe; //按键扫描第一行temp=P2;temp=temp&0xf0;while(temp!=0xf0){delay(10); //消抖temp=P2;temp=temp&0xf0;while(temp!=0xf0) //再次确认是否有键按下{temp=P2;switch(temp){case 0xee:num=0;break; case 0xde:num=1;break; case 0xbe:num=2;break; case 0x7e:num=3;break;}while(temp!=0xf0) //松手检测{temp=P2;temp=temp&0xf0;}delay(10); //消抖LE=1;P0=table[num];LE=0;P1=0x0f;}}P2=0xfd; //按键扫描第二行temp=P2;temp=temp&0xf0;while(temp!=0xf0){delay(10);temp=P2;temp=temp&0xf0;while(temp!=0xf0){temp=P2;switch(temp){case 0xed:num=4;break; case 0xdd:num=5;break; case 0xbd:num=6;break; case 0x7d:num=7;break; }while(temp!=0xf0){temp=P2;temp=temp&0xf0;}delay(10);LE=1;P0=table[num];LE=0;P1=0x0f;}}P2=0xfb; //按键扫描第三行temp=P2;temp=temp&0xf0; while(temp!=0xf0){delay(10);temp=P2;temp=temp&0xf0; while(temp!=0xf0){temp=P2;switch(temp){case 0xeb:num=8;break; case 0xdb:num=9;break; case 0xbb:num=10;break; case 0x7b:num=11;break; }while(temp!=0xf0){temp=P2;temp=temp&0xf0;}delay(10);LE=1;P0=table[num];LE=0;P1=0x0f;}}P2=0xf7; //按键扫描第四行temp=P2;temp=temp&0xf0; while(temp!=0xf0){delay(10);temp=P2;temp=temp&0xf0;while(temp!=0xf0){temp=P2;switch(temp){case 0xe7:num=12;break; case 0xd7:num=13;break; case 0xb7:num=14;break; case 0x77:num=15;break;}while(temp!=0xf0){temp=P2;temp=temp&0xf0;}delay(10);LE=1;P0=table[num];LE=0;P1=0x0f;}}}}void delay(uint z) //延时子函数{uint x;for(z;z>0;z--)for(x=1000;x>0;x--); }。
键盘扫描通用程序
} }
//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) {
单片机典型矩阵键盘扫描程序
单片机典型矩阵键盘扫描程序#include "Key.h"static uchar GetKeyStatus();////$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$bit KeyProcess() // 为程序方便而设的返回值{uchar i,j;void (*pFunction)(); // 定义函数指针void (*code Tab[mHorizontalNumber][mVerticalNumber])()= // 定义函数表{ { ZeroKey, OneKey, FourKey, SevenKey },{ DotKey, TwoKey, FiveKey, EightKey },{ NegativeKey, ThreeKey, SixKey, NineKey },{ EnterOrShiftKey, CancelKey, OptionKey, PauseKey }}; // 二维数组,对对应16个按键NOP(); NOP();if(!bScanKey)return 0; // 扫描时间未到,返回(时间值在定时器中设定)bScanKey=0;NOP(); NOP();j=GetKeyStatus(); // 取键值,0xff为无效键,即无按键NOP(); NOP();if(bKeyDown||bKeyPress||bKeyUp){i=j>>4; j=j&0x0f; // 高半字节为行,低半字节为列if((i<mHorizontalNumber)&&(j<mVerticalNumber)){pFunction=Tab[j]; // 指向函数入口地址(*pFunction)(); // 调用函数}}}//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // 判断按键状态:KeyFree,KeyDown,KeyPress,KeyUp,并返回键值//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ static uchar ucKey1,ucKey2,ucKeyBak;static uchar GetKeyCode();static uchar GetKeyStatus(){uchar c;NOP(); NOP();mHorizontalAllLow; // 行输入全为0mJugeVertical(c); // 判断是否有按键NOP(); NOP();if((ucKey1==0xff)&&(ucKey2==0xff)&&(c==0xff)){ // 三个值均为0xff,无按键bKeyDown=bKeyPress=bKeyUp=0;bKeyFree=TRUE; return 0xff; // 没按键}else{bKeyFree=0;if(c!=0xff)c=GetKeyCode(); // 扫描键值if((ucKey1==0xff)&&(ucKey2==c)){ucKey1=ucKey2; ucKey2=c;bKeyDown=TRUE; return c; // 键被按下}if((ucKey1==ucKey2)&&(ucKey2==c)){NOP();if(bKeyDown){bKeyPress=TRUE; // 键被按住bKeyDown=0;}return c;}if((ucKey1!=0xff)&&(ucKey2==0xff)&&(c==0xff)){ucKeyBak=ucKey1; ucKey1=ucKey2; ucKey2=c;if(bKeyPress){bKeyUp=TRUE; // 键弹起bKeyPress=0;}return ucKeyBak;}ucKey1=ucKey2; ucKey2=c;}return 0xff;}//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$// 本程序读按键的行列号值,将行列号组合成一个字节后返回, //// 若读键错误,或没按键均返回0xff。
单片机矩阵键盘行列扫描程序
//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍#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--);}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
页: 1
文 文 : D:\ScanKey.c 2012-10-18, 9:31:46
//短 要 要 很 很 //包 要 要 很 很
#define C_KEY_MASK
0x7f //要 要 MASK
/*******************************************************
function: 要 要 不 不 按 按
Input : 20ms很 很 时 时
{
unsigned char R=0;
struct
{
static unsigned char Cnt=0;
//发 很
static unsigned char State=C_IDLE;
//状 状
unsigned char UpValue=0;
//短 短 不 要 要
static unsigned char DownValue=0;
#define C_IDLE #define C_DEBOUNCE #define C_SHORT_KEY #define C_LONG_KEY
0
//空 空
1
//消 消
2
//短 要 要
3
//包 要 要
#define C_KEY_SHORT_TIME 2
#define C_KEY_LONG_TIME
100
else if(KeyInfo.DownValue)
//还 终 要 要 在 要 我 , 则 检 检 包 要 要
{
t=0;
KeyInfo.State = C_LONG_KEY;
}
break;
case C_DEBOUNCE://消 消
if(KeyInfo.Pre != KeyInfo.Cur)
KeyInfo.DownValue &= ~KeyInfo.UpValue;
//要 我 不 要 -
短短不要 = 剩剩要我不要
KeyInfo.State = C_IDLE;
KeyInfo.Pre = KeyInfo.Cur;
//当 当ห้องสมุดไป่ตู้要 不 覆 覆
在上要不
break; case C_LONG_KEY://包 要 要
Output : ( 短 要 要 ) or( 包 要 要 +0x80)
Detail : 1.支 支 包 要 要 /支 支 要 /要 要 要 各 各 要 要 /支 支 支 支 7要 要 要
2.短 要 要 但 要 短 要 要 短 短 短 不 不 不 要 要 不
3.包 要 要 长 要 很 很 要 功 不 不 ( 要 要 不 +0x80)
文 文 : D:\ScanKey.c 2012-10-18, 9:31:46
/*在 在 在 在 在 在 在 , 要 要 要 要 要 , 包 包 包 要 要 , 短 要 要 , 改 改 改 改 , 很 很 很 不不不在在不要不在在要要不不不不不,很很很很很,而而不而在 我在我在我我我要要不不不我要不不,但但我我但但但我要但但但但但但不, 要要很要要要很要要,移移移不移,于但于于于但但不在在, 功功功但短要要功包要要 1.要 要 要 在 要 要 功 要 要 要 要 , 互 不 互 互 , 支 支 支 支 要 2.支 支 包 要 要 功 短 要 要 , 3.要 按 在 在 要 很 , 另 在 在 要 功 另 另 要 要 4.在 在 包 要 要 一 , 不 不 不 不 在 在 不 要 要 不 发发要发发在在功功发发要要不不要不不,还还不要要还(我我我但我很我) 不我但但,终于终我但但不终终 发如如如我如要发发如如不如,可可可可我可不不 */
4.按 按 函 要 函 函 20ms不 很 很 时 时
5.按 按 函 要 函 函 要 要 不 函 函 , 不 很 同 改 MASK
author : 但 天 改 天
********************************************************/
unsigned char ScanKey(unsigned char TimerFlag)
{
t++;
if(t >= C_KEY_SHORT_TIME)//消 消 OK
{
KeyInfo.State = C_SHORT_KEY;
}
}
else //消 消 消 消
{
KeyInfo.State = C_IDLE;
}
break;
case C_SHORT_KEY://短 要 要
//区 区 包 要 要 区 短 要 要
页: 2
t++; if(KeyInfo.Pre != KeyInfo.Cur) //终 要 要 检 检 , 则 则 则 包 要 要 检 检 {
KeyInfo.State = C_IDLE; } else if(t >= C_KEY_LONG_TIME) {
R = KeyInfo.DownValue | 0x80; KeyInfo.DownValue = 0; KeyInfo.State = C_IDLE; } break; } return R; }
//要 我 不 要 要
unsigned char Cur=0;
//当 当 不 要 不
static unsigned char Pre=0;
//在 上 不 要 不
}KeyInfo;
if(TimerFlag)return 0; TimerFlag=0;
//短 等 很 很 时 时
KeyInfo.Cur &= C_KEY_MASK; //读 要 要 不 (高 高 高 高 高 要 要 ) switch(KeyInfo.State) {
KeyInfo.UpValue = (KeyInfo.Pre ^ KeyInfo.Cur) & KeyInfo.Pre;
//短 短 不 要 要
KeyInfo.DownValue |= (KeyInfo.Pre ^ KeyInfo.Cur) & KeyInfo.Cur;
//要 我 不 要 要
R = KeyInfo.UpValue & KeyInfo.DownValue; //短 要 要