打印
[经验分享]

4X4矩阵键盘

[复制链接]
2064|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
bartonalfred|  楼主 | 2024-12-16 23:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
P3口接矩阵键盘,其中P3.0~P3.3接行线,P3.4~P3.7接列线,P0口接共阴极7段数码管。

反转法的原理:

反转法就是通过给单片机的端口赋值两次,最后得出所按键的值的一种算法。

给P3口赋值0x0f,即00001111,假设0键按下了,则这时P3口的实际值为00001110;

给P3口再赋值0xf0,即11110000,如果0键按下了,则这时P3口的实际值为11100000;

通过这两次P3口的实际值相加得11101110,即0xee。

由此我们便得到了按下0键时所对应的数值0xee,以此类推可得出其他15个按键对应的数值,有了这种对应关系,矩阵键盘编程问题也就解决了,也就是程序的算法已经有了。

(上述方法来源于网络)

好了下面直接进入程序

#include                //头文件

#define uchar unsigned char         //宏定义

#define uint unsigned int

uchar key,n,i;                 //定义变量

uchar code table[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};        //反转法矩阵键盘的各个按键的计算值

uchar code yin[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};               //共阴极数码管显示0~F

void delay(uint i)    //延时函数

{

  while(i--);

}

void keyscan()

{

uchar l,h,i;                        //定义局部变量,用l得出低4位的值,用h得出高4位的值

P3=0x0f;                           //给P3赋值00001111

l=P3&0x0f;

if(l!=0x0f)

{

delay(100);   //延迟后再检测

P3=0x0f;                                      

l=P3&0x0f;

if(l!=0x0f)

{

h=P3&0xf0; //若有键按下,得出高四位的值

P3=0xf0;                         //给P3赋值11110000

h=P3&0xf0;                       //若有键按下,得出低四位的值

key=l+h;                         //高4位的值与低4位的值相加

for(i=0;i

{

if(key==table[i])            //通过查表得出n的值

n=i;

}

}

}

}

void main()

{

while(1)

   {

          keyscan();

    for(i=0;i   //送入位选信号控制数码管

{

P2_6=1;P2_7=0;

P0=yin[n];

P2_6=0;P2_7=1;

switch(i)

{

case 0:P0=0xfe;break;

case 1:P0=0xfd;break;

case 2:P0=0xfb;break;

case 3:P0=0xf7;break;

case 4:P0=0xef;break;

case 5:P0=0xdf;break;

default:break;

}

P2_6=0;P2_7=0;

delay(100);

     }

   }

}

使用特权

评论回复
沙发
uiint| | 2025-2-4 16:34 | 只看该作者
4行和4列分别连接到微控制器的I/O引脚。
行线通常配置为输出,列线配置为输入,并启用内部上拉电阻。

使用特权

评论回复
板凳
belindagraham| | 2025-2-4 19:32 | 只看该作者
逐列将列线依次置低电平,读取行线,如果某一条行线为低电平,则说明该行线与当前为低电平的列线交叉点处的按键被按下。

使用特权

评论回复
地板
zerorobert| | 2025-2-4 21:48 | 只看该作者
为了避免按键抖动带来的问题,需要在软件层面引入去抖动技术,通常会设置一个延时,当检测到按键动作后,软件会等待一段设定的时间后再确认按键信号

使用特权

评论回复
5
cashrwood| | 2025-2-4 22:52 | 只看该作者
由于按键在按下和释放时会产生机械抖动,可能导致多次触发按键事件。因此,在检测到按键按下后,需要进行消抖处理,一般采用软件延时的方法,延时时间通常设置在 10 - 20ms。

使用特权

评论回复
6
backlugin| | 2025-2-5 08:59 | 只看该作者
扫描过程中所有行线都设置为输出,可能会增加功耗。可以通过降低扫描频率或使用中断来减少功耗。

使用特权

评论回复
7
earlmax| | 2025-2-5 11:06 | 只看该作者
const int rowPins[4] = {2, 3, 4, 5}; // 行线连接到数字引脚2, 3, 4, 5
const int colPins[4] = {6, 7, 8, 9}; // 列线连接到数字引脚6, 7, 8, 9

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

void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 4; i++) {
    pinMode(rowPins[i], OUTPUT);
    digitalWrite(rowPins[i], HIGH); // 初始化行线为高电平
  }
  for (int i = 0; i < 4; i++) {
    pinMode(colPins[i], INPUT_PULLUP); // 初始化列线为输入,并启用内部上拉电阻
  }
}

void loop() {
  char key = scanKeyboard();
  if (key != 0) {
    Serial.println(key);
  }
}

char scanKeyboard() {
  for (int row = 0; row < 4; row++) {
    digitalWrite(rowPins[row], LOW); // 设置当前行为低电平
    for (int col = 0; col < 4; col++) {
      if (digitalRead(colPins[col]) == LOW) {
        delay(50); // 延时消抖
        if (digitalRead(colPins[col]) == LOW) {
          digitalWrite(rowPins[row], HIGH); // 恢复行线为高电平
          return keys[row][col];
        }
      }
    }
    digitalWrite(rowPins[row], HIGH); // 恢复行线为高电平
  }
  return 0; // 没有按键按下
}

使用特权

评论回复
8
lzmm| | 2025-2-5 13:08 | 只看该作者
软件扫描算法遍历矩阵键盘的所有行,每次将一行设为低电平,其他行为高电平,然后检查每一列是否因为按键被按下而变为低电平

使用特权

评论回复
9
everyrobin| | 2025-2-5 16:03 | 只看该作者
按键去抖动的时间需要根据实际情况进行调整,以确保按键的稳定性和准确性。

使用特权

评论回复
10
wilhelmina2| | 2025-2-5 18:11 | 只看该作者
先将行线作为输出,列线作为输入,将所有行线置为低电平,检测列线电平,若有列线变为低电平,记录该列号;然后将行线和列线的输入输出方向反转,将所有列线置为低电平,检测行线电平,记录该行号,根据行号和列号确定按键位置。

使用特权

评论回复
11
nomomy| | 2025-2-5 20:08 | 只看该作者
为了确保在没有按键按下时列线处于高电平状态,通常会在列线上连接上拉电阻。上拉电阻的阻值一般选择在 4.7KΩ - 10KΩ 之间。

使用特权

评论回复
12
dspmana| | 2025-2-6 11:43 | 只看该作者
4X4矩阵键盘是一种常见的输入设备,广泛应用于各种嵌入式系统、电子制作项目以及教学实验中。它由4条行线和4条列线交叉组成,总共能够提供16个按键。这种设计简单、成本低廉,适合初学者理解电路和编程的基础知识。

使用特权

评论回复
13
wengh2016| | 2025-2-6 12:06 | 只看该作者
4x4矩阵键盘需要8个I/O引脚,如果引脚资源紧张,可以考虑使用更高级的扫描算法或硬件解码器。

使用特权

评论回复
14
ingramward| | 2025-2-6 15:04 | 只看该作者
配置微控制器的I/O口,将行线设置为输出模式,列线设置为输入模式。
初始化相关变量和计数器。

使用特权

评论回复
15
deliahouse887| | 2025-2-6 15:49 | 只看该作者
在4X4矩阵键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。列线通过电阻接正电源,行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。当有按键按下时,相应的行线和列线会连通,从而可以通过检测行线和列线的状态来判断哪个按键被按下。

使用特权

评论回复
16
olivem55arlowe| | 2025-2-6 18:49 | 只看该作者
将矩阵键盘集成到嵌入式系统中,进行硬件连接、软件编程和系统集

使用特权

评论回复
17
houjiakai| | 2025-2-13 18:47 | 只看该作者

# define uint unsigned int
# define uchar unsigned char

uchar code table[4][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12},
    {13, 14, 15, 16}
};

void delay(uint z) {
    uint x, y;
    for(x=z; x>0; x--)
        for(y=110; y>0; y--);
}

uchar get_key() {
    uchar i, j;
    for(i=0; i<4; i++) {
        P1 = 0xF0 | (1 << i);
        for(j=0; j<4; j++) {
            if((P1 & (1 << (j+4))) == 0) {
                delay(50);
                if((P1 & (1 << (j+4))) == 0)
                    return table[i][j];
            }
        }
    }
    return 0;
}

void main() {
    while(1) {
        uchar key = get_key();
        if(key != 0) {
            P2 = key;  // 将按键值显示在P2口连接的设备上
            delay(500);
        }
    }
}

使用特权

评论回复
18
jkl21| | 2025-2-13 20:06 | 只看该作者
4X4矩阵键盘的列线接到单片机的低4位I/O口,行线接到单片机的高4位I/O口。例如,使用51单片机时,可以将键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。

使用特权

评论回复
19
mollylawrence| | 2025-2-13 20:47 | 只看该作者
键盘的电源和接地良好,以避免因电源问题导致的按键失灵或误判。

使用特权

评论回复
20
averyleigh| | 2025-2-14 09:32 | 只看该作者
4×4矩阵键盘,又称为行列式键盘,由4条行线和4条列线组成,共形成16个交叉点,每个交叉点上设置一个按键。这种设计能够有效地提高I/O口的利用率,节约单片机的资源。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

1377

帖子

1

粉丝