第十课学习

按键在未按下时,处于一种高电平状态,一般这种情况下,其对IO口的电平一致,则不会产生任何效果,只有在按下状态时,由于与接地的回路贯通,故相当于单片机的IO口直接接地。从原理图上看,之所以要接KeyIn1-KeyIn4外接至按键中,主要原因是为了获取按键的状态,因为我们只能获取单片机的IO口状态,而不能直接获取按键本身是否按下的状态,所以只能通过这个电路,通过IO口接地的情况,人为造成IO为低电平,从而判断按键被按下,如果我们不细致地把这个原因考虑清楚,而仅仅只是按这种电路图直接连接的话,势必是知其然而不知其所以然。

现在我们有16个按键,通过四个Out和四个In进行组合,但我们需要明白一个问题,Out的主要目标是为了产生低电平,从而才能够使按键按下后,对地电路导通。那么,如何进行控制Out的电平呢?如果默认情况下全部为低电平可不可以?答案是不可以的,因为假定其全部为底电平,此时比如我如果按下key1,key5,那么都会导致KeyIn1为低电平,那么我们如何判定是按了key1还是key5呢?所以不能将其全部设定为低电平,更何况如果全部是低电平,还何必要它们从单片机的IO引出来呢,直接接地就可以了。这里其实还是利用了与点阵LED与数码管一样的原理,就是扫描的方式。逐个令Keyout1-keyout4循环为低,则此时对应的那一排key值如有按下,则对应的keyin起作用,而如果不在同一排则按键不起作用。

下面是我实现的一个在最右边的那个数码管显示按键值的示例代码,其值从0到F进行显示。

#include <reg52.h>

typedef unsigned char uint8;

typedef unsigned int  uint16;

typedef unsigned long uint32;

 

//数码管的显示数字,从0至F一共16个字符

code uint8number[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

code uint8 keys[] ={0xe7,0xd7,0xb7,0x77,0xeb,0xdb,0xbb,0x7b,0xed,0xdd,0xbd,0x7d,0xee,0xde,0xbe,0x7e};

 

uint8 k=0;

uint8 counter=0;

 

sbit ENLED = P1^4;

sbit ADDR0 = P1^0;

sbit ADDR1 = P1^1;

sbit ADDR2 = P1^2;

sbit ADDR3 = P1^3;

sbit KeyOut1 = P2^3;

sbit KeyOut2 = P2^2;

sbit KeyOut3 = P2^1;

sbit KeyOut4 = P2^0;

 

 

//初始化计数器1

void init_timer1()

{

       TMOD|= 0x10;

       TMOD&= 0xdf; 

       TH1   = 0xFC;

       TL1   = 0x67;

       TR1   = 1;

}

//初始化中断响应

void init_interrupt()

{

       ET1= 1;

       EA  = 1;

}

 

void refresh_KeyOut()

{

         static uint8 j = 0;

        

         switch(j)

         {

            case0: KeyOut1=0;KeyOut2=1;KeyOut3=1;KeyOut4=1;break;

              case1: KeyOut2=0;KeyOut1=1;KeyOut3=1;KeyOut4=1;break;

              case2: KeyOut3=0;KeyOut1=1;KeyOut2=1;KeyOut4=1;break;

              case3: KeyOut4=0;KeyOut1=1;KeyOut2=1;KeyOut3=1;break;         

              default:break;

         }   

         if(3 == j++) j = 0;     

}

uint8 temp=0;

uint8 j=0;

uint8 i=0;

main()

{

 

       ENLED= 0; ADDR3 = 1;

       init_timer1();

       init_interrupt();

       ADDR0=0;

       ADDR1=0;

       ADDR2=0;

      

       while(1)

       {

              temp= P2;

              i=0;

              for(;i<16;i++)

              {

                     if(temp== keys[i])

                     {

                            j=i;

                            break;

                     }

              }

              P0=number[j];      

       }

      

}

void interrupt_timer1()   interrupt 3

{

         TH1 = 0xFC;

         TL1 = 0x67;

        

         if(10==counter++)

         {

            //切换KeyOut的输出,如果太快,则很难把握用户到底按下了

               //哪个按,只能在一段延时的情况下,进行判断用户按下了哪个键

               counter=0;

              refresh_KeyOut();

         }

                                           

}

上面代码中的keys数组所保存的是P2在不同按键时的值。其来源是通过如下方法获得的:

 

P2 7   6   5  4   3     2  1    0

   In4 In3 In2 In1 Out1 Out2 Out3 Out4

k1 1   1   1  0   0     1   1   1   =0xe7=0

k2 1   1   0  1   0     1   1   1   =0xd7=1

k3 1   0   1  1   0     1   1   1   =0xb7=2

k4 0   1   1  1   0     1   1   1   =0x77=3

k5 1   1   1  0   1     0   1   1   =0xeb=4

k6 1   1   0  1   1     0   1   1   =0xdb=5

k7 1   0   1  1   1     0   1   1   =0xbb=6

k8 0   1   1  1   1     0   1   1   =0x7b=7

k9 1   1   1  0   1     1   0   1   =0xed=8

k10 1  1   0   1  1     1    0  1   =0xdd=9

k11 1  0   1   1  1     1    0  1   =0xbd=a

k12 0  1   1   1  1     1    0  1   =0x7d=b

k13 1  1   1   0  1     1    1  0   =0xee=c

k14 1  1   0   1  1     1    1  0   =0xde=d

k15 1  0   1   1  1     1    1  0   =0xbe=e

k16 0  1   1   1  1     1    1   0  =0x7e=f


阅读更多
文章标签: timer io x86
个人分类: 单片机
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭