標題: 在書上看到的程序,總感覺它中斷里面的掃描緩存有問題,有興趣的可以看一下 [打印本頁]
作者: 星際漫游者 時間: 2017-7-14 15:00
標題: 在書上看到的程序,總感覺它中斷里面的掃描緩存有問題,有興趣的可以看一下
#include <reg52.h>
sbit KEY_IN_1 = P2^4; //矩陣按鍵的掃描輸入引腳1
sbit KEY_IN_2 = P2^5; //矩陣按鍵的掃描輸入引腳2
sbit KEY_IN_3 = P2^6; //矩陣按鍵的掃描輸入引腳3
sbit KEY_IN_4 = P2^7; //矩陣按鍵的掃描輸入引腳4
sbit KEY_OUT_1 = P2^3; //矩陣按鍵的掃描輸出引腳1
sbit KEY_OUT_2 = P2^2; //矩陣按鍵的掃描輸出引腳2
sbit KEY_OUT_3 = P2^1; //矩陣按鍵的掃描輸出引腳3
sbit KEY_OUT_4 = P2^0; //矩陣按鍵的掃描輸出引腳4
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
unsigned char code LedChar[] = {
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e
}; //數碼管真值表
unsigned char KeySta[4][4] = { //全部矩陣按鍵的當前狀態,默認都未按下
{1, 1, 1, 1}, //bit類型不能定義數組,因此定義成unsigned char
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1}
};
void main(void)
{
unsigned char i, j;
unsigned char backup[4][4] = { //按鍵值備份,保存前一次的值
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1}
};
//選擇最右邊的數碼管進行顯示
P0 = 0xFF;
ADDR0 = 0;
ADDR1 = 0;
ADDR2 = 0;
ADDR3 = 1;
ENLED = 0;
//配置T0工作在模式1,定時1ms
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
TR0 = 1;
ET0 = 1;
EA = 1;
while(1)
{
//檢索按鍵狀態的變化
for (i=0; i<4; i++) //i作為行循環變量
{
for (j=0; j<4; j++) //j作為列循環變量
{
if (backup[j] != KeySta[j]) //判斷按鍵動作
{
if (backup[j] == 0) //判斷按鍵彈起
{
P0 = LedChar[i*4+j]; //執行按鍵動作
}
backup[j] = KeySta[j]; //更新前一次的值
}
}
}
}
}
void InterruptTimer0() interrupt 1
{
unsigned char i;
static unsigned char keyout = 0; //矩陣按鍵掃描輸出計數器
static unsigned char keybuf[4][4] = { //按鍵掃描緩沖區,保存一段時間內的掃描值
{0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF}
};
TH0 = 0xFC; //溢出后進入中斷重新賦值
TL0 = 0x67; 按照我們的鍵盤掃描程序應該是中斷1ms鍵值賦值一次并賦值
左移4次則keyout加1轉下一列重新掃描16ms掃描完成。而此
程序我發現中斷1ms雖然會有鍵值輸入緩存但他會輸入一次
keyout就增加一次達不到我們所涉及的效果嗎。或許我分析的
不對,就請各位看一下
//將一行的4個按鍵值移入緩沖區
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
//消抖后更新按鍵狀態
for (i=0; i<4; i++) //每行4個按鍵,所以循環4次
{
if ((keybuf[keyout] & 0x0F) == 0x00)
{ //連續4次掃描值為0,即16ms(4*4ms)內都只檢測到按下狀態時,可認為按鍵已按下
KeySta[keyout] = 0;
}
else if ((keybuf[keyout] & 0x0F) == 0x0F)
{ //連續4次掃描值為1,即16ms(4*4ms)內都只檢測到彈起狀態時,可認為按鍵已彈起
KeySta[keyout] = 1;
}
}
//執行下一次的掃描輸出
keyout++;
keyout &= 0x03; //用跟0x03做“與”的方式,實現加到4即歸零,是不是很巧妙,學會它吧
switch (keyout)
{
case 0:
KEY_OUT_4 = 1;
KEY_OUT_1 = 0;
break;
case 1:
KEY_OUT_1 = 1;
KEY_OUT_2 = 0;
break;
case 2:
KEY_OUT_2 = 1;
KEY_OUT_3 = 0;
break;
case 3:
KEY_OUT_3 = 1;
KEY_OUT_4 = 0;
break;
default:
break;
}
}
作者: wulin 時間: 2017-7-14 17:08
這是哪本誤人子弟的書,這個例程不值得研究,給你推薦一個例程,程序很簡單,一眼看明白:
#include <reg52.h> //頭文件
#define uchar unsigned char //宏定義
#define uint unsigned int //宏定義
uchar key=0; //鍵值變量
void key_scan() //矩陣鍵盤掃描函數
{
uchar temp1,temp2,temp3; //臨時變量
static bit sign=0; //按鍵自鎖標志
static uchar count=0; //消抖計數變量
P3=0xf0; //先給P3賦一個初值
if(P3!=0xf0) //判斷P3不等于所賦初值,說明有健按下
{
if(sign==0) //如果按鍵自鎖標志為0
{
count++; //消抖計數
if(count>=100) //消抖計數自>=100,估算主循環周期調整
{ //摒棄Delay延時方式,
count=100; //防止溢出
sign=1; //按鍵自鎖標志置1,鍵不抬起,按其他鍵無效
temp1=P3; //temp1保存高4位變化
P3=0x0f; //再給P3賦值0x0f
temp2=P3; //temp2保存低4位變化
temp3=temp2|temp1; //temp3=高4位+低4位
key=temp3; //保存鍵值
}
}
}
else //按鍵抬起
{
sign=0; //按鍵自鎖標志清0
count=0; //消抖計數清0
}
}
void main()
{
while(1)
{
key_scan(); //鍵盤掃描
P1=key; //LED低電平亮顯示鍵值
}
}
作者: #include51.h 時間: 2019-2-7 15:21
同感,最不喜歡將那些變量名定的又臭又長的
| 歡迎光臨 (http://www.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |