将J5的KBD接在一起,使用矩阵按键。就是1.2接在一起。
现在8个I/O口控制16个按键。P34,P35,P42,P44控制四列,单片机通过这四个I/O输出高低电平。P30,P31,P32,P33控制四行,单片机通过这四个I/O接收高低电平。通过这种方式,单片机进行按键扫描。
具体来说,就是先给P44一个低电平,P34,P35,P42一个高电平,这个时候看P30,P31,P32,P33,如果P30给单片机一个低电平,那么表示S7按下,以此类推。
总结来说,按键扫描就是给a列低电平,其实三列高电平,如果b行是低电平,就是a列b行的按键被按下。
2.独立按键将J5的BTN接在一起,使用独立按键,就是2.3接在一起。
独立按键由四个一列的按键组成。
独立按键由于2.3接在一起,默认这列是低电平,然后看那行低电平,就是对应的按键。
总结来说,独立按键扫描就是那行低电平,就是那行对应的按键被按下。
二.按键模块化编程 1.按键模块化编程原理由于矩阵按键和独立按键扫描原理差不多,就不分开编程了。
在蓝桥杯单片机开发板中,按键是一个特殊的外设,一般通过它将其他的外设连接起来。例如:按下S7,LED全亮。
所以说,在按键编程时,不仅要编写按键的模块化代码,还要有一个模板来方便各种外设调用。
2.按键模块化编程代码 (1)按键扫描部分//key.c头文件代码部分
#include "key.h"
//根据考题决定是编写独立按键还是矩阵键盘
//--独立按键
unsigned char Key_Read_BTN(void)//这个独立按键结构简单,代码方便。
{
unsigned char Key_Value;
if(P30 == 0) Key_Value = 7;
else if(P31 == 0) Key_Value = 6;
else if(P32 == 0) Key_Value = 5;
else if(P33 == 0) Key_Value = 4;
else Key_Value = 0;
return Key_Value;
}
//--矩阵键盘
unsigned char Key_Read(void)/*这个思路是先扫描一列,然后接收P3的低四位,
P3 & 0X0F就是将P3的高四位清空,低四位保持不变。然后让这个低四位左移,而低
四位可以代表那一行的按键按下。在keil中,unsigned int是16位变量,通过不断
的左移,这个变量前四位是扫描第1列时P3的后四位,以此类推。这个变量就储存着
按下的按键位置。*/
{
unsigned int Key_New;
unsigned char Key_Value;
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 = 4; break;
case 0x4000: Key_Value = 5; break;
case 0x2000: Key_Value = 6; break;
case 0x1000: Key_Value = 7; break;
case 0x0800: Key_Value = 8; break;
case 0x0400: Key_Value = 9; break;
case 0x0200: Key_Value = 10; break;
case 0x0100: Key_Value = 11; break;
case 0x0080: Key_Value = 12; break;
case 0x0040: Key_Value = 13; break;
case 0x0020: Key_Value = 14; break;
case 0x0010: Key_Value = 15; break;
case 0x0008: Key_Value = 16; break;
case 0x0004: Key_Value = 17; break;
case 0x0002: Key_Value = 18; break;
case 0x0001: Key_Value = 19; break;
default : Key_Value = 0;
}
return Key_Value;
}
//key.h头文件代码部分
#include "STC15F2K60S2.H"
unsigned char Key_Read_BTN(void);//独立按键
unsigned char Key_Read(void);//矩阵键盘
(2)按键消抖
通过上面的代码以及注释,我们编写了一个只要按下s几按键,key—down就是多少的代码,但是实际上并非如此。通常的按键所用开关为机械d性开关,当按键按下、抬起时,电平短时间内会发生几次跳变,按键在闭合及断开的瞬间均伴随有一连串的抖动。
抖动很有可能带来一次按键按下,结果单片机执行多次指令,所以我们要做消抖的工作。常用的是通过延时函数进行消抖,不过效果不太好,还会造成性能浪费。蓝桥杯官方采用”三行代码“进行按键消抖。
//三行代码
Key_Value = Key_Read();
Key_Down = Key_Value & (Key_Old ^ Key_Value);//下降沿,按得哪个按键,这个值就是几 ^是异或符号,当两个数异或时,会把这两个数按位异或,例如 7^8 = 00000111 ^ 00001000 = 00001111 = 15
Key_Old = Key_Value;//检测电平,一直按着一直等于一个数
- 正常情况下按键没有按下,Key_Value = 0,Key_Old = 0 。
- 当有按键按下,例如S7,Key_Value = 7,Key_Down = 00000111 & (00000111 ^ 00000000)= 00000111 = 7 Key_Old = 7 。
- 当按住按键不动时,Key_Value = 7,Key_Down = 00000111 & (00000111 ^ 00000111)= 00000000 = 0 Key_Old = 7 。
- 在按键抬起时,Key_Value = 0,Key_Down = 00000000 & (00000111 ^ 00000000)= 00000000 = 0 Key_Old = 7 。
也就是说,Key_Down 是一个判断下降沿的变量,只有按键处于按下的过程Key_Down 才会被赋值,其他情况下Key_Down 是0 。
三行代码提供消抖的作用,同时三行代码具有很高的灵活性,通过一些变化,就可以实现单击,双击,长按等功能。
同时,在按键扫描的部分,我们需要搭配定时器来进行扫描,可以保证按键响应及时,这一部分在定时器部分在仔细讲解。
wn 才会被赋值,其他情况下Key_Down 是0 。==
三行代码提供消抖的作用,同时三行代码具有很高的灵活性,通过一些变化,就可以实现单击,双击,长按等功能。
同时,在按键扫描的部分,我们需要搭配定时器来进行扫描,可以保证按键响应及时,这一部分在定时器部分在仔细讲解。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)