您的位置: proteus仿真社区 >> 论坛 >> 我爱灌水 >> 查看帖子
字体: 小 中 大 | 打印 发表于: 2008-7-20 18:58 作者: jiankewuying 来源: proteus仿真社区
采用独特算法的键盘扫描程序 大家一起计论,还有没有可能将代码再优化
行列式键盘扫描子程序.rar(2008-07-20 18:58:04, Size: 44.7 KB, Downloads: 35)
QUOTE:
原帖由 arnxuezhe 于 2008-7-26 14:19 发表 我不喜欢汇编,C比较简单^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1.JPG
CODE:
/***************************************************************** 文件名称:行列式键盘扫描程序 作 者: 徐修亮 版 本: 说 明: 日期 : 2008 4 26 修改记录:2008 7 20 14:00 修改后能直接返回0-16的键值 2008 7 20 17:30 优化了代码 *******************************************************************/ #include #define uchar unsigned char #define PORT P2 //义键盘行列端口,低位为行,高位为列, uchar scan (void); uchar key(void); void delay100us(uchar t); void main(void) { uchar idata key1; while(1) { key1=key(); P1=key1; } } /************************************************* 函数名称:uchar key(uchar x) 函数功能:按顺充返回键值0到15,其中若为16则说明无键按下 入口参数:无 出口参数:uchar key() 即返回的键值 备 注: *************************************************/ /* uchar key(void) { uchar temp ; switch(scan()) { case 0 : temp=16 ; break; //无键按下返回16 case 0x11 : temp=0 ; break; //返回键值 case 0x21 : temp=1 ; break; case 0x41 : temp=2 ; break; case 0x81 : temp=3 ; break; case 0x12 : temp=4 ; break; case 0x22 : temp=5 ; break; case 0x42 : temp=6 ; break; case 0x82 : temp=7 ; break; case 0x14 : temp=8 ; break; case 0x24 : temp=9 ; break; case 0x44 : temp=10 ; break; case 0x84 : temp=11 ; break; case 0x18 : temp=12 ; break; case 0x28 : temp=13 ; break; case 0x48 : temp=14 ; break; case 0x88 : temp=15 ; break; } return temp ; } */ /********************************************************* 函数名称:uchar key(uchar x) 函数功能:按顺充返回键值0到15,其中若为16则说明无键按下 入口参数:无 出口参数:uchar key() 即返回的键值 备 注: 利用算法对代码进行优化使程序与前面的单独进行比较 方法相比,代码减少96个字节 ,虽然RAM多两个 ***********************************************************/ uchar key(void) { uchar y,high4,low4,temp,i,j; y=scan(); if(y==0) temp=16; else { high4=0x10; low4 =0x01; for(i=0;i<4;i++) for(j=0;j<4;j++) { if(y==(high4<<J)+(LOW4<<I)) temp=4*i+j; } } return temp ; } uchar scan(void) { uchar idata sccode; uchar idata recode; PORT =0xf0; if((PORT&0xf0)!=0xf0) { delay100us(100); // 延时10ms去抖动 if ((PORT&0xf0)!=0xf0) { sccode=0xfe; while((sccode&0x10)!=0) //没有扫描到最后一行,则往下执行 { PORT=sccode; if((PORT&0xf0)!=0xf0) //若有键按下则往下执行 { recode=(PORT&0xf0)|0x0f; return ( (~sccode)+(~recode)) ; //特征值 } else sccode=((sccode<<1)|0x01); } } } } /****************************** 函数名称:delay(uchar t) 函数功能: 延时t/10 ms 入口参数: uchar t 出口参数: 无 备 注: ******************************/ void delay100us(uchar t) { uchar j; while(t--) { for (j=50 ;j>0;j--); } }
最新回复
bonjour (2008-7-20 20:40:11)
fz5098 (2008-7-20 22:39:28)
yubo2007 (2008-7-21 06:40:37)
hgjinwei (2008-7-21 14:16:53)
;//
;// 程序名称:key_scan.asm
;// 程序用途:4*4矩阵键盘扫描检测
;// 功能描述:扫描键盘,确定按键值。程序不支持双键同时按下,
;// 如果发生双键同时按下时,程序将只识别其中先扫描的按键
;// 程序入口:void
;// 程序出口:CY : 有效性(0);ACC : 按键扫描值;KEY_STU : 按键状态记录
;// 编写人 :xxxx,2007-12-11
;// 最后修改:xxx,2007-12-12
;//
;//======================================================================
KEY_STU DATA 40H ;b7-b5纪录按键状态,b4-b0记录等待时间
R_TIME EQU 30 ;重复按键输入等待时间(不能大于32)
KEY_PORT EQU P1 ;键盘接口(必须完整I/O口)
;//======================================================================
KEY_CHK:
;//=============按键检测程序=============================================
ANL KEY_PORT,#0FH ;送扫描信号
MOV A,KEY_PORT ;读按键状态
CJNE A,#0FH,KEY_NEXT1 ;ACC<=0FH
; CLR C ;Acc等于0FH,则CY为0,无须置0
KEY_NEXT1:
; SETB C ;Acc不等于0FH,则ACC必小于0FH,CY为1,无须置1
MOV A,KEY_STU
RRC A ;ACC带CY右移一位,将当前状态记录到最高位
ANL A,#0E0H ;屏蔽低五位
DEC KEY_STU ;每执行一次,按键等待时间减1
ANL KEY_STU,#1FH ;屏蔽高三位,准备接受新值
ORL KEY_STU,A ;保留按键状态
;//=============判别按键状态,决定是否执行按键扫描========================
CJNE A,#0C0H,KEY_NEXT2 ;110按键稳定闭合,进入按键检测程序
SJMP KEY_SCAN
KEY_NEXT2:
CJNE A,#0E0H,KEY_NEXT3 ;111按键长闭合,重复输入允许判断
SJMP KEY_WAIT
KEY_NEXT3:
CJNE A,#040H,KEY_NEXT4
ANL KEY_STU,#01FH ;010干扰,当000处理
;SJMP KEY_R_0 ;ACC等于040H,不会等于0A0H,直接跳转可转为测试跳转
KEY_NEXT4:
CJNE A,#0A0H,KEY_RET_0 ;101干扰,当111长闭合处理
ORL KEY_STU,#0E0H
KEY_WAIT:
MOV A,KEY_STU
ANL A,#01FH ;屏蔽高三位(状态位)
JZ KEY_SCAN ;时间已到,扫描键盘
KEY_RET_0: ;按键扫描无效,返回CY = 1
SETB C ;没有按键,返回1,按键无效
ORL KEY_PORT,#0FFH
RET
RET
RET
;//=============键盘扫描程序==============================================
KEY_SCAN:
MOV R2,#4 ;初始化列地址
MOV R3,#11111110B ;初始化扫描码
KEY_LOOP:
MOV A,R3
RR A
MOV R3,A ;保留扫描码
MOV KEY_PORT,A ;送扫描码
MOV A,KEY_PORT ;读键盘
ORL A,#0F0H ;屏蔽高四位
CJNE A,#0FFH,KEY_NEXT21 ;A不等于FFH,说明该列有按键动作
DJNZ R2,KEY_LOOP
SJMP KEY_RET_0 ;扫描没有检测到按键,返回0
;//=======================================================================
CORRECT equ 7 ;修正值
KEY_NEXT21:
JB ACC.0,KEY_NEXT22
MOV R3,#1+CORRECT ;第1行有按键
SJMP KEY_NEXT25
KEY_NEXT22:
JB ACC.1,KEY_NEXT23
MOV R3,#2+CORRECT ;第2行有按键
SJMP KEY_NEXT25
KEY_NEXT23:
JB ACC.2,KEY_NEXT24
MOV R3,#3+CORRECT ;第3行有按键
SJMP KEY_NEXT25
KEY_NEXT24:
MOV R3,#4+CORRECT ;第4行有按键
KEY_NEXT25: ;计算按键地址
MOV A,R2
RL A
RL A ;列地址乘4(每列对应4行)
ADD A,R3 ;加行地址
MOVC A,@A+PC
KEY_RET_1: ;按键扫描有效,返回按键值
ORL KEY_PORT,#0FFH
ANL KEY_STU,#0E0H
ORL KEY_STU,#R_TIME ;送重复按键等待时间
;CLR C ;ACC+R3不会进位,CY无须清0
RET ;退出
RET
RET
;//=============按键名称表================================================
KEYNAME_TTAB:
DB 07H,08H,09H,0AH
DB 04H,05H,06H,0BH
DB 01H,02H,03H,0CH
DB 0FH,00H,0EH,0DH
不知这个程序算不算比较好.
[ 本帖最后由 hgjinwei 于 2008-7-27 15:11 编辑 ]
arnxuezhe (2008-7-21 14:49:42)
arnxuezhe (2008-7-21 14:50:37)
skdyu (2008-7-21 14:53:56)
fuda208 (2008-7-22 11:34:37)
panhearii (2008-7-22 11:43:28)
qinhonghua (2008-7-22 11:48:10)
hgjinwei (2008-7-22 12:51:50)
jiankewuying (2008-7-23 20:18:44)
zcmhff (2008-7-25 22:04:10)
哈哈
arnxuezhe (2008-7-26 14:19:38)
hgjinwei (2008-7-26 15:19:27)
QUOTE:
这家伙肯定很懒得动脑 ,ybzjllj (2008-7-27 13:53:07)
1.JPG
CODE:
/*****************************************************************
文件名称:行列式键盘扫描程序
作 者: 徐修亮
版 本:
说 明:
日期 : 2008 4 26
修改记录:2008 7 20 14:00 修改后能直接返回0-16的键值
2008 7 20 17:30 优化了代码
*******************************************************************/
#include
#define uchar unsigned char
#define PORT P2 //义键盘行列端口,低位为行,高位为列,
uchar scan (void);
uchar key(void);
void delay100us(uchar t);
void main(void)
{ uchar idata key1;
while(1)
{ key1=key();
P1=key1;
}
}
/*************************************************
函数名称:uchar key(uchar x)
函数功能:按顺充返回键值0到15,其中若为16则说明无键按下
入口参数:无
出口参数:uchar key() 即返回的键值
备 注:
*************************************************/
/*
uchar key(void)
{ uchar temp ;
switch(scan())
{
case 0 : temp=16 ; break; //无键按下返回16
case 0x11 : temp=0 ; break; //返回键值
case 0x21 : temp=1 ; break;
case 0x41 : temp=2 ; break;
case 0x81 : temp=3 ; break;
case 0x12 : temp=4 ; break;
case 0x22 : temp=5 ; break;
case 0x42 : temp=6 ; break;
case 0x82 : temp=7 ; break;
case 0x14 : temp=8 ; break;
case 0x24 : temp=9 ; break;
case 0x44 : temp=10 ; break;
case 0x84 : temp=11 ; break;
case 0x18 : temp=12 ; break;
case 0x28 : temp=13 ; break;
case 0x48 : temp=14 ; break;
case 0x88 : temp=15 ; break;
}
return temp ;
}
*/
/*********************************************************
函数名称:uchar key(uchar x)
函数功能:按顺充返回键值0到15,其中若为16则说明无键按下
入口参数:无
出口参数:uchar key() 即返回的键值
备 注: 利用算法对代码进行优化使程序与前面的单独进行比较
方法相比,代码减少96个字节 ,虽然RAM多两个
***********************************************************/
uchar key(void)
{ uchar y,high4,low4,temp,i,j;
y=scan();
if(y==0) temp=16;
else
{
high4=0x10;
low4 =0x01;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if(y==(high4<<J)+(LOW4<<I))
temp=4*i+j;
}
}
return temp ;
}
uchar scan(void)
{ uchar idata sccode;
uchar idata recode;
PORT =0xf0;
if((PORT&0xf0)!=0xf0)
{ delay100us(100); // 延时10ms去抖动
if ((PORT&0xf0)!=0xf0)
{ sccode=0xfe;
while((sccode&0x10)!=0) //没有扫描到最后一行,则往下执行
{ PORT=sccode;
if((PORT&0xf0)!=0xf0) //若有键按下则往下执行
{ recode=(PORT&0xf0)|0x0f;
return ( (~sccode)+(~recode)) ; //特征值
}
else
sccode=((sccode<<1)|0x01);
}
}
}
}
/******************************
函数名称:delay(uchar t)
函数功能: 延时t/10 ms
入口参数: uchar t
出口参数: 无
备 注:
******************************/
void delay100us(uchar t)
{
uchar j;
while(t--)
{
for (j=50 ;j>0;j--);
}
}
hygk (2008-7-30 15:25:16)
有没有汇编的啊
hgjinwei (2008-7-30 19:07:18)
不过不支持多键状态 , 不知多键状态有什么好算法.
MCU_51 (2008-8-28 14:43:36)
hyzqq (2008-8-28 17:24:33)
编好 ! 我喜欢