C51 单片机矩阵键盘

关于矩阵键盘的扫描,这个简单的问题居然困扰了我一天。扫描原理:输入行值,读取列值;输入列值,读取行值。这是很常用的方法。代码如下:

 //=======================================
  //       矩阵键盘扫描,返回按键码
  //=======================================
  unsigned char KeyScan()
  {
    /*低四位为行线值,高四位为列线值*/
    unsigned char code_h,code_l;
    KeyPort = 0xf0;     //令行线值为0
    code_l=KeyPort&0xf0; //读取列线值
    if(code_l!=0xf0)
    {
       DelayMs(10);//延时10毫秒
       if((KeyPort&0xf0)==code_l)
       { 
         KeyPort=0x0f;//令列线值为0
         code_h=KeyPort&0x0f;//读取行线值
         while(code_h==(KeyPort&0x0f));//while(KeyPort!=0xff); //等待松开按键
         return (code_h|code_l);   //返回组合码
       }
    }
    return 0xff;
  }

困扰我的就是KeyPort = 0xf0 ,我在想为什么用KeyPort &= 0xf0 就不可以。这是一个魔咒,根源是不熟悉矩阵的物理结构以及它和单片机的关系。这没什么必要详述,中咒之人一看便知。但明慧的人自然不会着道,因此也没有必要了解。
以下内容仅提供给和我一样犯迷糊的人。

1.矩阵的结构
矩阵结构示意图

2.矩阵所连接的单片机端口
假如所用端口P3,在扫描过程中P3仅仅是用来检测矩阵的按键状态,P3原有的状态没有任何意义。我就是怕赋值语句改变端口状态才那么纠结。
3.顺便做个笔记
关于16位定时器0初值赋值:

TH0=(65536-3000)>>8;      //重新赋值 3ms,高8
TL0=(65536-3000);         //低8位

网上提到许多取16位数据高8位和低8位的方法,综合比较了一下,还是上面这种简单实在效率。常用的也有下面这种,效率略逊。

TH0=(65536-3000)/256;     //重新赋值 3ms,高8
TL0=(65536-3000)%256;         //低8位
C51单片机矩阵键盘4x4的实现方法如下: 1. 矩阵键盘的原理是将按键按下后的电信号通过行列扫描方式转化为数字信号输入到单片机中。 2. 在C51单片机中,需要将矩阵键盘的行和列分别连接到单片机的GPIO口。 3. 程序中需要循环扫描矩阵键盘的每一行和每一列,检测是否有按键按下。 4. 如果检测到按键按下,就需要通过行列坐标计算出按键的编号,然后将该编号作为输入信号传输给单片机。 5. 单片机在接收到按键信号后,就可以根据程序中预先定义好的按键编号对应功能来执行相应操作。 下面是一个简单的C语言程序示例: ``` #include "reg52.h" sbit Row_1 = P1^0; // 矩阵键盘第1行 sbit Row_2 = P1^1; // 矩阵键盘第2行 sbit Row_3 = P1^2; // 矩阵键盘第3行 sbit Row_4 = P1^3; // 矩阵键盘第4行 sbit Col_1 = P1^4; // 矩阵键盘第1列 sbit Col_2 = P1^5; // 矩阵键盘第2列 sbit Col_3 = P1^6; // 矩阵键盘第3列 sbit Col_4 = P1^7; // 矩阵键盘第4列 unsigned char Key_Table[4][4] = // 键盘矩阵 { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; void main() { unsigned char i, j, key_value; while(1) { for(i = 0; i < 4; i++) // 扫描行 { switch(i) { case 0: Row_1 = 0; Row_2 = 1; Row_3 = 1; Row_4 = 1; break; case 1: Row_1 = 1; Row_2 = 0; Row_3 = 1; Row_4 = 1; break; case 2: Row_1 = 1; Row_2 = 1; Row_3 = 0; Row_4 = 1; break; case 3: Row_1 = 1; Row_2 = 1; Row_3 = 1; Row_4 = 0; break; } for(j = 0; j < 4; j++) // 检测列 { if(Col_1 == 0 && j == 0) key_value = Key_Table[i][j]; if(Col_2 == 0 && j == 1) key_value = Key_Table[i][j]; if(Col_3 == 0 && j == 2) key_value = Key_Table[i][j]; if(Col_4 == 0 && j == 3) key_value = Key_Table[i][j]; } } if(key_value != 0) // 如果有按键按下,则输出按键值 { P2 = key_value; key_value = 0; } } } ``` 在上述程序中,将矩阵键盘的行和列分别连接到单片机的P1口,并定义了键盘矩阵和按键值等变量。然后使用嵌套循环扫描矩阵键盘的每一行和每一列,并根据行列坐标计算出按键的编号。最后将该编号作为输入信号传输给单片机,并根据预先定义的按键编号对应功能来执行相应操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值