weimas 发表于 2013-3-7 10:27:24

4x4键盘消抖总是做不好,各位帮忙看下

刚学单片#include "reg51.h"

#define uchar unsigned char
#define uint unsigned int


//定义要发送的数组SendBuf[]并进行初始
uchar SendBuf_1[]={0XF0,0X03,0X26,0X01,0X00,0X27,0XFF};


void Delay1ms(uint count)
{
        uint i,j;
        for(i=0;i<count;i++)
        for(j=0;j<110;j++);
}

/********数据发送函数********/
void send_dat_1()
{
        uchar i;
        for(i=0;i<7;i++)
                {
                        SBUF =SendBuf_1;
                        while(!TI);    // 等待数据发送完成
                        TI = 0;    // 清发送标志位
               }
}

/********4X4键盘扫描函数********/
uchar keyscan()
{
        uchar cord_h,cord_l;
        P1=0x0f;                                //行线输出全为0
        cord_h=P1&0x0f;                        //读入列线值
        if(cord_h!=0x0f)                //先检测有无按键按下
        {
                Delay1ms(20);                //去抖
                if(cord_h!=0x0f)
                {
                       cord_h=P1&0x0f;                //读入列线值
                       P1=cord_h|0xf0;               //输出当前列线值
                       cord_l=P1&0xf0;               //读入行线值
                       return(cord_h+cord_l);
                }
        }
        return(0xff);
}


/********以下是串行口初始化函数********/
void series_init()
{
        SCON=0x50;                //串口工作方式1,允许接收
        TMOD=0x20;                //定时器T1工作方式2
        TH1=0xfd;
        TL1=0xfd;           //定时初值
//        PCON&=0x00;                //SMOD=0电源控制寄存器PCON SMOD=1时波特率倍增
        PCON=0x80;                //SMOD=1时波特率倍增为19200
        TR1=1;                        //开启定时器1
}

/********以下是主函数********/

void main()
{
        uchar key;
        series_init();                        //调串行口初始化函数
        while(1)
        {
                key=keyscan();         
                switch(key)
                {
                  case 0x7e:send_dat_1();break;//0 按下相应的键调数据发送函数
                  case 0x7d:send_dat_2();break;//1
                  case 0x7b:send_dat_3();break;//2
                  case 0x77:send_dat_4();break;//3
                  case 0xbe:send_dat_5();break;//4
                  case 0xbd:send_dat_6();break;//5
//                        case 0xbb:P0=table;break;//6
//                  case 0xb7:P0=table;break;//7
//                  case 0xde:P0=table;break;//8
//                  case 0xdd:P0=table;break;//9
//                  case 0xdb:P0=table;break;//a
//                  case 0xd7:P0=table;break;//b
//                  case 0xee:P0=table;break;//c
//                  case 0xed:P0=table;break;//d
//                  case 0xeb:P0=table;break;//e
//                  case 0xe7:P0=table;break;//f
                  default:        break;    //无键按下       
                }                                                                                                  
        }
}
机,直接进入主题吧。4x4键盘反转法,按下按键发送相应的串口数据,但是上位机收到的确是一堆数据,数据是正确的,只是多收到了好几遍,判定键盘消抖没做好!

dashashi 发表于 2013-3-7 10:57:47

用定时器中断隔时扫描,每隔几ms扫描一次键盘,看与上一次扫描是否有变化,进而判断是否有按下、弹起

xllsh 发表于 2013-3-7 10:59:34

把松手检测加上

weimas 发表于 2013-3-7 11:17:04

这个松手检测好像还真不好加唉,在cord_l=P1&0xf0; 后加了一句while(P1!=0X0f),没什么效果{:sad:}

mcu_Lei 发表于 2013-3-7 11:54:54

void main()
{
      uchar key,CurrenKey=0xff;
      series_init();                        //调串行口初始化函数
      while(1)
         {
                key=keyscan();
                                if(key!=CurrentKey)
                                {         
                  CurrentKey=key;
                                  switch(key)
                  {
                  case 0x7e:send_dat_1();break;//0 按下相应的键调数据发送函数
                  case 0x7d:send_dat_2();break;//1
                  case 0x7b:send_dat_3();break;//2
                  case 0x77:send_dat_4();break;//3
                  case 0xbe:send_dat_5();break;//4
                  case 0xbd:send_dat_6();break;//5
//                        case 0xbb:P0=table;break;//6
//                  case 0xb7:P0=table;break;//7
//                  case 0xde:P0=table;break;//8
//                  case 0xdd:P0=table;break;//9
//                  case 0xdb:P0=table;break;//a
//                  case 0xd7:P0=table;break;//b
//                  case 0xee:P0=table;break;//c
//                  case 0xed:P0=table;break;//d
//                  case 0xeb:P0=table;break;//e
//                  case 0xe7:P0=table;break;//f
                  default:CurrentKey=0xff; break;    //无键按下      
               }
                           }                                                                                                
      }
}

楼主可以试试这样,加一个当前按键中间变量,相同则不重复动作,释放后则设为初始值。

mcu_Lei 发表于 2013-3-7 11:56:20

mcu_Lei 发表于 2013-3-7 11:54 static/image/common/back.gif
void main()
{
      uchar key,CurrenKey=0xff;


回复初始值,应该在按键释放后,应该单列一个case条件。

ibichao 发表于 2013-3-7 12:16:00

弄个按键扫描子程序,开个定时器,10ms调用一次,扫描按键的时候有键按下就执行一次你的相应程序,在此之后如果按键没松开且按键值跟上一次一样不处理,否则你懂得。

weimas 发表于 2013-3-7 13:09:16

非常感谢mcu_Lei按你的方法问题解决了{:tongue:}

wye11083 发表于 2013-3-7 15:09:09

其实我觉得,应该使用定时器中断的方式来捕捉按键信号,第一次检测到按下时,把第一个比特字置1,第二次检测到按下时,就发出一个按下标志。
页: [1]
查看完整版本: 4x4键盘消抖总是做不好,各位帮忙看下