距阵按键也很好理解,就是发收换位,一排管脚前几个发,后几个收,然后在反过来。
以下是Proteus的仿真结果。
以下是在Atmel Studio 6,2的运行结果
以下是程序:
/*
* GccApplication22.c
*
* Created: 2014-9-16 21:23:06
* Author: Administrator
*/
#include <avr/io.h>
#define uchar unsigned char
#define uint unsigned int
uchar tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, //共阳极LED 0~F的段码
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x00};
void delay(uint k)
{
uint m,n;
for(m=0;m<k;m++)
{
for(n=0;n<114;n++);
}
}
uchar ScanKey()
{
uchar temp,temp1,key;
temp=PIND;
temp&=0x0F;
switch(temp)
{
case 0x0E:
{
DDRD=0x0F;
PORTD=0xF0;
delay(5);
temp1=PIND;
temp1&=PIND;
switch(temp1)
{
case 0xE0:
key=0;
break;
case 0xD0:
key=1;
break;
case 0xB0:
key=2;
break;
case 0x70:
key=3;
break;
default:
key=0;
break;
}
DDRD=0xF0;
PORTD=0x0F;
break;
}
case 0x0D:
{
DDRD=0x0F;
PORTD=0xF0;
delay(5);
temp1=PIND;
temp1&=PIND;
switch(temp1)
{
case 0xE0:
key=4;
break;
case 0xD0:
key=5;
break;
case 0xB0:
key=6;
break;
case 0x70:
key=7;
break;
default:
key=0;
break;
}
DDRD=0xF0;
PORTD=0x0F;
break;
}
case 0x0B:
{
DDRD=0x0F;
PORTD=0xF0;
delay(5);
temp1=PIND;
temp1&=PIND;
switch(temp1)
{
case 0xE0:
key=8;
break;
case 0xD0:
key=9;
break;
case 0xB0:
key=10;
break;
case 0x70:
key=11;
break;
default:
key=0;
break;
}
DDRD=0xF0;
PORTD=0x0F;
break;
}
case 0x07:
{
DDRD=0x0F;
PORTD=0xF0;
delay(5);
temp1=PIND;
temp1&=PIND;
switch(temp1)
{
case 0xE0:
key=12;
break;
case 0xD0:
key=13;
break;
case 0xB0:
key=14;
break;
case 0x70:
key=15;
break;
default:
key=0;
break;
}
DDRD=0xF0;
PORTD=0x0F;
break;
}
default:
key=0;
break;
}
return(key);
}
int main(void)
{
uchar temp,keynum;
DDRD=0xF0;
PORTD=0x0F;
DDRC=0xFF;
PORTC=0xFF;
while (1)
{
temp=PIND; //判断是否有按键
temp&=0x0F;
if(temp==0x0F)
{
continue;
}
else
{
delay(100); //约10ms延时去抖
temp=PIND; //判断是否有按键
temp&=0x0F;
}
if(temp==0x0F)
{
continue;
}
else
{
keynum=ScanKey();
PORTC=tab[keynum];
}
while(temp!=0x0F)
{
temp=PIND;
temp&=0x0F;
}
}
}
|