蓝桥杯单片机按键

蓝桥杯这块板子有矩阵按键和独立按键,可以根据换跳帽来切换,下面简单介绍一下这两种按键的程序和基本的原理。

其他51的板子原理也基本相同,下面的代码也可以参考。

独立按键

相对于矩阵按键,独立按键简单很多,就只有四个按钮,判断四个按键哪个被按下的情况较为简单

独立按键的写法也不止一种,这里就介绍两种

方法一:

实现比较简单,就是一个个判断,检测到为低电平的话就判断按键按下了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//先对每个按键进行位定义
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

void key_scan()
{
//然后逐一判断哪个按键被按下
if(S4 == 0)//按键按下之后会检测到低电平,所以对应引脚检测到低电平就视为按键被按下了
{
delay(5);//延时消抖
if(S4 == 0)//再次检测电平信号
{
//按键具体功能的实现
}
}
else if(S5 == 0)
{
delay(5);
if(S5 == 0)
{
//按键具体功能的实现
}
}
else if(S6 == 0)
{
delay(5);
if(S6 == 0)
{
//按键具体功能的实现
}
}
else if(S7 == 0)
{
delay(5);
if(S7 == 0)
{
//按键具体功能的实现
}
}
}

方法二:

检测P3口的低四位,若S4被按下,则第四位P3^3为0,所以P3&0xf的值为0x07,其他三个按键也以此类推。这种方法把按键的检测程序和功能程序分开了,如果不想要按下按键后按键里面的功能一直执行的话,按键功能每次执行完要把按键的值归零,否则单片机会一直执行那个按键里面的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
char press_flag = 0,key_value = 0;//按下标志

void key_scan()
{
if((P3&0x0f) != 0x0f&&!press_flag)
{
delay(50);
if((P3&0x0f) != 0x0f&&!press_flag)
{
press_flag = 1;//按键被按下过后将按下标志置为1
switch(P3&0x0f)//按下的按键对应的为0,与0x0f相与可以判断哪个按键被按下
{
case 0x07: key_value = 4; break;
case 0x0b: key_value = 5; break;
case 0x0d: key_value = 6; break;
case 0x0e: key_value = 7; break;
}
}
}
if((P3&0x0f) == 0x0f&&press_flag)//当没有按键按下但是按下标志为1的时候,要将按下标志置为0
press_flag = 0;
}

void key_func()//按键的功能函数
{
switch(key_value)
{
case 4: /*按键具体功能*/ key_value = 0; break;
case 5: /*按键具体功能*/ key_value = 0; break;
case 6: /*按键具体功能*/ key_value = 0; break;
case 7: /*按键具体功能*/ key_value = 0; break;
}
}

矩阵按键

相对于独立按键来说,矩阵按键相对是要复杂一点,这里就介绍一种方法

原理:

这个方法和上面独立按键的方法2实现的思路差不多。因为51单片机的资源很有限,所以这里用了八个引脚来实现一个4×4的矩阵按键。这里对照一下原理图:

image.png

第一步:列扫描,先将P3的低四位置为0,高四位置为1,但是这款单片机的P36和P37被P42和P44代替了,所以P42和P44要单独位定义,然后将其置为1。初始值设置完之后就要进行检测了,因为P3的低四位为0,所以当按键按下时接到对应列的那条线会被拉到低电平P44对应的是第一列,其他参照上面的原理图以此类推。

第二部:行扫描,反过来,将P3的低四位置为1,高两位以及P42和P44置为0,哪一行的按键被按下对应行的值会被置为0,这一步和上面独立按键的扫描相似。

经过行和列的扫描就可以确定下来是那个一个按键被按下了,行和列就可以看成是横坐标和纵坐标,这里是先确定纵坐标,再确定横坐标,通过这样的一个坐标就可以确定被按下按键的位置。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
sfr P3 = 0xc0;
sbit P42 = P4^2;
sbit P44 = P4^4;
sbit P34 = P3^4;
sbit P35 = P3^5;
char key_value = 0,key_past = 0,key_now = 0;

void key_scan()
{
P3 = 0xf0;//将低四位置为0,高四位和P42、P44置为1
P42 = 1;
P44 = 1;
if(P42 != 1||P44 != 1||P34 != 1||P35 != 1)//如果有按键被按下对应引脚会被置为0
{
key_past = key_now;
key_now = 1;
if(!(key_past == 1&&key_now == 1))//按键的松手检测
delay(5);
if((P42 != 1||P44 != 1||P34 != 1||P35 != 1)&&!(key_past == 1&&key_now == 1))
{
if(P44 == 0) key_value = 4;
else if(P42 == 0) key_value = 8;
else if(P35 == 0) key_value = 12;
else if(P34 == 0) key_value = 16;
P3 = 0x0f;
P42 = 0;
P44 = 0;
switch(P3&0x0f)
{
case 0x07: key_value += 0; break;
case 0x0b: key_value += 1; break;
case 0x0d: key_value += 2; break;
case 0x0e: key_value += 3; break;
}
}
}
else
{
key_past = key_now;
key_now = 0;
}
}

这里没有写按键的功能函数,这个就和独立按键的第二种方法类似,传入key_value的值然后执行对应的功能函数,执行完一次之后如果不想要一直执行的话就在执行完之前将key_value的值归零。