/*
* GccApplication23.c
*
* Created: 2014-9-17 20:39:58
* 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,0xBF,};
uchar dis_buff[8];
uchar key_flag;
void delay(uint k) //延时约0.1ms
{
uint m,n;
for(m=0;m<k;m++)
{
for(n=0;n<114;n++);
}
}
void display(void)
{
PORTB=0x01;
PORTC=tab[dis_buff[0]];
delay(10);
PORTB=0x02;
PORTC=tab[dis_buff[1]];
delay(10);
PORTB=0x04;
PORTC=tab[dis_buff[2]];
delay(10);
PORTB=0x08;
PORTC=tab[dis_buff[3]];
delay(10);
PORTB=0x10;
PORTC=tab[dis_buff[4]];
delay(10);
PORTB=0x20;
PORTC=tab[dis_buff[5]];
delay(10);
PORTB=0x40;
PORTC=tab[dis_buff[6]];
delay(10);
PORTB=0x80;
PORTC=tab[dis_buff[7]];
delay(10);
}
uchar ScanKey() //键盘扫描
{
uchar temp,temp1,key;
temp=PIND; //读取PD端口状态
temp&=0x0F; //判断行线状态
switch(temp)
{
case 0x0E: //行线的PD0为低电平
{
DDRD=0x0F; //改变端口方向,准备进行列线的状态判断
PORTD=0xF0;
delay(5); //延时片刻,以利于状态的获取
temp1=PIND; //读取PD端口状态
temp1&=PIND; //判断列线状态
switch(temp1)
{
case 0x70: //列线的PD7为低电平,表示“0”键按下
key=0; //键值为0
break; //跳出列线状态判断
case 0xB0: //列线的PD6为低电平,表示“1”键按下
key=1; //键值为1
break; //跳出列线状态判断
case 0xD0: //列线的PD5为低电平,表示“2”键按下
key=2;
break;
case 0xE0: //列线的PD4为低电平,表示“3”键按下
key=3;
break;
default: //列线没发生状态改变
key=0;
break;
}
DDRD=0xF0; //改变PD端口方向,为下次行线判断做好准备
PORTD=0x0F;
break;
}
case 0x0D: //行线的PD1为低电平
{
DDRD=0x0F; //改变端口方向,准备进行列线的状态判断
PORTD=0xF0;
delay(5);
temp1=PIND; //读取PD端口状态
temp1&=PIND; //判断列线状态
switch(temp1)
{
case 0x70: //列线的PD7为低电平,表示“4”键按下
key=4;
break;
case 0xB0: //列线的PD6为低电平,表示“5”键按下
key=5;
break;
case 0xD0: //列线的PD5为低电平,表示“6”键按下
key=6;
break;
case 0xE0: //列线的PD4为低电平,表示“7”键按下
key=7;
break;
default: //列线没发生状态改变
key=0;
break;
}
DDRD=0xF0; //改变PD端口方向,为下次行线判断做好准备
PORTD=0x0F;
break;
}
case 0x0B: //行线的PD2为低电平
{
DDRD=0x0F; //改变端口方向,准备进行列线的状态判断
PORTD=0xF0;
delay(5);
temp1=PIND; //读取PD端口状态
temp1&=PIND; //判断列线状态
switch(temp1)
{
case 0x70: //列线的PD7为低电平,表示“8”键按下
key=8;
break;
case 0xB0: //列线的PD6为低电平,表示“9”键按下
key=9;
break;
case 0xD0: //列线的PD5为低电平,表示“A”键按下
key=10;
break;
case 0xE0: //列线的PD4为低电平,表示“B”键按下
key=11;
break;
default: //列线没发生状态改变
key=0;
break;
}
DDRD=0xF0; //改变PD端口方向,为下次行线判断做好准备
PORTD=0x0F;
break;
}
case 0x07: //行线的PD3为低电平
{
DDRD=0x0F; //改变端口方向,准备进行列线的状态判断
PORTD=0xF0;
delay(5);
temp1=PIND; //读取PD端口状态
temp1&=PIND; //判断列线状态
switch(temp1)
{
case 0x70: //列线的PD7为低电平,表示“C”键按下
key=12;
break;
case 0xB0: //列线的PD6为低电平,表示“D”键按下
key=13;
break;
case 0xD0: //列线的PD5为低电平,表示“E”键按下
key=14;
break;
case 0xE0: //列线的PD4为低电平,表示“F”键按下
key=15;
break;
default: //列线没发生状态改变
key=0;
break;
}
DDRD=0xF0; //改变PD端口方向,为下次行线判断做好准备
PORTD=0x0F;
break;
}
default: //行线没发生状态改变
key=0;
break;
}
return(key); //返回键值
}
int main(void)
{
uchar x;
uchar temp,keynum;
DDRB=0xFF;
PORTB=0xFF;
DDRD=0xF0;
PORTD=0x0F;
DDRC=0xFF;
PORTC=0xFF;
for(x=0;x<8;x++) //初始状态显示8个"-"
{
dis_buff[x]=16;
}
while (1)
{
temp=PIND; //判断是否有按键
temp&=0x0F;
if(temp==0x0F)
{
key_flag=0;
}
else
{
delay(100); //约10ms延时去抖
temp=PIND; //判断是否有按键
temp&=0x0F;}
if(temp==0x0F)
{
key_flag=0;
}
else
{
key_flag=1;
keynum=ScanKey(); //键值送keynum
}
while(temp!=0x0F)
{
temp=PIND;
temp&=0x0F;
}
if(key_flag==1)
{
dis_buff[0]=dis_buff[1];
dis_buff[1]=dis_buff[2];
dis_buff[2]=dis_buff[3];
dis_buff[3]=dis_buff[4];
dis_buff[4]=dis_buff[5];
dis_buff[5]=dis_buff[6];
dis_buff[6]=dis_buff[7];
dis_buff[7]=keynum;
}
display();
}
}