完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
请教!这个矩阵键盘不用中断如何修改?
/* 程序功能: K1单击时num+1;长击num+2; K2单击时num-1;长击num-2; K5连击按键 按着num+1; K6连击按键 按着num-1; 无按键时间4s led亮;有按键,led灭。 */ //支持单击(短击)、连击,长击,无击 //长击时间到后,立即执行;短击释放后执行 //按键方式(单击,长击)、(只支持单击)、(连击) //连击实际上包含了单击 #include "reg51.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int #define NOP() _nop_() #define KeyPIN P1 ***it led=P3^7; uchar num; uchar key_code[]= {0x7e,0x7d,0x7b,0x77,0xbe,0xbd,0xbb,0xb7,0xde,0xdd,0xdb,0xd7,0xee,0xed,0xeb,0xe7}; struct { uchar state;//按键状态 0-等待阶段;1-闭合抖动阶段;2-有效闭合阶段;3-释放阶段 uchar type;//0-无按键或者按键已经响应 ;1-单击 ;2-连击 ;3-长击;4-无击 uchar detect;//按键检测标志 1为检测到按键 uchar value;//当前键值 uchar backvalue;//备份键值 uchar disable;//按键禁止响应标志:按键执行过,则标志为1.主要用于长击。 uchar scan_en;//按键扫描标志 1为允许扫描 uchar tmr_no;//无键计数器,用于无击。 uchar cnt_press;//按键闭合计数器,用于长击。 uchar delay_con;//连击响应延时时间,用于连击。 #define AN_XD_DL 2//AN_XD_DL*定时器中断20ms #define AN_LA_DL 10//AN_LA_DL*20ms #define AN_CJ_DL 5//长击所需时间:AN_CJ_DL*AN_LA_DL*20ms #define KEY_IDLE 0//按键等待阶段 #define KEY_IS_DOWN 1//闭合抖动阶段 #define KEY_DOWN 2//有效闭合阶段 #define KEY_IS_UP 3//释放阶段 #define NoKey 0//无键 #define NoKeyTMR 200//无键所需时间:NoKeyTMR*20ms } key; unsigned char KeyScan(void); void KeyInit(void); void KeyProcess(void); void KeyShortPress(void);//短击 单击 void KeyLongPress(void);//长击 void KeyContinuePress(void);//连击 void KeyNoPress(void);//无击 void KeyAction(void);//根据按键类型动作 散转程序 void main() { TCON=0x00; IE=0x84; TMOD=0x01; TH0=0xB1; TL0=0xE0; ET0=1; TR0=1; EA = 1; while(1) { KeyPIN=0x0f; KeyProcess(); KeyAction(); P0=num/10; P2=num%10; } } //键盘扫描方法,反转法 uchar KeyScan(void) { uchar temp,keyval=0; KeyPIN = 0x0f; if (KeyPIN != 0x0f) { temp=KeyPIN; KeyPIN = 0xf0; temp|=KeyPIN; keyval=1; while (key_code[keyval-1] != temp) //把特征码转换为键号 { keyval++; if(keyval>0x0f) { break; } } } return keyval; } void KeyProcess() { switch(key.state) { case KEY_IDLE://等待阶段 { key.disable=0; key.delay_con=AN_XD_DL; key.cnt_press=0; if(key.detect)//有按键才允许扫描 { key.tmr_no=0;//有键按下,无键计数器清零 key.type=0; key.detect=0; if(key.scan_en) { key.scan_en=0; key.state=KEY_IS_DOWN; } } else { if(key.tmr_no==NoKeyTMR) { key.type=4; } } } break; case KEY_IS_DOWN: { key.tmr_no=0; if(key.scan_en) { key.scan_en=0; key.value=KeyScan(); if(key.value==key.backvalue) { key.state=KEY_DOWN; } else { key.backvalue=key.value; } } } break; case KEY_DOWN: { key.tmr_no=0; if(key.scan_en) { key.scan_en=0; key.backvalue=key.value;//备份当前键值供释放后 单击 使用 key.value=KeyScan(); key.delay_con--; if(key.delay_con==0) { key.delay_con=AN_LA_DL; key.cnt_press++; if(key.cnt_press>AN_CJ_DL) { if(!key.disable)//长击执行过一次后,如不释放按键,不执行。 { key.type=3; } else { key.type=0; } } else { key.type=2; } } if(key.value==NoKey) { key.state=KEY_IS_UP; } } } break; case KEY_IS_UP: { key.tmr_no=0; if(!key.disable)//避免长击释放后 继续执行单击 { key.type=1; } key.state=KEY_IDLE; } break; } } void KeyAction(void) { switch(key.type) { case 1: { KeyShortPress(); } break; case 2: { KeyContinuePress(); key.type=0; } break; case 3: { KeyLongPress(); } break; case 4: { KeyNoPress(); } break; } } void KeyNoPress(void) { led=0; } void KeyShortPress(void) { led=1; switch(key.backvalue) { case 1: num++; break; case 2: num--; break; } } void KeyContinuePress(void) { led=1; switch(key.backvalue) { case 5: num++; break; case 6: num--; break; } } void KeyLongPress(void) { led=1; switch(key.backvalue) { case 1: num+=2; key.disable=1; key.type=0; break;//此处key.disable和key.type必须这样处理 case 2: num-=2; key.disable=1; key.type=0; break; default: key.type=2;//因为长击是在按下后时间足够后就触发的,所以为避免连击和长击冲突,必须加此句 } } void timer0() interrupt 1 using 1 //12M晶振 20ms中断 { TH0=0xB1; TL0=0xE0; key.tmr_no++; if(key.detect) { key.scan_en=1; //有键按下才允许扫描 } } void EXT_INT() interrupt 2 using 1 { key.detect=1; } |
|
相关推荐
9个回答
|
|
|
|
|
|
这个程序不用中断如何修改?多谢指点!
|
|
|
|
弄个定时器中断,比如5MS一次中断,做个标志,在定时器里面,中断来了就置1,主函数里面,判断这个标志位为1了,调用一次按键扫描程序,同时清标志。
|
|
|
|
麻烦你改改这个程序,谢谢!
|
|
|
|
我有发到论坛的,你找一下,自己修改下吧,很简单的。
|
|
|
|
感谢你的支持。可是你的程序修改C51不成功?如何实现长按、连击请指教!
|
|
|
|
我的例程就有。这个按键扫描没用过在51上,但是51是最简单的。
|
|
|
|
!!!!!!!!!!!
|
|
|
|
程序结构改用轮询的方法,按键扫描、按键处理放在主循环,主循环计数周期放在定时器中断里。这样你想做多久的长按都可以。
|
|
|
|
只有小组成员才能发言,加入小组>>
3288 浏览 9 评论
2962 浏览 16 评论
3465 浏览 1 评论
9010 浏览 16 评论
4054 浏览 18 评论
1127浏览 3评论
579浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
573浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2306浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1864浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 03:14 , Processed in 1.619273 second(s), Total 98, Slave 77 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号