单片机 键盘程序_单片机键盘自检程序 - CSDN
  • 51单片机简洁按键程序

    千次阅读 2018-10-10 11:47:46
    同时,这里面用到了一些分层的思想,在单片机当中也;以下假设你懂C语言,因为纯粹的C语言描述,所以和;核心算法:;unsignedcharTrg;;unsignedcharCont;;voidKeyRead(void);unsignedcharReadDat  最为精辟和...

    最为精辟和实用的按键处理程序;1.新型的按键扫描程序;不过我在网上游逛了很久,也看过不少源程序了,没有;同时,这里面用到了一些分层的思想,在单片机当中也;以下假设你懂C语言,因为纯粹的C语言描述,所以和;核心算法:;unsignedcharTrg;;unsignedcharCont;;voidKeyRead(void);unsignedcharReadDat

          最为精辟和实用的按键处理程序

          1.新型的按键扫描程序

          不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为C语言强大的可移植性。

          同时,这里面用到了一些分层的思想,在单片机当中也是相当有用的,也是本文的另外一个重点。 对于老鸟,我建议直接看那两个表达式,然后自己想想就会懂的了,也不需要听我后面的自吹自擂了,我可没有班门弄斧的意思,hoho~~但是对于新手,我建议将全文看完。因为这是实际项目中总结出来的经验,学校里面学不到的东西。

          以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。当然,我自己也是在多个项目用过,效果非常好的。 好了,工程人员的习惯,废话就应该少说,开始吧。以下我以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。

          核心算法:

          unsigned char Trg;

          unsigned char Cont;

          void KeyRead( void )

          {

          unsigned char ReadData = PINB^0xff; // 1

          Trg = ReadData & (ReadData ^ Cont); // 2

          Cont = ReadData; // 3

          }

          完了。有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!! 下面是程序解释:

          Trg(triger) 代表的是触发,Cont(continue)代表的是连续按下。

          1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。

          2:算法1,用来计算触发变量的。一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。

          3:算法2,用来计算连续变量。

          看到这里,有种“知其然,不知其所以然”的感觉吧?代码很简单,但是它到底是怎么样实现我们的目的的呢?好,下面就让我们绕开云雾看青天吧。

          我们最常用的按键接法如下:AVR是有内部上拉功能的,但是为了说明问题,我是特意用外部上拉电阻。那么,按键没有按下的时候,读端口数据为1,如果按键按下,那么端口读到0。下面就看看具体几种情况之下,这算法是怎么一回事。

          (1) 没有按键的时候

          端口为0xff,ReadData读端口并且取反,很显然,就是 0x00 了。

          Trg = ReadData & (ReadData ^ Cont); (初始状态下,Cont也是为0的)很简单的数学计算,因为ReadData为0,则它和任何数“相与”,结果也是为0的。

          Cont = ReadData; 保存Cont 其实就是等于ReadData,为0;

          结果就是:

          ReadData = 0;

          Trg = 0;

          Cont = 0;

          (2) 第一次PB0按下的情况

          端口数据为0xfe,ReadData读端口并且取反,很显然,就是 0x01 了。

          Trg = ReadData & (ReadData ^ Cont); 因为这是第一次按下,所以Cont是上次的值,应为为0。那么这个式子的值也不难算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01

          Cont = ReadData = 0x01;

          结果就是:

          ReadData = 0x01;

          Trg = 0x01;Trg只会在这个时候对应位的值为1,其它时候都为0

          Cont = 0x01;

          (3) PB0按着不松(长按键)的情况

          端口数据为0xfe,ReadData读端口并且取反是 0x01 了。

          Trg = ReadData & (ReadData ^ Cont); 因为这是连续按下,所以Cont是上次的值,应为为0x01。那么这个式子就变成了 Trg = 0x01 & (0x01^0x01) = 0x00

          Cont = ReadData = 0x01;

          结果就是:

          ReadData = 0x01;

          Trg = 0x00;

          Cont = 0x01;

          因为现在按键是长按着,所以MCU会每个一定时间(20ms左右)不断的执行这个函数,那么下次执行的时候情况会是怎么样的呢?

          ReadData = 0x01;这个不会变,因为按键没有松开

          Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按键没有松开,这个Trg值永远为 0 !!!

          Cont = 0x01;只要按键没有松开,这个值永远是0x01!!

          (4) 按键松开的情况

          端口数据为0xff,ReadData读端口并且取反是 0x00 了。

          Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00

          Cont = ReadData = 0x00;

          结果就是:

          ReadData = 0x00;

          Trg = 0x00;

          Cont = 0x00;

          很显然,这个回到了初始状态,也就是没有按键按下的状态。

          总结一下,不知道想懂了没有?其实很简单,答案如下:

          Trg 表示的就是触发的意思,也就是跳变,只要有按键按下(电平从1到0的跳变),那么Trg在对应按键的位上面会置一,我们用了PB0则Trg的值为0x01,类似,如果我们PB7按下的话,Trg 的值就应该为 0x80 ,这个很好理解,还有,最关键的地方,Trg 的值每次按下只会出现一次,然后立刻被清除,完全不需要人工去干预。所以按键功能处理程序不会重复执行,省下了一大堆的条件判断,这个可是精粹哦!!Cont代表的是长按键,如果PB0按着不放,那么Cont的值就为 0x01,相对应,PB7按着不放,那么Cont的值应该为0x80,同样很好理解。

          如果还是想不懂的话,可以自己演算一下那两个表达式,应该不难理解的。

          因为有了这个支持,那么按键处理就变得很爽了,下面看应用:

          应用一:一次触发的按键处理

          假设PB0为蜂鸣器按键,按一下,蜂鸣器beep的响一声。这个很简单,但是大家以前是怎么做的呢?对比一下看谁的方便?

          #define KEY_BEEP 0x01

          void KeyProc(void)

          {

          if (Trg & KEY_BEEP) // 如果按下的是KEY_BEEP

          {

          Beep(); // 执行蜂鸣器处理函数

          }

          }

          怎么样?够和谐不?记得前面解释说Trg的精粹是什么?精粹就是只会出现一次。所以你按下按键的话,Trg & KEY_BEEP 为“真”的情况只会出现一次,所以处理起来非常的方便,蜂鸣器也不会没事乱叫,hoho~~~

          或者你会认为这个处理简单,没有问题,我们继续。

          应用2:长按键的处理

          项目中经常会遇到一些要求,例如:一个按键如果短按一下执行功能A,如果长按2秒不放的话会执行功能B,又或者是要求3秒按着不放,计数连加什么什么的功能,很实际。不知道大家以前是怎么做的呢?我承认以前做的很郁闷。

          但是看我们这里怎么处理吧,或许你会大吃一惊,原来程序可以这么简单

          这里具个简单例子,为了只是说明原理,PB0是模式按键,短按则切换模式,PB1就是加,如果长按的话则连加(玩过电子表吧?没错,就是那个!)

          #define KEY_MODE 0x01 // 模式按键

          #define KEY_PLUS 0x02 // 加

          void KeyProc(void)

          {

          if (Trg & KEY_MODE) // 如果按下的是KEY_MODE,而且你常按这按键也没有用,

      { //它是不会执行第二次的哦 , 必须先松开再按下

          Mode++; // 模式寄存器加1,当然,这里只是演示,你可以执行你想

          // 执行的任何代码

          }

          if (Cont & KEY_PLUS) // 如果“加”按键被按着不放

          {

          cnt_plus++; // 计时

          if (cnt_plus > 100) // 20ms*100 = 2S 如果时间到

          {

          Func(); // 你需要的执行的程序

          }

          }

          }

          不知道各位感觉如何?我觉得还是挺简单的完成了任务,当然,作为演示用代码。

          应用3:点触型按键和开关型按键的混合使用

          点触形按键估计用的最多,特别是单片机。开关型其实也很常见,例如家里的电灯,那些按下就不松开,除非关。这是两种按键形式的处理原理也没啥特别,但是你有没有想过,如果一个系统里面这两种按键是怎么处理的?我想起了我以前的处理,分开两个非常类似的处理程序,现在看起来真的是笨的不行了,但

          是也没有办法啊,结构决定了程序。不过现在好了,用上面介绍的办法,很轻松就可以搞定。

          原理么?可能你也会想到,对于点触开关,按照上面的办法处理一次按下和长按,对于开关型,我们只需要处理Cont就OK了,为什么?很简单嘛,把它当成是一个长按键,这样就找到了共同点,屏蔽了所有的细节。程序就不给了,完全就是应用2的内容,在这里提为了就是说明原理~~

     

     

    转载原地址:http://www.51hei.com/bbs/dpj-41204-1.html,如侵删

    展开全文
  • 单片机键盘程序(4×4矩阵式).单片机键盘程序(4×4矩阵式).单片机键盘程序(4×4矩阵式).单片机键盘程序(4×4矩阵式).单片机键盘程序(4×4矩阵式).
  • 本文主要讲了单片机键盘程序设计示例 ,下面一起来学习下
  • 一个51单片机键盘扫描程序,算法简单有效  发一个51单片机键盘扫描程序,算法简单有效   再给大家分享一个不错按键程序(来自ourdev) /****************************************  键盘_不采用...
    一个51单片机的键盘扫描程序,算法简单有效 


    发一个51单片机的键盘扫描程序,算法简单有效 
                                          再给大家分享一个不错按键程序(来自ourdev)
    /**************************************** 


    键盘_不采用定时器_不延时 


    特点: 
    按键在松手后有效,灵敏度高,消耗资源少,运行效率高 


    独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7; 
    矩阵键盘为:行(上到下)_P2.3_P2.2_P2.1_P2.0 
               列(左到右)_P2.7_P2.6_P2.5_P2.4 


    提供的操作函数: 


    //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key 
    extern unsigned char keyboard_self(); 


    //矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位 
    extern unsigned char keyboard_matrix(); 


    ****************************************/


    .
     


    先看独立键盘(和矩阵键盘的算法一样) 
    ----------------------------------------------------------------------- 
    #include<reg52.h> 
    #include<intrins.h> 


    //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key 
    extern unsigned char keyboard_self() 

            unsigned char num_key=0;//按键号 
            unsigned char temp=0;//用于读取P2线上按键值 
            static unsigned char temp_code=0;//保存按键值 
            static unsigned char num_check=0;//低电平有效次数 
            static unsigned char key_flag=0;//按键有效标识 


            temp=P2&0xF0;//读取P2线数据 


            if(temp!=0xF0)//低电平判断 
            { 
                    num_check++; 
                    if(num_check==10)//连续10次(10ms)低电平有效,则认为按键有效 
                    { 
                            key_flag=1;//使能按键有效标识 
                            temp_code=temp;//保存按键值 
                    } 
            } 
            else//松手时判断 
            { 
                    num_check=0; 


                    if(key_flag==1)//按键有效 
                    { 
                            key_flag=0; 


                            switch(temp_code)//读取按键号 
                            { 
                                    case 0xE0: num_key=1; 
                                               break; 
                                    case 0xD0: num_key=2; 
                                               break; 
                                    case 0xB0: num_key=3; 
                                               break; 
                                    case 0x70: num_key=4; 
                                               break; 
                            } 
                    } 
            } 


            return(num_key); 

     


    现在是矩阵键盘的 
    ----------------------------------------------------------------------- 
    #include<reg52.h> 
    #include<intrins.h>  


    //矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位 
    extern unsigned char keyboard_matrix() 

            unsigned char num_key=0;//按键号 
            unsigned char temp=0;//读取P2口线数据 
            static unsigned char temp_code=0;//用于保存按键值 
            static unsigned char temp_circle=0xFE;//保存P2线上的循环扫描值 
            static unsigned char num_check=0;//低电平计数 
            static unsigned char key_flag=0;//按键有效标识 


            P2=temp_circle;//0xFX 
            temp=P2;//读取P2口线数据 
            if(temp!=temp_circle)//有按键动作 
            { 
                    num_check++;//低电平计数|逢低电平加1 
                    if(num_check==10)//连续10次(10ms)低电平有效 
                    { 
                            key_flag=1;//按键有效标识置1 
                            temp_code=temp;//保存按键值 
                    } 
            } 
            else//松手OR无按键动作,此时应该改变扫描线 
            { 
                    num_check=0; 
                    if(key_flag==1)//按键有效判断 
                    { 
                            key_flag=0; 
                            switch(temp_code)//读取按键号 
                            { 
                                    //P2^0线 
                                    case 0xEE: num_key=1; 
                                               break; 
                                    case 0xDE: num_key=2; 
                                               break; 
                                    case 0xBE: num_key=3; 
                                               break; 
                                    case 0x7E: num_key=4; 
                                               break; 
                                    //P2^1线 
                                    case 0xED: num_key=5; 
                                               break; 
                                    case 0xDD: num_key=6; 
                                               break; 
                                    case 0xBD: num_key=7; 
                                               break; 
                                    case 0x7D: num_key=8; 
                                               break; 
                                    //P2^2线 
                                    case 0xEB: num_key=9; 
                                               break; 
                                    case 0xDB: num_key=10; 
                                               break; 
                                    case 0xBB: num_key=11; 
                                               break; 
                                    case 0x7B: num_key=12; 
                                               break; 
                                    //P2^3线 
                                    case 0xE7: num_key=13; 
                                               break; 
                                    case 0xD7: num_key=14; 
                                               break; 
                                    case 0xB7: num_key=15; 
                                               break; 
                                    case 0x77: num_key=16; 
                                               break; 
                            } 
                    } 
                    temp_circle=_crol_(temp_circle,1);//改变扫描线 
                    if(temp_circle==0xEF) 
                    { 
                            temp_circle=0xFE; 
                    } 
            } 
            return(num_key);//返回按键号 



    /************************************************************************* 


    未按键时,扫描线一直变化。 
    长按键时,扫描线不变化,使得该行按键变成了独立按键,这样的扫描效率极高。 
    如当按下P2.0线上的某个键时,程序将扫描到这个键,而后扫描线不变化, 
    当键盘程序连续10次进入时检测到10次按键有效,直到松手后扫描线才变化 


    *************************************************************************/


    http://bbs.elecfans.com/jishu_184831_1_1.html


    展开全文
  • 以下程序功能很简单,但它演示了一个单片机程序的基本思路,程序本身很简单,也不很实用,实际工作中还会有好多要考虑的因素,比如主循环每次都调用灯的循环程序,会造成按钮反应“迟钝”,而如果一直按着键不放,则...
  • #include<reg52.h> typedef unsigned char uchar; typedef unsigned int uint; sbit a=P1^0;...uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}...

    #include<reg52.h>
    typedef unsigned char uchar;
    typedef unsigned int uint;
    sbit a=P1^0;
    uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    void delay(uint x);
    uchar temp,key,disnum;
    void main()
    {
    a=0; //接通第一个数码管
    disnum=16; //在没按按键时,数码管什么都不显示
    while(1) //大循环
    {
    P3=0xf0; //P3=11110000 列全为1,行全为0
    temp=P3; //在没有按键按下时temp=11110000,当有按键被按下时,temp!=11110000
    temp=temp&0xf0; //将temp的低四位全为0
    if(temp!=0xf0) //检测是否有按键被按下
    {
    delay(10); //延时,消抖
    if(temp!=0xf0) //检测是否有按键被按下
    {
    temp=P3; //将P3口实时的值赋给temp,此时的temp高四位有一位为0,低四位全为0
    temp=temp|0x0f; //将temp低四位全置1
    P3=temp; //将temp值赋给P3口
    key=P3; //用key读取P3口的值
    switch(key) //拿key的值与case后面的值进行对比
    {
    case 0xee : disnum=0;break; //当key=0x00时,把disnum=0并退出switch语句
    case 0xde : disnum=1;break;
    case 0xbe : disnum=2;break;
    case 0x7e : disnum=3;break;
    case 0xed : disnum=4;break;
    case 0xdd : disnum=5;break;
    case 0xbd : disnum=6;break;
    case 0x7d : disnum=7;break;
    case 0xeb : disnum=8;break;
    case 0xdb : disnum=9;break;
    case 0xbb : disnum=10;break;
    case 0x7b : disnum=11;break;
    case 0xe7 : disnum=12;break;
    case 0xd7 : disnum=13;break;
    case 0xb7 : disnum=14;break;
    case 0x77 : disnum=15;break;
    }
    }

    }
    P0=table[disnum]; //把数组中的第disnum位的真值赋给P0
    }
    }
    void delay(uint x) //延时函数,延时时间为x次所花费的时间
    {
    while(x–); //x进行自减,直到x=0时才跳出延时函数
    }

    展开全文
  • 51单片机矩阵键盘响应程序

    千次阅读 2018-01-27 18:39:22
    51单片机矩阵键盘响应程序 #include // P0端口接LED // P0端口接数码管 // P3端口接矩阵键盘 #define LED P0 #define KEY P3 #define DIG P0 unsigned char GetKey(void); void delay10ms(void); /...

    51单片机矩阵键盘响应程序

    #include <reg51.h>

    // P0端口接LED
    // P0端口接数码管
    // P3端口接矩阵键盘


    #define LED P0
    #define KEY P3
    #define DIG P0
    unsigned char GetKey(void);
    void delay10ms(void);
    // 独立数码管的段码表
    unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
    void main(void)
    {
    unsigned char key = 0;
    while (1)
    {
    key = GetKey();
    if (key != 0)
    {
    DIG = val[key];
    }
    }
    }
    unsigned char GetKey(void)
    {
    unsigned char hang = 0, lie = 0;
    unsigned char keyvalue = 0;
    // 第1回合第1步
    KEY = 0x0f; // 从IO口输出,写IO口
    if (KEY != 0x0f)// 从IO口输入,读IO口
    {
    // 读出的不是0x0f说明有按键被按下
    // 第1回合第2步:读出端口从读出值来判断是哪一行
     delay10ms();
    // 第一回合中算出行号
    switch (KEY)
    {
    case 0x0e:hang = 1; break;
    case 0x0d: hang = 2; break;
    case 0x0b: hang = 3; break;
    case 0x07: hang = 4; break;
    default: break;
    }
    // 第2回合第1步
    KEY = 0xf0;
    if (KEY != 0xf0)
    {
     switch (KEY)
    {
    case 0xe0:lie = 1; break;
    case 0xd0: lie = 2; break;
    case 0xb0: lie = 3; break;
    case 0x70: lie = 4; break;
    default: break;
    }
    // 经过2个回合后hang和lie都知道了,然后根据hang和lie去计算键值即可
    keyvalue = (hang - 1) * 4 + lie;
    return keyvalue;
    }
    }
    return 0;
    }
    void delay10ms(void)   //误差 0us
    {
        unsigned char a,b,c;
        for(c=5;c>0;c--)
            for(b=4;b>0;b--)
                for(a=248;a>0;a--);
    }


    展开全文
  • /****************************************键盘_不采用定时器_不延时特点:按键在松手后有效,灵敏度高,消耗资源少,运行效率高独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7;矩阵键盘为:行(上到下)_P2.3_P...
  • STC单片机按键扫描程序

    千次阅读 2018-10-17 11:07:39
    STC单片机按键扫描程序 最近在做一个电子秤相关项目,使用STC系列单片机作为主控芯片,项目第一阶段直接使用IAP15W4K58S4驱动两个矩阵键盘,一切调试顺利,在项目即将结束时老板要求使用另一块单片机驱动矩阵键盘,...
  • 51单片机矩阵键盘C程序

    千次阅读 2020-04-29 10:44:32
    51单片机矩阵键盘C程序程序1:void main() { uchar i,j,k i=0; j=0; while(1) { i=key();//键盘循环扫描,其值赋给变量数组table if(i!=0)//键盘程序返回值非0,即有按键按下 { table[j]=i;//将值存在...
  • 51单片机之矩阵键盘

    千次阅读 2019-05-16 21:28:15
    独立键盘单片机连接时,每一个按键都需要单片机的一个I/O口若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O口资源。单片机系统中I/O口资源往往比较宝贵,当用到多个按键时为了节省I/O口口线,我们引入...
  • 单片机键盘及显示器控制源程序 包括子函数 显示 初始化 //实验目的:熟悉MSSP通信协议。 //当按键RB0按下时,把6个连续的数据写入到6个连续的单元内 //写完成后数码管显示单个0,做为完成标志位 //当按键RB1按下后...
  • 51单片机PS2键盘程序

    热门讨论 2020-04-18 23:31:19
    我的其他资源都是免费的,是对于c语言初学者的帮助比较大的,其中有单片机,ARM,数据结构,window编程。我也在学c语言,每当我写完一个程序,我都会免费发上来。
  • 单片机键盘程序(4×4矩阵式)设计:用AT89S51的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F”序号。
  • 程序为51单片机开发中常用的4x4矩阵键盘扫描程序,精简,稳定,注释详细
  • 51单片机矩阵键盘输入液晶显示程序
  • 单片机按键使用程序 (51单片机

    千次阅读 2020-08-03 23:27:01
    单片机独立按键使用程序 (51单片机) 独立按键是单片机中很重要的一个器件,在这篇文章里,通过这个用独立按键控制LED灯的小程序来介绍独立按键开关的使用。 ...
  • 51单片机矩阵键盘扫描

    千次阅读 多人点赞 2015-11-30 17:03:45
    矩阵键盘检测之行列扫描法:对矩阵键盘按1至16的顺序进行编号,通过下面的扫描程序得到返回数值即可确定是哪个键被按下。矩阵键盘检测原理: 1、查询是否有键按下。 2、键的抖动处理。 3、查询按下键所在行和列...
  • C语言编写的C51单片机键盘扫描行扫描方法
  • 关注【电子开发圈】微信公众号,一起学习吧!...电子DIY、Arduino、51单片机、STM32单片机、FPGA…… 电子百科、开发技术、职业经验、趣味知识、科技头条、设备拆机…… 点击链接,免费下载100G+电子设计学习资料! ...
1 2 3 4 5 ... 20
收藏数 6,855
精华内容 2,742
关键字:

单片机 键盘程序