矩阵键盘是蓝桥杯开发板的一个重要模块,矩阵键盘的扫描思想在以后的单片机学习中也是一个重要的思想,除了通过条件判断的方式实现矩阵键盘,我们还可以通过移位运算符更方便的实现矩阵键盘;
一、移位运算符实现矩阵键盘
二、加入长短按功能
一、移位运算符实现矩阵键盘
我么可以对一行或列进行扫描后,将数据左移四位(<<4)后腾出空间,将下一行或列写入,每次将扫描数据加入后都左移四位,这样我们就可以通过一个16位的变量存储一轮扫描获得的每一行或列的信息,代码实现如下:
unsigned char Key_Scan(void)
{
unsigned int Key_New;
unsigned char Key_Value;
P3 |= 0x0F;
P44 = 0; P42 = 1; P35 = 1; P34 = 1; // 第一列
Key_New = P3 & 0X0F;
P44 = 1; P42 = 0; P35 = 1; P34 = 1; // 第二列
Key_New = (Key_New << 4) | (P3 & 0X0F);
P44 = 1; P42 = 1; P35 = 0; P34 = 1; // 第三列
Key_New = (Key_New << 4) | (P3 & 0X0F);
P44 = 1; P42 = 1; P35 = 1; P34 = 0; // 第四列
Key_New = (Key_New << 4) | (P3 & 0X0F);
switch(~Key_New)
{
case 0x8000: Key_Value = 1; break;
case 0x4000: Key_Value = 2; break;
case 0x2000: Key_Value = 3; break;
case 0x1000: Key_Value = 4; break;
case 0x0800: Key_Value = 5; break;
case 0x0400: Key_Value = 6; break;
case 0x0200: Key_Value = 7; break;
case 0x0100: Key_Value = 8; break;
case 0x0080: Key_Value = 9; break;
case 0x0040: Key_Value = 10; break;
case 0x0020: Key_Value = 11; break;
case 0x0010: Key_Value = 12; break;
case 0x0008: Key_Value = 13; break;
case 0x0004: Key_Value = 14; break;
case 0x0002: Key_Value = 15; break;
case 0x0001: Key_Value = 16; break;
default : Key_Value = 0;
}
return Key_Value;
}
将以上函数放入循环中即可实现移位运算符法实现矩阵键盘。
二、加入长短按功能
加入了长短按功能可以使矩阵键盘的功能更加丰富,这里我们采用Delay延时+Count计数的方式获得按键按下的时间,再设定一个阈值来判断长按或是短按,代码实现如下:
//长短按判断函数
unsigned char LongOrShort()
{
unsigned int TimeCount = 0;
unsigned int EnterFlag = 0;
while(Key_Scan() != 0)//使用Key_Scan()函数的返回值作为按键按下的判断标志,其他判断标志亦可
{
TimeCount++;
EnterFlag = 1;//释放信号量,防止直接进入按键按下时间判断(即下面的if和else if)
Delay(1);//理想情况下计数值每增加一花费1毫秒,但实际略大于1毫秒
//想减少误差可增加delay时间,减少判断时Count的阈值(懒得改了)
}
if(TimeCount<500 & EnterFlag == 1)
{
TimeCount = 0;//清除循环次数计数
EnterFlag = 0;//清除信号量
return 0;
}
else if(TimeCount>500 & EnterFlag == 1)
{
TimeCount = 0;
EnterFlag = 0;
return 1;
}
return IFLong_OutPut;//若未进入按下时间判断,返回上次值
}
全部函数如下:
#include <STC15F2K60S2.H>
code unsigned char smg_DM[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char Key_OutPut,IFLong_OutPut;
void Delay(unsigned int xms) //@11.0592MHz
{
while(xms--)
{
unsigned char i, j;
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
void smg_bit(unsigned char com,unsigned char num)//数码管显示函数
{
P2 = (P2 & 0x1f) | 0xC0;
P0 = 1 << (com - 1);
P2 = (P2 & 0x1f) | 0xE0;
P0 = smg_DM[num];
Delay(2);
P0 = 0xff;
}
unsigned char Key_Scan(void)
{
unsigned int Key_New;
unsigned char Key_Value;
P3 |= 0x0F;
P44 = 0; P42 = 1; P35 = 1; P34 = 1; // 第一列
Key_New = P3 & 0X0F;
P44 = 1; P42 = 0; P35 = 1; P34 = 1; // 第二列
Key_New = (Key_New << 4) | (P3 & 0X0F);
P44 = 1; P42 = 1; P35 = 0; P34 = 1; // 第三列
Key_New = (Key_New << 4) | (P3 & 0X0F);
P44 = 1; P42 = 1; P35 = 1; P34 = 0; // 第四列
Key_New = (Key_New << 4) | (P3 & 0X0F);
switch(~Key_New)
{
case 0x8000: Key_Value = 1; break;
case 0x4000: Key_Value = 2; break;
case 0x2000: Key_Value = 3; break;
case 0x1000: Key_Value = 4; break;
case 0x0800: Key_Value = 5; break;
case 0x0400: Key_Value = 6; break;
case 0x0200: Key_Value = 7; break;
case 0x0100: Key_Value = 8; break;
case 0x0080: Key_Value = 9; break;
case 0x0040: Key_Value = 10; break;
case 0x0020: Key_Value = 11; break;
case 0x0010: Key_Value = 12; break;
case 0x0008: Key_Value = 13; break;
case 0x0004: Key_Value = 14; break;
case 0x0002: Key_Value = 15; break;
case 0x0001: Key_Value = 16; break;
default : Key_Value = 0;
}
return Key_Value;
}
unsigned char LongOrShort()
{
unsigned int TimeCount = 0;
unsigned int EnterFlag = 0;
while(Key_Scan() != 0)
{
TimeCount++;
EnterFlag = 1;
Delay(1);
}
if(TimeCount<500 & EnterFlag == 1)
{
TimeCount = 0;
EnterFlag = 0;
return 0;
}
else if(TimeCount>500 & EnterFlag == 1)
{
TimeCount = 0;
EnterFlag = 0;
return 1;
}
return IFLong_OutPut;
}
void main()
{
while(1)
{
if(Key_Scan()) Key_OutPut = Key_Scan();
IFLong_OutPut = LongOrShort();
if(IFLong_OutPut){P2 = (P2 & 0x1f) | 0x80;P0 = 0;}//长按点亮所有LED,反之关闭所有
else {P2 = (P2 & 0x1f) | 0x80;P0 = 0xFF;}
smg_bit(1,Key_OutPut/10);//显示按键编号
smg_bit(2,Key_OutPut%10);
}
}
|