4*4键盘扫描文档<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
今天把4*4键盘的程序从单片机上移植到了NIOS上。
4*4键盘扫描电路
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
程序采用间隔时间进行扫描法,由于键盘的抖动时间为10ms-20ms之间,所以在定时器中加入一个标志位,当定时10ms后,就进入判断,采用类似FPGA的状态机法,进行扫描。有效的避开了抖动。
状态一,判断是否有键按下,有键按下,则转到状态二。
状态二:再进行判断有没键按下,有按下,则进行扫描,进入状态三。没有,则返回状态一。
状态三: 根据行码,和列码进行判断键值,根据相应的键值执行相应的程序。进入状态四
状态四: 判断键是否释放,松开,则返回状态一,没有,则在状态四。
首先分为行信号(key4—key7),作为输入端口,用于读取IO口上的电平值,初始时写0。
列信号(key0---key3),作为输出端口,为送入扫描信号。
在初始时,将所有的列信号(输出口)(key3—key3)置为低电平,在没有任何键按下时,读取(输入口)key4—key7上的电平值将为1,当任何一个按键按下时,则key4-key7中将会有一行被拉低,则表示有键按下。
这时就开始从key0-key3送入扫描字,进行扫描。扫描字为0111,1011,1101,1110。
如果在它的输入端口发现一个0值,则就知道了在哪一列上有键按下。没有的话,则扫描字左移,继续扫描。根据行值,列值,来读出键值。
根据上面的接口电路。Key7—key0对应着键盘的接口高位到低位。
假如:开始key7-key4作为输入口,由于上拉电阻,则读出的数据为1,key0-key3作为输出口,写低电平。当键S4按下时,则Key4电平被拉低,判断出在第一行上有键按下。这时,进行扫描。在key0-key3送入扫描字1110,读取key4-key7口上电平,发现key4上的电平为0,则判断出第四列有键按下。则得出s4键按下。键值为key7:key0=1110 (行码)&1110(列扫描字)==1110 1110以此累推。
总结:经过移植几种程比较,这种效率最高。而且占用的时间比较少。不过在NIOS上移植,可以结合FPGA,直接做个4*4键盘扫描控制器,当有键按下时,可以进入中断。这样的话,节省了CPU的时间。当有键按下时,送出键按下标志位。进入中断。读取键值,执行键盘程序。可见NIOS的强大功能,和可配置性,还有很多东西待去学习。
/**********************************************************
*功能: 键盘扫描函数
*说明:
*********************************************************/
unsigned char read_key(void)
{
unsigned char i;
unsigned char key_return = 0;
IOWR_ALTERA_AVALON_PIO_DIRECTION(KEY_PIO_BASE,0X<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />0f);
//高四位作为输入,读取数据,低四位为输出
Key_data=0x00;//低四位输出口写0
switch (key_state)
{
case 0:
// 读按键高四位I/O电平,当有键按下时为0,没按下时为1
if((IORD_ALTERA_AVALON_PIO_DATA(KEY_PIO_BASE)&0xf0)==0xf0)
{
break;//无键按下返回
}
else
{
key_state=1; //有键按下
}break;
case 1://进行扫描键值
{
if((IORD_ALTERA_AVALON_PIO_DATA(KEY_PIO_BASE)&0xf0)==0xf0)
//读取高四位电平
{
break;//无键按下返回,是误动作
}
else
{ //有键按下去抖
key_line=0x08;
for(i=1;i<=4;i++)
{
Key_data=~key_line;//1111 0111
key_value=0xf0&IORD_ALTERA_AVALON_PIO_DATA(KEY_PIO_BASE);
if (key_value == 0xf0)
{
key_line >>= 1; // 没有按键,继续扫描
}
else
{
key_state=2; // 有按键,停止扫描,转入下一个状态
}
}
}
}
case 2:
{
switch (key_line|key_value) //0000 1000
{
case 0x78:
key_return=1;break;
case 0x74:
key_return=2;break;
case 0x72:
key_return=3;break;
case 0x71:
key_return=4;break;
case 0xb8:
key_return=5; break;
case 0xb4:
key_return=6;break;
case 0xb2:
key_return=7;break;
case 0xb1:
key_return=8;break;
case 0xd8:
key_return=9;break;
case 0xd4:
key_return=10;break;
case 0xd2:
key_return=11;break;
case 0xd1:
key_return=12;break;
case 0xe8:
key_return=13; break;
case 0xe4:
key_return=14;break;
case 0xe2:
key_return=15;break;
case 0xe1:
key_return=16;break;
}
key_state = 3; // 状态转换到键释放态
} break;
case 3: //键已经释放,确认了有键按下
{
Key_data=0xf0;//低四位写0,高四位作为输入口,不受影响
if((0xf0&IORD_ALTERA_AVALON_PIO_DATA(KEY_PIO_BASE))==0xf0)
key_state = 0;
}
break; //按键已释放,转换到按键初始态
}
return key_return; //当返回为0时,表示没有键按下,
}
用户178123 2009-2-14 09:44
用户178123 2009-2-14 09:42
crazy_embeddedsystem_775092187 2007-12-12 12:47
多个按键同时按下了怎么处理??
用户1316816 2007-12-11 13:31
用户65681 2007-12-11 09:44