- /*
- * 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();
- }
- }