矩阵键盘按键识别与数码管动态显示【PROTEUS C51】

实现功能:
按下按键时,数码管动态显示 ‘ 键值-扫描值 ’
按键松开时,数码管动态显示 ‘ 0-00 ’

  • proteus连线图

矩阵键盘按键识别与数码管动态显示【PROTEUS C51】_第1张图片
Clock Frequency 12MHz
使用查询方式

#include 
#include 
#define LED_port XBYTE[0XFDFF]//A9
#define uint unsigned int
#define uchar unsigned char
uchar line, row, kvalue, kscan, kscanA, kscanB;

// 共阴极数码表
uchar dispcode[] =
    {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
     0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,
     0x40}; //最后一个为实现视觉效果‘键值-扫描值’而设置只有g亮
void delay1ms(uchar n)
{
    uint t = n * 1000;
    TMOD = 0x01;
    TH0 = (65536 - t) / 256;
    TL0 = (65536 - t) % 256;
    TR0 = 1;
    while (TF0 != 1)
    {
        /* code */
    }
    TF0 = 1;
}
/*矩阵按键函数开始*/
// 行列反转法
uchar keyRowLine()
{
    P1 = 0x0f;
    line = P1;
    if (line != 0x0f)
    {
        /* 判断行状态 */
        delay1ms(20);
        line = P1;
        if (line != 0x0f)
        {
            /* 有按键按下 */
            line = line & 0x0f;
            P1 = 0xf0;
            delay1ms(1); //等待变化时间
            row = P1;
            row = row & 0xf0;
            kscan = line | row;
            return kscan;
        }
    }
    return 0xff;
}

// 获得键编码
void getKeyVaule()
{
    uchar Kscan;
    Kscan = keyRowLine();
    switch (Kscan)
    {
    case 0xee:
        kvalue = 0;
        kscanA = 14;
        kscanB = 14;
        break;
    case 0xde:
        kvalue = 1;
        kscanA = 13;
        kscanB = 14;
        break;
    case 0xbe:
        kvalue = 2;
        kscanA = 11;
        kscanB = 14;
        break;
    case 0x7e:
        kvalue = 3;
        kscanA = 7;
        kscanB = 14;
        break;
    case 0xed:
        kvalue = 4;
        kscanA = 14;
        kscanB = 13;
        break;
    case 0xdd:
        kvalue = 5;
        kscanA = 13;
        kscanB = 13;
        break;
    case 0xbd:
        kvalue = 6;
        kscanA = 11;
        kscanB = 13;
        break;
    case 0x7d:
        kvalue = 7;
        kscanA = 7;
        kscanB = 13;
        break;
    case 0xeb:
        kvalue = 8;
        kscanA = 14;
        kscanB = 11;
        break;
    case 0xdb:
        kvalue = 9;
        kscanA = 13;
        kscanB = 11;
        break;
    case 0xbb:
        kvalue = 10;
        kscanA = 11;
        kscanB = 11;
        break;
    case 0x7b:
        kvalue = 11;
        kscanA = 7;
        kscanB = 11;
        break;
    case 0xe7:
        kvalue = 12;
        kscanA = 14;
        kscanB = 7;
        break;
    case 0xd7:
        kvalue = 13;
        kscanA = 13;
        kscanB = 7;
        break;
    case 0xb7:
        kvalue = 14;
        kscanA = 11;
        kscanB = 7;
        break;
    case 0x77:
        kvalue = 15;
        kscanA = 7;
        kscanB = 7;
        break;
    default:
        kvalue = 0;
        kscanA = 0;
        kscanB = 0;
        break;
    }
}

/*矩阵按键函数结束*/
// 主函数
void main()
{
    while (1)
    {
        getKeyVaule();
        P3 = 0Xff; //消隐
        LED_port = dispcode[kvalue];
        P3 = 0Xfe;
        delay1ms(5);
        P3 = 0Xff; //消隐
        LED_port = dispcode[16];
        P3 = 0Xfd;
        delay1ms(5);
        P3 = 0Xff; //消隐
        LED_port = dispcode[kscanA];
        P3 = 0Xfb;
        delay1ms(5);
        P3 = 0Xff; //消隐
        LED_port = dispcode[kscanB];
        P3 = 0Xf7;
        delay1ms(5);
    }
}

使用中断方式

#include 
#include 
#define LED_port XBYTE[0XFDFF] //A9
#define uint unsigned int
#define uchar unsigned char
uchar line, row, kvalue, kscan, kscanA, kscanB;
uchar dat[4] = {0, 0, 0, 0};
uchar led_active = 0;

// 共阴极数码表
uchar dispcode[] =
    {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
     0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,
     0x40}; //最后一个为实现视觉效果‘键值-扫描值’而设置只有g亮
void delay1ms(uchar n)
{
    uint t = n * 1000;
    TH0 = (65536 - t) / 256;
    TL0 = (65536 - t) % 256;
    TR0 = 1;
    while (TF0 != 1)
    {
        /* code */
    }
    TF0 = 1;
}
/*矩阵按键函数开始*/
// 行列反转法
uchar keyRowLine()
{
    P1 = 0x0f;
    line = P1;
    if (line != 0x0f)
    {
        /* 判断行状态 */
        delay1ms(20);
        line = P1;
        if (line != 0x0f)
        {
            /* 有按键按下 */
            line = line & 0x0f;
            P1 = 0xf0;
            delay1ms(1); //等待变化时间
            row = P1;
            row = row & 0xf0;
            kscan = line | row;
            return kscan;
        }
    }
    return 0xff;
}

// 获得键编码
void getKeyVaule()
{
    uchar Kscan;
    Kscan = keyRowLine();
    switch (Kscan)
    {
    case 0xee:
        kvalue = 0;
        kscanA = 14;
        kscanB = 14;
        break;
    case 0xde:
        kvalue = 1;
        kscanA = 13;
        kscanB = 14;
        break;
    case 0xbe:
        kvalue = 2;
        kscanA = 11;
        kscanB = 14;
        break;
    case 0x7e:
        kvalue = 3;
        kscanA = 7;
        kscanB = 14;
        break;
    case 0xed:
        kvalue = 4;
        kscanA = 14;
        kscanB = 13;
        break;
    case 0xdd:
        kvalue = 5;
        kscanA = 13;
        kscanB = 13;
        break;
    case 0xbd:
        kvalue = 6;
        kscanA = 11;
        kscanB = 13;
        break;
    case 0x7d:
        kvalue = 7;
        kscanA = 7;
        kscanB = 13;
        break;
    case 0xeb:
        kvalue = 8;
        kscanA = 14;
        kscanB = 11;
        break;
    case 0xdb:
        kvalue = 9;
        kscanA = 13;
        kscanB = 11;
        break;
    case 0xbb:
        kvalue = 10;
        kscanA = 11;
        kscanB = 11;
        break;
    case 0x7b:
        kvalue = 11;
        kscanA = 7;
        kscanB = 11;
        break;
    case 0xe7:
        kvalue = 12;
        kscanA = 14;
        kscanB = 7;
        break;
    case 0xd7:
        kvalue = 13;
        kscanA = 13;
        kscanB = 7;
        break;
    case 0xb7:
        kvalue = 14;
        kscanA = 11;
        kscanB = 7;
        break;
    case 0x77:
        kvalue = 15;
        kscanA = 7;
        kscanB = 7;
        break;
    default:
        kvalue = 0;
        kscanA = 0;
        kscanB = 0;
        break;
    }
    
                    /*swich语句太长,改进一下,建议换成下面语句:
    for ( i = 0; i < 16; i++)
    {
      if (Kscan==dispcode[i])
      {
         kvalue=i;
      }
    }
    kscanA=Kscan>>4;
    kscanB=Kscan&0x0f;
                   swich语句太长,改进一下*/
                   
    dat[0] = kvalue;
    dat[1] = 16;
    dat[2] = kscanA;
    dat[3] = kscanB;
}

/*矩阵按键函数结束*/
// 主函数
void main()
{
    TMOD = 0x11;
    TH1 = (65536 - 5000) / 256;
    TL1 = (65536 - 5000) % 256;
    EA = 1;
    ET1 = 1;
    TR1 = 1;
    while (1)
    {
        getKeyVaule();
    }
}
void TIMER1() interrupt 3
{
    TR1 = 0;
    TH1 = (65536 - 5000) / 256;
    TL1 = (65536 - 5000) % 256;
    // getKeyVaule();  该函数内部有延时,违背中断的设计,不推荐在中断内部使用
    P3 = P3 | 15; //消隐
    LED_port = dispcode[dat[led_active]];
    P3 = ~(1 << led_active);
    led_active++;
    if (led_active >= 4)
    {
        led_active = 0;
    }
    TR1 = 1;
}

你可能感兴趣的:(单片机,switch)