还是和之前一样,在大佬ReCclay的代码上稍加了修改和注释。
真的十分感谢ReCclay的博客
《关于按键的故事》 作者 ReCclay (https://blog.csdn.net/ReCclay/article/details/79293182)
这次的矩阵按键是在独立按键的基础上改造的:
理解独立按键,必须理解应用层KeyDriver()和底层KeyScan(),KeyAction()三者的联系
- KeyScan()在中断里扫描键值 运用移位操作,静态变量,循环,判断按下的键值
- KeyDriver()在主函数循环里刷新 使用静态变量keyback,进行按键松开,按下,按住的判断
- KeyAction()根据扫描的键值操作 使用多个if语句,或者case语句进行直接操作或flag操作
只是多加了一个 j,判断4* 4键盘状态。
流程:判断按下的哪个键,进行松开,按下,按住的判断,最后执行按键的指令
《定时扫描独立按键》https://blog.csdn.net/qq_28997735/article/details/88320420
注意:矩阵按键P36,P37转接为P42,P44!!!
与独立按键(2ms一扫)不同,这次扫描时间为1ms一扫,1* 4* 4=16ms,这样就和独立按键扫描时间一样了
******************************************************************************
* 文件名:定时扫描矩阵按键
* 描 述:
* 作 者:思索与猫
* 日 期: 19/3/13
* 备 注:
*
******************************************************************************
#include<stc15f2k60s2.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit Key_Out_1 = P3^0; //横排
sbit Key_Out_2 = P3^1;
sbit Key_Out_3 = P3^2;
sbit Key_Out_4 = P3^3;
sbit Key_In_1 = P4^4; //纵排
sbit Key_In_2 = P4^2;
sbit Key_In_3 = P3^5;
sbit Key_In_4 = P3^4;
uchar code duan[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; //10black,11-
uchar dispbuff[8];
uchar num = 0;
uchar KeySta[4][4] = {{1, 1, 1, 1}, //4*4矩阵按键的状态,1为抬起,0为按下
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1}};
uchar KeyCodeMap[4][4] = {{'1', '2', '3', '0'}, //注意这里用的是字符,可以直接写数字,那就不用加引号了
{'4', '5', '6', '0'},
{'7', '8', '9', '0'},
{'0', '0', '0', '0'}};
//function
void Timer0Init();
void CloseFucker();
void Display();
void ShowNumber();
void KeyScan();
void KeyAction(uchar temp);
void KeyDriver();
void main()
{
CloseFucker();
Timer0Init(); //2ms 12Mhz
while(1)
{
ShowNumber();
KeyDriver();
}
}
void T0_time() interrupt 1
{
Display();
KeyScan();
}
void KeyDriver()
{
uchar i = 0, j = 0;
static uchar keyback[4][4] = {{1,1,1,1}, //备用键,用来判断抬起,按下
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},};
for(i = 0; i < 4; i++)
{
for(j = 0; j <4; j++)
{
if(KeySta[i][j] != keyback[i][j]) //按键状态发生变化
{
if(KeySta[i][j] != 0) //按键状态又发生变化,说明按下又抬起
{
KeyAction(KeyCodeMap[i][j]); //执行按键指令
}
keyback[i][j] = KeySta[i][j]; //将变化后的按键状态值储存
}
}
}
}
void KeyAction(uchar temp) //按键执行
{
num = temp-'0';
}
void KeyScan()
{
uchar i = 0;
static uchar keyout = 0;
static uchar KeyBuf[4][4] = {{0xff,0xff,0xff,0xff},
{0xff,0xff,0xff,0xff},
{0xff,0xff,0xff,0xff},
{0xff,0xff,0xff,0xff}};
switch(keyout)
{
case 0:Key_Out_1 = 0;Key_Out_4 = 1;break;
case 1:Key_Out_2 = 0;Key_Out_1 = 1;break;
case 2:Key_Out_3 = 0;Key_Out_2 = 1;break;
case 3:Key_Out_4 = 0;Key_Out_3 = 1;break;
}
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++)
{
if((KeyBuf[keyout][i]&0x0f) == 0x00) //键盘按下
{
KeySta[keyout][i] = 0;
}
else if((KeyBuf[keyout][i]&0x0f) == 0x0f) //键盘抬起
{
KeySta[keyout][i] = 1;
}
}
keyout++;
keyout &= 0x03;
}
void ShowNumber()
{
dispbuff[0] = num/10;
dispbuff[1] = num%10;
dispbuff[2] = 10;
dispbuff[3] = 10;
dispbuff[4] = 10;
dispbuff[5] = 10;
dispbuff[6] = 10;
dispbuff[7] = 10;
}
void Display()
{
static uchar index = 0;
P2 = P2&0x1f|0xe0;
P0 = 0xff;
P2 = P2&0x1f;
P2 = P2&0x1f|0xc0;
P0 = 1<<index;
P2 = P2&0x1f;
P2 = P2&0x1f|0xe0;
P0 = ~duan[dispbuff[index]];
P2 = P2&0x1f;
index++;
index &= 0x07;
}
void Timer0Init() //1ms 12Mhz
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0x20;
TH0 = 0xD1;
TF0 = 0;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void CloseFucker()
{
P2 = P2&0x1f|0xa0;
P0 = 0xaf;
P2 = P2&0x1f;
}