上期学习了数码管的静态显示,这次我们来学习独立按键&矩阵按键
独立按键
原理很简单,当作为独立按键使用时,跳线帽的23接在一起,此时按键如果按下,则按键连接的IO口电平会被拉低,通过捕获IO的电平变化,就可以判断按键是否按下。
按键消抖
什么是按键消抖?按键为什么会有抖动?
通常的按键所用开关为机械弹性开关。由于机械触电的弹性作用,按键在闭合及断开的瞬间均伴随有一连串的抖动。键抖动会引起一次按键被误读多次。为了确保CPU对键的一次闭合仅作一次处理,必须去除抖动。
如何消抖?
硬件消抖:硬件消抖的典型做法是:采用 R-S触发器 或RC积分电路。在没有MCU的情况下通常使用这种方法,但在嵌入式开发中,我们比较常用的时软件消抖。
软件消抖:软件消抖是当检测出键闭合后执行一个10ms~20ms的延时程序,再一次检测键的状态,如仍保持闭合状态,则确认真正有按键按下。
矩阵按键
作为矩阵按键使用时,跳线帽的12脚连接在一起。
矩阵按键的优点:可以通过比较少的IO实现对多个按键的控制,节省IO口。
缺点:在使用时需要对按键进行扫描。
扫描
对于独立按键,它的每一个IO都对应着一行或一列,通过读取按键按下时的行和列,就可以确定是哪一个按键按下。
扫描就是对按键的每一行(列)进行扫描,从而得到按键按下的行(列),从而确定是否有按键按下,以及按键按下的键码值。目前按键扫描的方法,主要分为行扫描和列扫描两种。
所谓行扫描就是,先把每一行和每一列的上的电平拉高,然后分别把每一行的电平依次拉低,去检测每一个列上的电平是否跟着被拉低,如果被拉低,说明按键按下,则可以去读到当前的行和列,计算出按下的键码值。
列扫描则和行扫描的逻辑相反,这里不做赘述。
代码实现
1.main.c
#include <STC15F2K60S2.H>
#include <INTRINS.h>
#include "Key.h"
#include "LS138.h"
//效果:当有按键按下时,会在数码管上显示当前按下按键的键码值
//当没有按键按下时,数码管会显示上一次按下的键码值
void main()
{
unsigned int i =0;
LS138_Init();
Key_Init(); //初始化函数
while(1)
{
if(Get_KeyBoard_Num()) //判断矩阵按键是否有按下
{
i = Get_KeyBoard_Num(); //如果按下则,改变当前变量的值,
}
SEG_Write_Num(i); //通过数码管显示矩阵按键按下的键码值
}
}
2.Key.h
#ifndef __KEY_H_
#define __KEY_H_
#include <STC15F2K60S2.H>
#include <INTRINS.h>
sbit Key7 = P3^0;
sbit Key6 = P3^1;
sbit Key5 = P3^2;
sbit Key4 = P3^3;
sbit Col1 = P4^4;
sbit Col2 = P4^2;
sbit Col3 = P3^5;
sbit Col4 = P3^4;
#define Row1 Key4
#define Row2 Key5
#define Row3 Key6
#define Row4 Key7
//延时函数,可以延时xms的时间
void Delayxms(unsigned int x); //@11.0592MHz
//初始化函数
void Key_Init(void);
//按键扫描函数,由按键按下时返回值为1,否则为0
unsigned char Key_Scan(void);
//获取当前按键按下的数值,返回结果为4~7
//当没有按键按下是,返回值为0
//函数内部由两种实现方法,一直延时,一种不延时。可以按需要使用
unsigned int Get_Key_Num(void);
//获取当前矩阵按键中按下健的值
//返回值为4~19
//当没有按键按下时,返回值为0
unsigned int Get_KeyBoard_Num(void);
#endif /*__KEY_H_*/
这里有一个Delayxms()延时函数,可以延时xms.这个不是static 修饰的,外部可调用
3.Key.c
#include "Key.h"
//延时函数,可以延时xms的时间
void Delayxms(unsigned int x) //@11.0592MHz
{
unsigned char i,j,k;
for(k=0;k<x;k++)
{
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
//初始化函数
void Key_Init(void)
{
Key7 = Key6 = Key5 = Key4 =1;
Col1 = Col2 = Col3 = Col4=1;
}
//按键扫描函数,由按键按下时返回值为1,否则为0
unsigned char Key_Scan(void)
{
static unsigned char Key_Count =0;
if(Key7==0 | Key6==0 | Key5==0 | Key4==0 )
{
Key_Count++;
Delayxms(1);
if(Key_Count >= 100)
{
return 1;
Key_Count=0;
}
}
return 0;
}
//获取当前按键按下的数值,返回结果为4~7
//当没有按键按下是,返回值为0
//函数内部由两种实现方法,一直延时,一种不延时。可以按需要使用
unsigned int Get_Key_Num(void)
{
#if 1 //这个是没有延时的,需要多次进入函数。
static unsigned char Key_Count = 0;
if(Key7==0 | Key6==0 | Key5==0 | Key4==0 )
{
Key_Count++;
Delayxms(1);
if(Key_Count >= 100)
{
if(Key7 == 0)
{
return 7;
}
if(Key6 == 0)
{
return 6;
}
if(Key5 == 0)
{
return 5;
}
if(Key4 == 0)
{
return 4;
}
Key_Count=0;
}
}
return 0;
#if 0 //这个是有延时的,只需要进入函数一次,但是会导致系统Delay在函数内部
if(Key7==0 | Key6==0 | Key5==0 | Key4==0 )
{
Delayxms(20);
if(Key7 == 0)
{
while(!Key7)
{
}
return 7;
}
if(Key6 == 0)
{
while(!Key6)
{
}
return 6;
}
if(Key5 == 0)
{
while(!Key5)
{
}
return 5;
}
if(Key4 == 0)
{
while(!Key4)
{
}
return 4;
}
}
else
{
return 0;
}
#endif
}
//获取当前矩阵按键中按下健的值
//返回值为4~19
//当没有按键按下时,返回值为0
unsigned int Get_KeyBoard_Num(void)
{
unsigned char i;
for(i=0;i<4;i++)
{
P3 =0x03F;
Col1 = Col2 = 1;
P3 =~(0x08>>i); //Rowi = 1; //第一行为0
// Delayxms(1);
if(Col1==0 | Col2==0 | Col3==0 | Col4==0) //扫描每一列是否有按键按下
{
Delayxms(20);
if(~Col1)
{
return i+4;
}
if(~Col2)
{
return i+8;
}
if(~Col3)
{
return i+12;
}
if(~Col4)
{
return i+16;
}
}
}
return 0;
}
这里面获取独立按键的键码值的函数,我写了两种实现方式,
区别就是一个用到的软件消抖(使用了延时函数),另一个没有使用软件消抖,但是需要多次调用进入函数才可以使用,具体实现方法可以自己看代码的。需要使用哪一种方法,可以自行选择。
为什么这么写:在后面如果学习使用到了定时器的话,在函数内部进行延时,可能会影响其他对时间要求比较严格的模块。造成不必要的损失。文章来源:https://www.toymoban.com/news/detail-414223.html
总结
独立按键&矩阵按键这一部分比较简单,原理也容易看懂,我这里只实现了基本的按键控制功能,大家也可以尝试着去实现,长按、短按、双击、等功能,我就不再去多写啦。好好努力吧!
文章来源地址https://www.toymoban.com/news/detail-414223.html
到了这里,关于蓝桥杯单片机学习4——独立按键&矩阵按键的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!