费劲心思写了一个定时器中断消抖的矩阵按键扫描,为什么没用呢

2019-07-15 15:38发布

#include<reg52.h>

unsigned char code Ledchar[4][4] = {
                                                                   {0x3f,0x06,0x5b,0x4f},
                                                                   {0x66,0x6d,0x7d,0x07},
                                                                   {0x7f,0x6f,0x77,0x7c},
                                                                   {0x39,0x5e,0x79,0x71},
                                                                   };
unsigned char keysta[4][4] = {
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         };
void main()
{
        unsigned char keyup[4][4] = {
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         };
        static unsigned char i,j;
        EA = 1;
        ET0 = 1;
        TMOD = 0X01;
        TH0 = 0XFC;
        TL0 = 0X18;
        TR0 = 1;
        P0 = Ledchar[0][0];
        while(1)
        {
                for(i=0;i<4;i++)
                {
                        for(j=0;j<4;j++)
                        {
                                if(keysta[j] != keyup[j])
                                {
                                        if(keyup[j] == 0)
                                        {
                                                P0 = Ledchar[j];
                                        }
                                }        
                                keyup[j] = keysta[j];
                        }
                }               
        }               
}

void keyscan()
{
        unsigned char keybuf[4][4] = {
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         {1,1,1,1},
                                                         };        
        static unsigned char th,tl;
        static unsigned char i,j;
        P3 = 0xf0;
        th = P3;
        switch(th)
        {
                case 0xe0: i = 0; break;
                case 0xd0: i = 1; break;
                case 0xb0: i = 2; break;
                case 0x70: i = 3; break;
                default:break;
        }
        P3 = 0x0f;
        tl = P3;      
        switch(tl)
        {
                case 0x0e: j = 0; break;
                case 0x0d: j = 1; break;
                case 0x0b: j = 2; break;
                case 0x07: j = 3; break;
                default:break;
        }        
        if((keybuf[j] & 0x0f) == 0x00)
        {
                keysta[j] = 0;        
        }
        if((keybuf[j] & 0x0f) == 0xff)
        {
                keysta[j] = 1;        
        }
}

void TimeInt() interrupt 1
{
        TH0 = 0XFC;
        TL0 = 0X18;
        keyscan();
}
为什么总是卡在主函数P0 = Ledchar[0][0];这里
大神求教

原理图.png


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
4条回答
阿莫斯
2019-07-16 10:21
2042951220 发表于 2015-11-13 14:03
消抖应该在按键按下后进行消抖,你写的程序只是定时去执行keyscan();这个函数,而起不到消抖的作用

通过方法的比较,这种矩阵按键扫描方法不行,换了一种扫描方法,就准确的解决了
#include<reg52.h>

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit key3 = P1^0;
sbit key2 = P1^1;
sbit key1 = P1^2;
sbit key0 = P1^3;
sbit key33= P1^4;
sbit key22 = P1^5;
sbit key11 = P1^6;
sbit key00 = P1^7;

unsigned char code LedChar[]={
        0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
        };
unsigned char KeySta[4][4] = {
        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
        };
unsigned char LedBuff[8] = {
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF,0xFF
        };
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
    { 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
    { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
    { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键
    { 0x30, 0x1B, 0x0D, 0x27 }  //数字键0、ESC键、  回车键、 向右键
        };
void  KeyDriver();
void main()
{
    EA = 1;       //使能总中断
    TMOD = 0x01;  //设置T0为模式1
    TH0  = 0xFC;  //为T0赋初值0xFC67,定时1ms
    TL0  = 0x67;
    ET0  = 1;     //使能T0中断
    TR0  = 1;     //启动T0
        LedBuff[0] = LedChar[0];
    while (1)
    {
        KeyDriver();   //调用按键驱动函数
    }
}

void ShowNumber(unsigned long num)
{
        signed char i;
        unsigned char buf[8];

        for(i=0; i<8; i++)
        {
                buf = num % 10;
                num = num / 10;
        }

        for(i=7; i>=1; i--)
        {
                if(buf == 0)
                {
                        LedBuff = 0x00;
                }
                else
                        break;
        }
       
        for(; i>=0; i--)
        {
                LedBuff = LedChar[buf];       
        }

}
void KeyAction(unsigned char keycode)
{
        static unsigned long result = 0;
        static unsigned long addend = 0;
       
        if((keycode >= 0x30) &&(keycode <= 0x39))
        {
                addend = (addend *10) + (keycode - 0x30);   
                ShowNumber(addend);
        }
       
        else if(keycode == 0x26)
        {
                result += addend;
                addend = 0;
                ShowNumber(result);
        }
        else if(keycode == 0x0D)
        {
                result += addend;
                addend = 0;
                ShowNumber(result);
        }
        else if(keycode == 0x1B)
        {
                addend = 0;
                result = 0;
                ShowNumber(addend);        
        }       
         
}
void  KeyDriver()
{
        unsigned char i, j;
        static        unsigned char backup [4][4] = {
        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
        };

        for(i=0; i<4; i++)
                {
                        for(j=0; j<4; j++)
                        {
                                if(backup[j] != KeySta[j])
                                {
                                        if(backup[j] == 0)
                                        {
                                                KeyAction(KeyCodeMap[j]);
                                        }
                                        backup[j] = KeySta[j];
                                }
                        }       
                }

       
}

/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
void KeyScan()
{
    static unsigned char KeyValue=0;
    unsigned char i;
        static unsigned char keybuf[4][4] = {
        {0xff, 0xff, 0xff, 0xff},
        {0xff, 0xff, 0xff, 0xff},
        {0xff, 0xff, 0xff, 0xff},
        {0xff, 0xff, 0xff, 0xff},
        };
       
        keybuf[KeyValue][0] = (keybuf[KeyValue][0] <<1) | key0;
        keybuf[KeyValue][1] = (keybuf[KeyValue][1] <<1) | key1;
        keybuf[KeyValue][2] = (keybuf[KeyValue][2] <<1) | key2;
        keybuf[KeyValue][3] = (keybuf[KeyValue][3] <<1) | key3;

        for(i=0;i<4;i++)
        {
                if((keybuf[KeyValue] & 0x0F) == 0x00)
                {
                        KeySta[KeyValue] = 0;
                }
                else if((keybuf[KeyValue] & 0x0F) == 0x0F)
                {
                        KeySta[KeyValue] = 1;
                }
        }
        KeyValue++;
        KeyValue = KeyValue & 0x03;
        switch(KeyValue)
        {
                case 0:key00=0;key33=1;break;
                case 1:key00=1;key11=0;break;
                case 2:key11=1;key22=0;break;
                case 3:key22=1;key33=0;break;
                default:break;
        }
}
/* 数码管动态扫描刷新函数,需在定时中断中调用 */
void LedScan()
{
    static unsigned char i = 0;  //动态扫描的索引
   
    P0 = 0x00;   //显示消隐
    switch (i)
    {
        case 0: LSA=0;LSB=0;LSC=0; i++; P0=LedBuff[0]; break;
        case 1: LSA=1;LSB=0;LSC=0; i++; P0=LedBuff[1]; break;
        case 2: LSA=0;LSB=1;LSC=0; i++; P0=LedBuff[2]; break;
        case 3: LSA=1;LSB=1;LSC=0; i++; P0=LedBuff[3]; break;
        case 4: LSA=0;LSB=0;LSC=1; i++; P0=LedBuff[4]; break;
                case 5: LSA=1;LSB=0;LSC=1; i++; P0=LedBuff[5]; break;
                case 6: LSA=0;LSB=1;LSC=1; i++; P0=LedBuff[6]; break;
        case 7: LSA=1;LSB=1;LSC=1; i=0; P0=LedBuff[7]; break;
        default: break;
    }
}

/* T0中断服务函数,用于数码管显示扫描与按键扫描 */
void InterruptTimer0() interrupt 1
{
        TH0 = 0xFC;
        TL0 = 0x67;
        LedScan();
        KeyScan();
}

一周热门 更多>