欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
請教!這個單片機矩陣鍵盤程序不用外部中斷如何修改?
[打印本頁]
作者:
zlkj
時間:
2021-5-20 13:42
標題:
請教!這個單片機矩陣鍵盤程序不用外部中斷如何修改?
請教!這個矩陣鍵盤不用外部中斷如何修改?/*程序功能:
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
sbit 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;
}
作者:
glinfei
時間:
2021-5-20 15:10
EXT_INT()只是相當于最開始鎖鍵盤的作用,可以不用,鍵盤初始化時直接 key.detect=1就行;void timer0() 這個功能有點麻煩,如果你不需要雙擊等功能,就比較好改,否則會改的面部全非了。但源程序誰寫的,寫的不錯啊。
作者:
tyrl800
時間:
2021-5-20 21:48
enum st{Nkey,Skey,Ckey,Lkey};
unsigned char kstate;
#define S_cnt 100
#define C_cnt 400
bit flag_down;
unsigned char kpadscan_turn_S_L_C(void)
{ unsigned char i,tmp,tmp1;
static uchar keyv;
keyport=0x0f;
tmp=~keyport&0x0f;
if(tmp)
{if(++kpadcnt>5)
{
keyport=0xf0;
tmp1=~keyport&0xf0;
tmp=tmp|tmp1;
for(i=0;i<16;i++)
{
if(tmp==keycode[i])
{keyv=i+1;
break;
}
}
flag_down=1;
}
}
if(flag_down)
{
keyport=0x0f;
tmp=~keyport&0x0f;
if(tmp==0)
{if(kpadcnt<S_cnt)kstate=Skey;
else if((kpadcnt>=S_cnt)&&(kpadcnt<C_cnt))kstate=Ckey;
else kstate=Lkey;
flag_down=0;
kpadcnt=0;
}
}
return keyv;
}
歡迎光臨 (http://m.raoushi.com/bbs/)
Powered by Discuz! X3.1