搜索
bottom↓
回复: 45

发个经典的4X4KEY键盘程序

[复制链接]

出0入0汤圆

发表于 2007-11-14 19:47:36 | 显示全部楼层 |阅读模式
//参考C51改写,并调试通过
//端口定义
//4X4键盘输入
#define   D_IO_SET       DDRD
#define   OUT_XY         PORTD
#define   IN_XY          PIND
//键盘输入程序
uchar key_4x4(void)
{    uchar i,SC_X=0,RD_Y=0;
     OUT_XY=0xF0;                //                         
     D_IO_SET=0x0F;                 //  
     _delay_ms(10);
     asm("nop");
     asm("nop");
   if((IN_XY&0xf0)!=0xf0)
     {          _delay_ms(10);
        asm("nop");
           asm("nop");
         if((IN_XY&0xf0)!=0xf0)
         {    SC_X=0xfe;                //行扫描初值
                 while((SC_X&0x10)!=0)  
                {    OUT_XY=SC_X;    //输出扫描值
                     asm("nop");
                     asm("nop");
                    if((IN_XY&0xf0)!=0xf0)
                       {   asm("nop");
                        asm("nop");
                        RD_Y=(IN_XY&0xf0)|0x0f;//读列值
                        //---------------------等待按键弹起
                        asm("nop");
                        asm("nop");
                        for(i=0;i<50;i++)   //0.XS后自动确认按下,退出
                          {        asm("nop");
                                           asm("nop");
                               if(((IN_XY&0xf0)|0x0f)!=RD_Y)break;
                                   asm("nop");
                                           asm("nop");
                                _delay_ms(5);
                                asm("nop");
                                                                          
                          }
                        //------------------------------
                          return((~SC_X)+(~RD_Y));//返回键值Y+X
                        }
                   else
                          SC_X=(SC_X<<1)|0x01;  //扫描下1行,共4行
                 }
            }
     }
  return 0;
}

出0入13汤圆

发表于 2007-11-14 22:55:50 | 显示全部楼层
good!不错!

出0入0汤圆

发表于 2007-11-14 23:13:24 | 显示全部楼层
不错!

出0入0汤圆

发表于 2007-11-15 01:03:58 | 显示全部楼层
在键盘扫描过程中使用软件延时,并不是什么经典的好例子。使用这种方式,吃亏在后面等着呢。

出0入0汤圆

发表于 2007-11-15 10:40:39 | 显示全部楼层
是的,程序比较大时,功能比较多时,问题比较明显。
除非你的键盘放在主程序中,其他主要的处理程序放在中断中,这样不会影响你的其他功能的!

出0入0汤圆

发表于 2007-11-15 11:09:22 | 显示全部楼层
俺以前也喜欢用这种4*4键盘,上个月做18通非标ppm信号源时感觉键盘消抖处理太麻烦,干脆去买74c922键盘处理芯片,可惜太贵,22元一片,就用ad转换方式,还是麻烦,干脆用12f675的ad转换作成专门的键盘处理,4线并口,爽呆了;ppm每次循环就直接读io口值,方便多了;
俺被老师骂惨了:“不会使用周边硬件你还做啥工控东西!”
呵呵,还有一句他没明说,但是俺理解到了:单单一片M8的小板子你敢向客户要价?

出0入0汤圆

发表于 2007-11-15 11:19:36 | 显示全部楼层
顶!

出0入0汤圆

发表于 2008-4-27 19:20:32 | 显示全部楼层
帮顶~

出0入0汤圆

发表于 2008-4-28 15:35:06 | 显示全部楼层
发一个我写的,注意根据需要做适当变化,实现长按、短按、连按等模式的按钮操作。
我一般放到定时中断中调用


void CheckKey(void)
{   uchar uTmp;static uchar key_rel,key_prs,keycodetemp;

    uTmp = ((~inb(PIND)&0x18) | (~inb(PINC)&0x03))  ;

    if( uTmp==0x00){
        if( (++key_rel >= 10) ){
            if( (key_prs >= 1) && (key_prs< 250) ){
                //if(!KeyLPrsingFlag){
                    KeyCode = keycodetemp;
                //}
            }
            key_prs = 0;
            //KeyLPrsingFlag = 0;
        }

    }else{
        key_rel = 0;
            if(key_prs++ == 1){
                keycodetemp = uTmp;
                LEDLightTimer = ParaSet.LEDLightTimer*10;
            }else if(key_prs ==  252){
            KeyCode = keycodetemp|0x80;
            //KeyLPrsingFlag = 1;
            }else if(key_prs >  252){
                key_prs = 240;
            }
    }

}

出0入22汤圆

发表于 2008-4-28 16:14:53 | 显示全部楼层
谢谢。标记

出0入0汤圆

发表于 2008-4-28 16:34:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-4-28 16:37:25 | 显示全部楼层
呵呵,以前就用过这段代码

出0入0汤圆

发表于 2008-4-28 17:22:52 | 显示全部楼层
mark!

出0入0汤圆

发表于 2008-4-28 17:47:20 | 显示全部楼层
mark!

出0入0汤圆

发表于 2008-8-1 14:41:37 | 显示全部楼层
mark ,too.

出0入93汤圆

发表于 2008-8-1 16:00:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-8-1 16:29:23 | 显示全部楼层
这个还行吧,不过如果程序要实现的功能比较多时就不太好用了!

出0入0汤圆

发表于 2008-8-1 17:42:53 | 显示全部楼层
看看我的键盘驱动 ,是不是比上面的清晰许多??



#define KEYPORT PORTB
#define KEYDDR DDRB
#define KEYPIN PINB
/*
                  P4           P5        P6         P7
P3                7           8        9         'Clear'        //C 意为清除
P2                4           5        6         'Ok'        //o 为ok
P1                1           2        3         'Up'        //u 为 up 向上
P0                0         'Left''Rigth''Down'

*/


uchar key_read(){
          uchar hang,lie,key;
          uchar i;
                   KEYDDR=0x0f;
                   KEYPORT=0xf0;
                 for(i=0;i<5;i++){_NOP();}        //读行
               
                 hang=KEYPIN&0xf0;
                   
                                 
                   KEYDDR=0xf0;                        //读列
                   KEYPORT=0x0f;
                 for(i=0;i<10;i++){_NOP();}
                 //delay_ms(1);
                   lie=(KEYPIN&0x0f);
                 
                 KEYDDR=0x00;
                 KEYPORT=0xff;
  
                   key = hang|lie;
                 switch (key) {/*将按键码转换成键值*/  
                 case  0xff: return 0xff;  
                 case  0xEE: return 0;  
                 case  0xDE: return 'l';  
                 case  0xBE: return 'r';  
                 case  0x7E: return 'd';  
                 case  0xED: return 1;  
                 case  0xDD: return 2;  
                 case  0xBD: return 3;  
                 case  0x7D: return 'u';  
                 case  0xEB: return 4;  
                 case  0xDB: return 5;  
                 case  0xBB: return 6;  
                 case  0x7B: return 'o';  
                 case  0xE7: return 7;  
                 case  0xD7: return 8;  
                 case  0xB7: return 9;  
                 case  0x77: return 'c';  
                 default : return 0xff;  
                }
                 
}
uchar get_key(void){
        unsigned char i;
        static unsigned char j;/*按键记录*/
       
        i = key_read();
        if (i == 0xff){/*无有效按键按下*/  
                j = 0xff;/*清除按键记录*/  
                return 0xff;/*程序退出*/  
        }
        if (j == 0xff) {/*为新按键*/  
                j = i;/*保存本次采样结果*/  
                delay_ms(10);/*去按键颤抖*/  
                i = key_read();  
                if(i == j) {   
                        return i;   
                }  
        }
        return 0xff;
}

出0入0汤圆

发表于 2008-8-1 17:52:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-8-1 18:14:18 | 显示全部楼层
谢谢!

出0入0汤圆

发表于 2008-8-2 20:30:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-8-3 01:06:57 | 显示全部楼层
不错,MARK

出0入0汤圆

发表于 2008-9-25 15:20:27 | 显示全部楼层
标记

出0入0汤圆

发表于 2008-9-26 00:41:30 | 显示全部楼层
对初学者很有用,但是作者也需要看一下软件编写规范,程序有点乱,最好看一下华为软件编写规范之类的。还有单片机很多时候是应用于系统的,延时会占用太多的软件资源,这对于多任务的系统是不可忍受的。因此一般有还有一下方法替换:1利用单片机空闲的定时器扫描,定时约为消抖时间;2键盘控制芯片(有一些有中断功能);其他就先不说了。

出0入0汤圆

发表于 2008-9-26 00:43:04 | 显示全部楼层
写错字了,不好意思

出0入0汤圆

发表于 2008-9-26 09:15:26 | 显示全部楼层
17楼的方法最好,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KEYDDR=0x0f;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KEYPORT=0xf0;&nbsp;



楼主的并非对矩阵的好方法,一边去吧,还逐行扫描呢,书上学的吧,害人啊。

出0入0汤圆

发表于 2008-9-29 09:21:10 | 显示全部楼层
迷糊

出0入0汤圆

发表于 2009-6-10 10:21:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-12 17:29:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-13 19:24:36 | 显示全部楼层
17楼的好?有没有搞错啊?17楼的写法是查询扫描,对其他功能的影响很大!所以最好的键盘扫描是使用中断的方法实现!!!!!

出0入0汤圆

发表于 2010-5-14 00:07:53 | 显示全部楼层
用中断扫描我认为是最好的,对于功能多时更能体现,而且可方便精确的控制,各种按键状态都可获取,对其它没影响,可说是实时的。
像这种延时的,都是扯淡,教本上看多了吧?也不说书上害人,因为他给了你怎么获取按键的方法,
但老师是害人的,只念书,不解释更不引申,很多教授都是没做过实际有用的东西
我部门新招一老者,他说自己精通51,精通汇编,但来了几个月了,连个数码管动态显示加按键扫描都没搞好,
出于好心,我给他写了c的实例,还有仿真,并且苦口婆心的把原理解释给他听,但还是不懂,
最后说让我编译好后,反汇编给他看,没办法,我就反给他看,我都做到这份上了,就差没帮你这项目的程序写好了,看你啥时
能搞好,光知道吹水,还好我不是老板不用我付工资,不然,早打发他走人了

出0入0汤圆

发表于 2010-5-15 15:13:03 | 显示全部楼层
顶:

【30楼】 MZ_Guo
讲得好

出0入0汤圆

发表于 2010-5-15 18:25:06 | 显示全部楼层
哈哈哈 顶30楼

出0入0汤圆

发表于 2010-5-16 11:14:44 | 显示全部楼层
最近做了一个用m16内部ad实现键盘的板子,每秒钟读100次ad值。
如果3次ad值变换小于1%fs即判断简直,否则放弃。
效果还不错

出0入0汤圆

发表于 2010-5-16 12:11:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-20 15:04:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-20 16:27:45 | 显示全部楼层
键盘 扫描 恒久不变的话题啊

出0入0汤圆

发表于 2010-7-20 19:37:42 | 显示全部楼层
mark.

出0入0汤圆

发表于 2010-7-20 20:51:25 | 显示全部楼层
记下

出0入0汤圆

发表于 2010-7-20 22:49:00 | 显示全部楼层
工程上几乎没人这么用的

出0入0汤圆

发表于 2010-7-20 23:14:53 | 显示全部楼层
不知道这个贴库在哪里啊.没有看懂,但是我觉得下面的那个要好点,用指令延时不好

出0入0汤圆

发表于 2010-7-21 00:20:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-21 00:26:40 | 显示全部楼层
mark~学习一下

出0入0汤圆

发表于 2010-8-13 17:28:55 | 显示全部楼层
不错!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-7 18:47

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表