ARM7键盘工作原理及中断方式实现(C语言)

一般键盘结构如图所示.


图中的每个行列交叉处为一个按键。当键盘上没有任何按键动作,整个行列线均处于断开状态,此时列线输出为高电平,当某个按键被按下,则与此按键相连的行线被连通,此时对应列线电平输出则取决于行线的电平。如果将所有列线设置为输出,对应行线设置为输入,则可通过程序控制行线的电平状态,如,首先将第一行设置为低电平,其余行为高电平,此时依次检测列线电平输出状态,若第一列电平输出为低电平,表明第一列与第一行交叉处按键被按下,若第二列电平输出为低电平,则相应的第二列与第一行交叉处按键被按下,依次类推;判定为第一行后,将第一行与第三行设置为高电平,第二行设置为低电平。然后按照判定第一行的方法判定第二行,最后判定第三行。这种逐行逐列检测键盘电平状态的过程即为键盘的一次完整扫描。

CPU对键盘的扫描可采用轮询方式也可采用中断方式。中断实现的方式为:每当有按键被按下,则产生中断传递给CPU,CPU转入中断处理程序从而完成键值的判定及后续动作。键值的判定工作可由程序实现,也可由制定的行线、列线的状态表查询获取。

具体实现方面,在按键的断开和闭合过程中一般会产生抖动,具体的抖动时间和开关的机械特性有关,一般为5ms-10ms。为保证CPU对键值处理的可靠性,可在程序中添加适当的延时,消除抖动可能产生的错误。也可将行线和列线通过74AC245收发器与一个与非门相连,然后连接到IRQ0中断引脚,这样一旦键盘上有按键被按下,则产生中断信号,从而进入中断服务程序进行减值的判定及后续处理。收发器一般可将按键产生的抖动消除,避免CPU判断错误。

程序代码实现如下:

void IRQ_Keyboard_Handler (void)   __irq                                

{

  unsignedint    i;

 unsigned int    PA_ROW_Status;


 AT91PS_AIC   AIC0 =AT91C_BASE_AIC;

 AT91F_AIC_DisableIt(AIC0,AT91C_ID_IRQ0); //通过IRQ0引脚触发CPU中断

 PA_ROW_Status = (unsignedchar)((AT91F_PIO_GetInput(AT91C_BASE_PIOA)>>25)&0x1F);  //此处偏移地址与硬件设计引脚有关

 if(PA_ROW_Status==0x1E)         //判定键值

 { 

       AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, PIN_COL_1);           //置低电平

          AT91F_PIO_SetOutput(AT91C_BASE_PIOA,PIN_COL_2|PIN_COL_3);         //置高电平

          for (i=0;i<100;i++);  //让引脚电平趋于稳定

          PA_ROW_Status = (unsignedchar)((AT91F_PIO_GetInput(AT91C_BASE_PIOA)>>25)&0x1F);

          if(PA_ROW_Status==0x1E)                                                                 

          {                                                 

                   Button_Pressed_Value=0x00;                                                                      //表明按钮被按下

               KEY0_PRESSED_MARK=True;

          }

 

          AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,PIN_COL_2);    

          AT91F_PIO_SetOutput(AT91C_BASE_PIOA,PIN_COL_1|PIN_COL_3);

          for (i=0;i<100;i++);         

          PA_ROW_Status = (unsignedchar)((AT91F_PIO_GetInput(AT91C_BASE_PIOA)>>25)&0x1F);

          if(PA_ROW_Status==0x1E)

          {                                               

                   Button_Pressed_Value=0x01;                                                                                     

                   KEY1_PRESSED_MARK=True;                              

          }

                             

          AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,PIN_COL_3);

          AT91F_PIO_SetOutput(AT91C_BASE_PIOA,PIN_COL_1|PIN_COL_2);

          for (i=0;i<100;i++);         

          PA_ROW_Status=(unsigned char)((AT91F_PIO_GetInput(AT91C_BASE_PIOA)>>25)&0x1F);

          if(PA_ROW_Status==0x1E)

          {                                               

                   Button_Pressed_Value=0x02;           

                   KEY2_PRESSED_MARK=True; 

          }

  }

//此处可依次添加判定代码。

 AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,PIN_COL_1|PIN_COL_2|PIN_COL_3);     //全部置低电平

  for(i=0;i<100;i++);

 PA_ROW_Status = (unsignedchar)((AT91F_PIO_GetInput(AT91C_BASE_PIOA)>>25)&0x1F);   

 

 while(PA_ROW_Status!=0x1F)                                                                                                       //等到按键抬起再退出中断

  {

          PA_ROW_Status = (unsignedchar)((AT91F_PIO_GetInput(AT91C_BASE_PIOA)>>25)&0x1F);

  }       

 AT91F_AIC_AcknowledgeIt(AIC0);  //End of Interrupt      

 AT91F_AIC_ClearIt(AIC0,AT91C_ID_IRQ0);        //Clear the Interrupt

 AT91F_AIC_EnableIt(AIC0,AT91C_ID_IRQ0);    //Enable ENDRX Interrupt

}

void IRQ_Init(void) //config the AIC

{

  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,AT91C_ID_IRQ0,6,

                             AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE,(void(*)())IRQ_Keyboard_Handler);     //配置为边沿触发。

  AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_IRQ0);            //Enable IRQ Interrupt        

}

 

void main(void)

{

         PMC_Init(); //使能外设引脚

         Config_Pio(); //引脚配置初始化

 IRQ_Init();

 

While(1)

{

         ;

}

}



(文章原创,转载请声明)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值