单片机/MCU论坛
直播中

余一痴

6年用户 80经验值
私信 关注
[问答]

在别的地方搬了一个程序 ,有点地方不明白,希望大佬能给我解释一下 不明白的地方已经标注红色了

`以下为程序:
/*反转法矩阵键盘的应用,我认为这是一个编程简便又容易理解的矩阵键盘编程应用,因此拿来与大家共享*/
/*殷传东对此程序拥有独家版权,仅可用于研究学习,严禁用于商业目的,欢迎喜爱单片机的大虾小虾皮皮虾联系交流QQ:77329961*/
#include                //头文件
#define uchar unsigned char         //宏定义
#define uint unsigned int
uchar key,n;                 //定义变量
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位的值
P1=0x0f;                                        //给P1赋值00001111
l=P1&0x0f;
if(l!=0x0f)
{
  delay(100);
     if(l!=0x0f)
          l=P1&0x0f;                        //若有键按下,得出低四位的值
  }
  P1=0xf0;                                        //给P1赋值11110000
  h=P1&0xf0;
if(h!=0xf0)
{
  delay(100);
     if(h!=0xf0)
          h=P1&0xf0;                        //若有键按下,得出高4位的值
  }

  key=l+h;                                        //高4位的值与低4位的值相加
  for(i=0;i<16;i++)
           {
    if(key==table)                   //通过查表得出n的值
    n=i;
        }
}

void main()
{
while(1)
   {
           keyscan();
        P0=yin[n];                                //在数码管上显示相应的键值
   }
}

` B{}{Y2d(J7{`G@3@H6K.png

回帖(14)

余一痴

2017-11-8 19:31:48
在线急等{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}{:4:}
举报

dabing89

2017-11-8 19:51:51
通过查表得出N的值?只写一个table怎么查?最起码写完整吧,table[i];
举报

余一痴

2017-11-8 20:15:23
引用: XX00XX00 发表于 2017-11-8 19:51
通过查表得出N的值?只写一个table怎么查?最起码写完整吧,table;

尴尬  少搬了点
举报

余一痴

2017-11-8 20:17:22
引用: 余一痴 发表于 2017-11-8 20:15
尴尬  少搬了点

这个程序在单片机上显示不全
举报

余一痴

2017-11-8 20:23:00
像这样显示不全第一个按键还不显示
举报

余一痴

2017-11-8 20:24:25

dabing89

2017-11-8 21:24:39

你买的谁的?没有技术支持吗?这个东西得看硬件,光看这个现象,是不行的,数码管是共阳还是共阴,数组数值编码不一样
举报

人中狼

2017-11-8 22:12:59
  delay(100);
     if(l!=0x0f)
          l=P1&0x0f;                        //若有键按下,得出低四位的值
  }
括号配对有问题,上面的这个括号应该去掉,其他的你看着配对吧,既然是搬的程序,也可以对比一下原来的程序
举报

张金权

2017-11-9 19:44:49
这是一个按键扫描程序 判断有没有按键按下
举报

026544

2017-11-13 08:18:57
你比我看得懂的多得多
举报

余一痴

2017-11-17 21:17:01


程序基于AT89S51芯片,两个573锁存器(控制 段选位选)

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<16;i++)
                           {
                            if(key==table[i])            //通过查表得出n的值
                            n=i;
                    }
                }
        }
}
void main()
{

while(1)
   {
          keyscan();       
    for(i=0;i<6;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);
     }
   }
}

新手标注可能不够到位,多多理解,如有错误请多多指教。
举报

余一痴

2017-11-17 21:17:22
引用: 026544 发表于 2017-11-13 08:18
你比我看得懂的多得多

也是新手?
举报

张海波

2017-11-21 00:34:03
这个是使用先给按键矩阵IO口赋值,并通过判断值是否变化来判断是否有按键按下,从IO口取值判断是哪行(列)有按键按下;同时再次反向赋值,并取值再次判断是哪列(行)有按键按下,就能直接得出按键值,我学矩阵键盘时也是这个思路写的,不过用的swich语句判断,这个table【】数组用的更灵活些
/****************************************************************************************************
4*4=16个矩阵键盘,开始数码管不显示,在分别按下这16个按键时,数码管静态分别显示0-F
实现电路:郭天祥GTX-1C,4*4矩阵键盘的4行和4列分别连接P3.0-P3.7口
****************************************************************************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  
***it dula=P2^6;                        //定义段拉
***it wela=P2^7;                        //定义位拉
uchar key;
void delay(uint x)                           //延时子函数500uS
{
        uchar y;
        for(x;x>0;x--)
                for(y=225;y>0;y--);
}
void scankey()                                  //按键扫描程序
{
        uchar tmp,tmp1;
        if(P3!=0x0f)                 //在主函数中,先给P3送了0x0f(00001111)电平,以检测按下的是哪一行,如果有按键按下,这个值都会变化。
        {                                 
                tmp1=P3;   //如果是1-4按键按下,则变为00001110,5-8为00001101,9-12为00001011,13-16为00000111,把这个值赋给tmp1
                delay(20);        //延时10mS,消抖
                P3=0xf0;        //再次给P3送0xf0(11110000)电平,以检测是那一列按键按下
                if(P3!=0xf0)         //消抖后仍然检测到按键按下,值发生变化,P3不等于0xf0
                {                                 //如果是1.5.9.13按键按下,则变为11100000,2.6.10.14为11010000,3.7.11.15为10110000,4.8.12.16为01110000
                        tmp=(tmp1|P3);         //将检测的行值和列值进行或运算
                        switch(tmp)                  //switch语句对tmp值进行多条件选择
                        {
                                case 0xee:                 //如果是1按键按下,这个值对应为11101110,则显示数组的0位数
                                        key=0;
                                        break;
                                case 0xde:
                                        key=1;
                                        break;
                                case 0xbe:
                                        key=2;
                                        break;
                                case 0x7e:
                                        key=3;
                                        break;
                                case 0xed:
                                        key=4;
                                        break;
                                case 0xdd:
                                        key=5;
                                        break;
                                case 0xbd:
                                        key=6;
                                        break;
                                case 0x7d:
                                        key=7;
                                        break;
                                case 0xeb:
                                        key=8;
                                        break;
                                case 0xdb:
                                        key=9;
                                        break;
                                case 0xbb:
                                        key=10;
                                        break;
                                case 0x7b:
                                        key=11;
                                        break;
                                case 0xe7:
                                        key=12;
                                        break;
                                case 0xd7:
                                        key=13;
                                        break;
                                case 0xb7:
                                        key=14;
                                        break;
                                case 0x77:
                                        key=15;
                                        break;       
                        }
                        while(P3!=0xf0);                 //等待按键放开
                        dula=1;
                        P0=table[key];                   //送数码管段数据
                        dula=0;
                }                    
        }               
}
void main()
{
        wela=1;
        P0=0x00;       
        wela=0;                                           //因为是静态显示,所以就没有写单独的display显示子函数
        while(1)
        {               
                P3=0x0f;        //先给P3送00001111电平
                scankey();        //扫描按键子函数
        }
}
举报

张海波

2017-11-21 00:44:44
两个结合一起程序显得更清爽了哈:
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  
uchar code table0[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};        //反转法矩阵键盘的各个按键的计算值
***it dula=P2^6;                        //定义段拉
***it wela=P2^7;                        //定义位拉
uchar key;
void delay(uint x)                           //延时子函数500uS
{
        uchar y;
        for(x;x>0;x--)
                for(y=225;y>0;y--);
}
void scankey()                                  //按键扫描程序
{
        uchar tmp,tmp1,i;
        if(P3!=0x0f)                 //在主函数中,先给P3送了0x0f(00001111)电平,以检测按下的是哪一行,如果有按键按下,这个值都会变化。
        {                                 
                tmp1=P3;   //如果是1-4按键按下,则变为00001110,5-8为00001101,9-12为00001011,13-16为00000111,把这个值赋给tmp1
                delay(20);        //延时10mS,消抖
                P3=0xf0;        //再次给P3送0xf0(11110000)电平,以检测是那一列按键按下
                if(P3!=0xf0)         //消抖后仍然检测到按键按下,值发生变化,P3不等于0xf0
                {                                 //如果是1.5.9.13按键按下,则变为11100000,2.6.10.14为11010000,3.7.11.15为10110000,4.8.12.16为01110000
                        tmp=(tmp1|P3);         //将检测的行值和列值进行或运算
                    for(i=0;i<16;i++)
                        {
                                if(tmp==table0[i])
                                        key=i;
                        }
                        while(P3!=0xf0);                 //等待按键放开
                        dula=1;
                        P0=table[key];                   //送数码管段数据
                        dula=0;
                }                    
        }               
}
void main()
{
        wela=1;
        P0=0x00;       
        wela=0;                                           //因为是静态显示,所以就没有写单独的display显示子函数
        while(1)
        {               
                P3=0x0f;        //先给P3送00001111电平
                scankey();        //扫描按键子函数
        }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分