Arduino驱动4X4矩阵薄膜按键

Arduino驱动4X4矩阵薄膜按键

  • 参考网站:

  • 使用Arduino IO口内部上拉功能

  • 那天看到别人的51有个4 * 4矩阵,想到按键自己还有一个4 * 4***矩阵薄膜按键***,于是就想要玩一下

  • 其实挺简单的!

原理图

img

img

我的薄膜按键

接线按自己的宏定义将行引脚连续接,列引脚连续接。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ebWmIWFu-1580626011386)(C:\Users\fengyun323\Documents\Tencent Files\1920922256\FileRecv\MobileFile\IMG_20190716_104758.jpg)]

按键上拉

Arduino的ATmega328P芯片由内部上拉功能,但没有下拉功能,内部电路如图:

img

上拉电阻介绍

在数字电路中,上拉电阻(英语:Pull-up resistors)是当某输入端口未连接设备或处于高阻抗的情况下,一种用于保证输入信号为预期逻辑电平的电阻元件。他们通常在不同的逻辑器件之间工作,提供一定的电压信号。

上拉电阻作用

在上拉电阻所连接的导线上,如果外部组件未启用,上拉电阻将“微弱地”将输入电压信号“拉高”。当外部组件未连接时,对输入端来说,外部“看上去”就是高阻抗的。这时,通过上拉电阻可以将输入端口处的电压拉高到高电平。如果外部组件启用,它将取消上拉电阻所设置的高电平。通过这样,上拉电阻可以使引脚即使在未连接外部组件的时候也能保持确定的逻辑电平。

例程

void setup ()
{
  pinMode(2,INPUT_PULLUP); //将2号管脚设置为输入并且内部上拉模式
  pinMode(12,OUTPUT);
}
 
void loop()
{
  int n =digitalRead(2); //创建一个变量n,将4号数字口的状态采集出来赋值给他。
  if (n==LOW) //判断n是否为低电平,如果是执行下面的语句,不是则跳过。
  {
    delay(1000);
    digitalWrite(12,HIGH);
    delay(5000);
    digitalWrite(12,LOW);
  }
}
pinMode(2,INPUT_PULLUP);

定义了2号引脚为INPUT_PULLUP模式意味着该引脚为输入模式,并且被拉高,这就是为什么按键接到了GND
当按键按下时,2号管脚变为GND,这样就完成了按键的功能
因为ATmega328P单片机管脚默认是高电平,所以我们通常设定低电平有效,这样就可以避免误触发

我的想法

建立一个4*4矩阵列表
初始化行引脚为上拉输入
初始化列引脚为推挽输出
使能一个列引脚为低电平,其余高电平
扫描矩阵,循环读取行引脚状态
通过串口提醒发送信息给电脑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ojgnZnqw-1580626011387)(C:\Users\fengyun323\AppData\Roaming\Typora\typora-user-images\1563247741759.png)]

上图可见我已成功实现矩阵按键检测功能!!!

我的代码(老)

char key[4][4] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

int symbol = 0;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  for(int i=2;i<=5;i++){
    pinMode(i,INPUT_PULLUP);
  }
  for(int i=6;i<=9;i++){
    pinMode(i,OUTPUT);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  for(int j=6;j<=9;j++){
    for(int i=6;i<=9;i++){
      digitalWrite(i,HIGH);
    }
    digitalWrite(j,LOW);
    symbol = 0;
    for(int i=0;i<5000;i++){
      for(int k=2;k<=5;k++){
        if(digitalRead(k) == 0){
          for(int t=0;t<100;t++){}
          if(digitalRead(k) == 0)
            symbol = k;
        }
      }
      if(symbol != 0){
        Serial.print(symbol-2);
        Serial.print(' ');
        Serial.println(j-6);
        break;
      }
    }
  }
  
}

后续

4 * 4按键矩阵一些全局变量及宏定义

#define keyboard_line 2
#define keyboard_row 6

char key[4][4] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};//保存矩阵字符

int symbol_line = 0;
int symbol_row = 0;

扫描矩阵函数封装

函数功能:反馈矩阵对应的字符

char keyboard_scan(void)
{
  for(symbol_row=keyboard_row;symbol_row<keyboard_row+4;symbol_row++)
  {
    for(int i=keyboard_row;i<keyboard_row+4;i++)
      digitalWrite(i,HIGH);
    digitalWrite(symbol_row,LOW);
    symbol_line = 0;
    for(int i=0;i<500;i++){
      for(int k=keyboard_line;k<keyboard_line+4;k++)
      {
        if(digitalRead(k) == 0)
        {
          while(1)
          {
            if(digitalRead(k) == 1){
              symbol_line = k;
              break;
            }
          }
        }
      }
      if(symbol_line != 0)
        return key[symbol_line-2][symbol_row-6];
    }
  }
  if(symbol_line == 0)
    return 0;
}

最后改进的代码(完整版)

#define keyboard_line 2
#define keyboard_row 6

char key[4][4] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

int symbol_line = 0;
int symbol_row = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println('W');
  for(int i=keyboard_line;i<keyboard_line+4;i++){
    pinMode(i,INPUT_PULLUP);
  }
  for(int i=keyboard_row;i<keyboard_row+4;i++){
    pinMode(i,OUTPUT);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  char dri = 0;
  dri = keyboard_scan();
  if(dri!=0){
    Serial.println(dri);}
}

char keyboard_scan(void)
{
  for(symbol_row=keyboard_row;symbol_row<keyboard_row+4;symbol_row++)
  {
    for(int i=keyboard_row;i<keyboard_row+4;i++)
      digitalWrite(i,HIGH);
    digitalWrite(symbol_row,LOW);
    symbol_line = 0;
    for(int i=0;i<500;i++){
      for(int k=keyboard_line;k<keyboard_line+4;k++)
      {
        if(digitalRead(k) == 0)
        {
          while(1)
          {
            if(digitalRead(k) == 1){
              symbol_line = k;
              break;
            }
          }
        }
      }
      if(symbol_line != 0)
        return key[symbol_line-2][symbol_row-6];
    }
  }
  if(symbol_line == 0)
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值