学习蓝桥杯单片机-矩阵键盘的使用:线反转法、三步消抖、长按与短按处理

此片文章用于记录蓝桥杯单片机的学习

篮球杯单片机上的矩阵按键原理图如下:

  使用矩阵键盘时,要将跳线帽J5跳至KBD模式。

  值得注意的是,若开发板上的单片机使用的为STC15,那么以上原理图适用。如果单片机为IAP15,则在上述原理图中,要将P36换成P42,P37换成P44。

  修改如下(IAP15):

   常用的矩阵键盘扫描方式有行扫描法和线反转法,在比赛过程中,为了提高键盘的扫描速度和程序的运行效率,这里建议采用三步消抖法加线反转法,这样程序运行效率较高,并且支持按键的短按和长按。

  线反转法原理简单,配合三步消抖即可支持按键的快速扫描和长按与短按。

  矩阵键盘程序如下:

KET4X4.c(IAP15)

#include <STC15F2K60S2.H>
#define u8 unsigned char
#define KEY_4X4  //定义KEY_4X4就代表使用矩阵按键模式
#ifdef KEY_4X4
u8 Key_4_value;          //用来记录键值
bit Key_time_falg;       //用来做为计时标志位
unsigned long Key_time;  //用来记录按键按下的时间,进而判断是长按还是短按

u8 Key_scan4x4() {
  u8 Key_temp, Key_value;
  P3 = 0x0f;
  P42 = 0;
  P44 = 0;
  Key_temp = (P3 & 0x0f);
  switch (Key_temp) {
    case (0x07): Key_value = 4; break;  //第四行按下  0000 0111
    case (0x0b): Key_value = 5; break;  //第三行按下  0000 1011
    case (0x0d): Key_value = 6; break;  //第二行按下  0000 1101
    case (0x0e): Key_value = 7; break;  //第一行按下  0000 1110
    default: Key_value = 0; break;
  }
  P3 = 0xf0;  //1111 0000
  P42 = 1;
  P44 = 1;
  Key_temp = (P3 & 0xf0);
  if (P44 == 0) {  //第一列按下
    Key_value = Key_value;
  } else if (P42 == 0) {  //第二列按下
    Key_value = Key_value + 4;
  } else if (Key_temp == 0xd0) {  //第三列按下
    Key_value = Key_value + 8;
  } else if (Key_temp == 0xe0) {  //第四列按下
    Key_value = Key_value + 12;
  }

  return Key_value;
}
void Read_key4x4() {
  u8 Key_up, Key_down, Key_temp;
  static u8 Key_old = 0;

  Key_temp = Key_scan4x4();
  Key_down = Key_temp & (Key_old ^ Key_temp);  //三步消抖法,Key_donw是按键按下的键值 Key_up是按键弹上的键值 Key_old用来记录上一次的键值
  Key_up = ~Key_temp & (Key_old ^ Key_temp);
  Key_old = Key_temp;

  if (Key_down)  //如果需要在按键按下就立马执行 则可以在这里对把Key_donw的值给Key_4_value
  {
    Key_time_falg = 1;  //开始计时
  }
  if (Key_up)  //这里是按键按下 并松手了才执行
  {
    Key_time_falg = 0;    // 已松手 结束计时
    if (Key_time >= 500)  //  如果按下的时间大于500,则为长按 否则为短按
    {
      Key_4_value = Key_up + 100;
      Key_time = 0;
    } else {
      Key_4_value = Key_up;
      Key_time = 0;
    }
  }
}
#endif

KET4X4.h

#ifndef _KEY4X4_H_
#define _KET4X4_H_
#define u8 unsigned char

u8 Key_scan4x4();
void Read_key4x4();

#endif

现在,在主程序中配置好定时器和中断即可:

Main.c

#include <STC15F2K60S2.H>
#include "intrins.h"
// #include "74LS138.h"
// #include "Key4.h"
#include "KEY4X4.h"
extern u8 Key_4_value;          //记录键值
extern unsigned long Key_time;  //记录按下的时间
extern bit Key_time_falg;       //计时标志位
void Timer0Init(void)           //1毫秒@11.0592MHz
{
  AUXR |= 0x80;  //定时器时钟1T模式
  TMOD &= 0xF0;  //设置定时器模式
  TMOD |= 0x01;  //设置定时器模式
  TL0 = 0xCD;    //设置定时初值
  TH0 = 0xD4;    //设置定时初值
  TF0 = 0;       //清除TF0标志
  EA = 1;
  ET0 = 1;
  TR0 = 1;  //定时器0开始计时
}
void main() {
  //  init_ls138();               // 上电关闭所有外设
  Timer0Init();
  while (1) {
    if (Key_4_value == 11)          //按键S11被按下
    {                               /*做事情*/
    } else if (Key_4_value == 10)   //按键S10被按下
    {                               /*做事情*/
    } else if (Key_4_value == 18)   //按键S18被按下
    {                               /*做事情*/
    } else if (Key_4_value == 19)   //按键S19被按下
    {                               /*做事情*/
    } else if (Key_4_value == 111)  //按键S11被长按
    {                               /*做事情*/
    } else if (Key_4_value == 110)  //按键S10被长按
    {                               /*做事情*/
    } else if (Key_4_value == 118)  //按键S18被长按
    {                               /*做事情*/
    } else if (Key_4_value == 119)  //按键S19被长按
    {                               /*做事情*/
    }
  }
}
void Tim0_interrupt() interrupt 1 {
  static u8 i = 0;
  TL0 = 0xCD;  //设置定时初值
  TH0 = 0xD4;  //设置定时初值
  i++;
  if (Key_time_falg == 1) {
    Key_time++;
  }
  if (i >= 10) {  //10ms按键扫描一次
    Read_key4x4();
    i = 0;
  }
}

  在程序中,只需要判断KEY-4-value的值即可分辨按键哪个被按下,分别对应S4~S19,长按的键值为原本的键值加上100。

蓝桥杯单片机学习日记1-LED 蜂鸣器 继电器 数码管的简单驱动

蓝桥杯单片机学习日记2-独立按键的短按,长按的使用

物联沃分享整理
物联沃-IOTWORD物联网 » 学习蓝桥杯单片机-矩阵键盘的使用:线反转法、三步消抖、长按与短按处理

发表评论