您的位置:首页 > 编程语言 > C语言/C++

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

2013-01-07 16:42 295 查看
一般键盘结构如图所示.



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

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)

{

;

}

}

(文章原创,转载请声明)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: