打印
[Atmel]

用AtmelStudio6.2跑mega16例程(16):另类距阵按键

[复制链接]
937|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
这个是另一种解决方法,proteus仿真结果:


以下是程序:
/*
* 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();
        }
}



相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://shop34182318.taobao.com/ http://shop562064536.taobao.com

2398

主题

6955

帖子

67

粉丝