专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

AVR单片机矩阵键盘程序(2种方法)

作者:佚名   来源:本站原创   点击数:  更新时间:2012年06月05日   【字体:

AVR矩阵键盘2种方法实现!

普通方法:

#include<iom16v.h>//
#include<macros.h>//
#define uchar unsigned char//
#define uint unsigned int//
#define setb(val,bitn) (val|=(1<<(bitn)))//设置某IO口某位为1
#define clr(val,bitn) (val&=~(1<<(bitn)))//设置某IO口某位为0
#define get(val,bitn) (val&(1<<(bitn)))//读取某位状态如if(get(PORTC,7))即判断PC7口是否为1
#pragma data:code//数组存放位置
const table[]={
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,
0x8e
};//共阳数码管0--9代码
uchar num,yin,temp;//键值码及识别码
void delay(uchar);//延时函数
void  disy();//显示函数
void skk()
{
  for(yin=0;yin<2;yin++)
  {
   PORTD=0xfe;//将第一行置0,即检测第一行
  temp=PIND;//将值给tem
  temp=temp&0xf0;//与0xf0与门一下,
  while(temp!=0xf0)//判断是否为0xf0
  {
   delay(10);//延时
   temp=PIND;//将P1值再给tem
   temp=temp&0xf0;//将值再与门
   while(temp!=0xf0)//再次判断是否为0xf0
   {
    temp=PIND;//确实按下了,将tem值装回,以便下次判断开关语句,否则没有它对应的值,如原来是ee,如果再按下是第二个键就不是de了
    switch(temp)//开关语句
     {
      case 0xee:num=0;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xde:num=1;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xbe:num=2;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0x7e:num=3;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
     }
    while(temp!=0xf0)//松手判断,以便退出以上两个while
    {
     temp=PIND;//给temp赋值
     temp=temp&0xf0;//与门一下
    }
   }
  }
 }
 
  for(yin=0;yin<2;yin++)
      {
   PORTD=0xfd;//将第一行置0,即检测第一行
  temp=PIND;//将值给tem
  temp=temp&0xf0;//与0xf0与门一下,
  while(temp!=0xf0)//判断是否为0xf0
  {
   delay(10);//延时
   temp=PIND;//将P1值再给tem
   temp=temp&0xf0;//将值再与门
   while(temp!=0xf0)//再次判断是否为0xf0
   {
    temp=PIND;//确实按下了,将tem值装回,以便下次判断开关语句,否则没有它对应的值,如原来是ee,如果再按下是第二个键就不是de了
    switch(temp)//开关语句
     {
      case 0xed:num=4;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xdd:num=5;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xbd:num=6;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0x7d:num=7;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
     }
    while(temp!=0xf0)//松手判断,以便退出以上两个while
    {
     temp=PIND;//给temp赋值
     temp=temp&0xf0;//与门一下
    }
   }
  }
 }
 for(yin=0;yin<2;yin++)
      {
   PORTD=0xfb;//将第一行置0,即检测第一行
  temp=PIND;//将值给tem
  temp=temp&0xf0;//与0xf0与门一下,
  while(temp!=0xf0)//判断是否为0xf0
  {
   delay(10);//延时
   temp=PIND;//将P1值再给tem
   temp=temp&0xf0;//将值再与门
   while(temp!=0xf0)//再次判断是否为0xf0
   {
    temp=PIND;//确实按下了,将tem值装回,以便下次判断开关语句,否则没有它对应的值,如原来是ee,如果再按下是第二个键就不是de了
    switch(temp)//开关语句
     {
      case 0xeb:num=8;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xdb:num=9;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xbb:num=10;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0x7b:num=11;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
     }
    while(temp!=0xf0)//松手判断,以便退出以上两个while
    {
     temp=PIND;//给temp赋值
     temp=temp&0xf0;//与门一下
    }
   }
  }
 }
  for(yin=0;yin<2;yin++)
       {
   PORTD=0xf7;//将第一行置0,即检测第一行
  temp=PIND;//将值给tem
  temp=temp&0xf0;//与0xf0与门一下,
  while(temp!=0xf0)//判断是否为0xf0
  {
   delay(10);//延时
   temp=PIND;//将P1值再给tem
   temp=temp&0xf0;//将值再与门
   while(temp!=0xf0)//再次判断是否为0xf0
   {
    temp=PIND;//确实按下了,将tem值装回,以便下次判断开关语句,否则没有它对应的值,如原来是ee,如果再按下是第二个键就不是de了
    switch(temp)//开关语句
     {
      case 0xe7:num=12;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xd7:num=13;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0xb7:num=14;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
      case 0x77:num=15;//与num值比较是否相等,如果相等就退出switch语句
      break;//退出switch语句
     }
    while(temp!=0xf0)//松手判断,以便退出以上两个while
    {
     temp=PIND;//给temp赋值
     temp=temp&0xf0;//与门一下
    }
   }
  }

 }
}
void main()
{
     DDRD|=0xff;//设置PB口为输出
     PORTD|=0xff;//PB输出为高电位
     DDRD&=0x0f;//设置高
     while(1)//大循环
     {
      skk();
 disy();//调用显示子程序 
     }
}
void delay(uchar z)//延时子函数
{
 uchar x,y;
 for(x=100;x>0;x--)
 for(y=z;y>0;y--); 
}
void disy()//显示子函数
{   
     DDRC=0xff;
     DDRB=0xff;
     PORTB=table[num];
     PORTC=0x00;
}

简单方法:

#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#pragma data:code//定义程序存在ROM里面
const table[]={
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,
0x8e,0xff
};
/***********************************************/
/*******************延时子程序******************/
/***********************************************/
void delay(uchar z)
{
   uchar x,y;
  for(x=0;x<50;x++)
  for(y=0;y<z;y++);
}
/***********************************************/
/*******************显示子程序******************/
/***********************************************/
void xian(uchar num)
{
  uchar i;
 PORTB=table[num];//十位
 PORTC=0x00;
}
/***********************************************/
/***************按键按下处理程序***************/
/***********************************************/
uchar key_press()
{
     uchar i;
     DDRD=0XFF;//设置PD口全为输出
  PORTD=0XF0;//设置PD高四位为高电平,以便进行判断
  DDRD=0X0F;//设置高4位为输入,低4位为输出
  i=PIND;//读出IO口状态
  if(i==0XF0)//如果它等于0XF0就执返回0
  {
    DDRD=0XFF;//将IO口值读回来
    return 0;
  }
  else//否则它就执返回1
  {
    DDRD=0XFF;
    return 1;
  }
}
/***********************************************/
/***************按键键值处理程序***************/
/***********************************************/
uchar key_scan()
{
    uchar key,i=0X7F,j;//将变量I设置为01111111B
 if(key_press())//判断按键是否被按下了
 {
      delay(10);//如果被按下了,消下抖
   if(key_press())//再次判断下按键是否被按下了
   {
     do//先执行一次
  {
   i=(i<<1|i>>7);/*将变量I内容左移1位,11111110
   然后将I右移7位,11111110,即实现11111110
   11111101 11111011 11110111*/
   PORTD=i;//将移位后的值给PD口
   DDRD=0X0F;//将PD口高位设为输入,低位设为输出
   key=PIND;//将IO口高位值读一下
   j=key&0XF0;//只需要读高4位
    }
  while(j==0XF0);//如果按键没有按下,则再执行上面的do语句
  while(key_press());//如果有按下则释放一下
  switch(key)//确定有按键按下了就判断下到底是哪个值
  {
          case 0xEE:
      key=0x0;
   break;
      case 0xDE:
      key=0x1;
   break;
      case 0xBE:
      key=0x2;
   break;
      case 0x7E:
      key=0x3;
   break;
      case 0xED:
      key=0x4;
   break;
      case 0xDD:
      key=0x5;
   break;
      case 0xBD:
      key=0x6;
   break;
     case 0x7D:
      key=0x7;
   break;
      case 0xEB:
      key=8;
   break;
      case 0xDB:
      key=9;
   break;
      case 0xBB:
      key=0xA;
   break;
      case 0x7B:
      key=0xB;
   break;
      case 0xE7:
      key=0xC;
   break;
      case 0xD7:
      key=0xD;
   break;
        case 0xB7:
      key=0xE;
   break;
      case 0x77:
      key=0xF;
   break;
  }
  }
  }
  return key;//返回按键值
}
/***********************************************/
/*******************主程序*********************/
/***********************************************/
void main()
{
   uchar ik=16;//定义局部变量
   DDRB=0xff;//设置PB口为输出
  DDRC=0xff;//设置PC口为输出
  while(1)
  {
     ik=key_scan();//将按键返回值给变量IK
     if(ik<16)//如果返回值小于16就在数码管上显示出来
   xian(ik); //调用显示子程序
   else//如果返回值不小于16,就显示黑屏
   xian(16);
  }
}

关闭窗口

相关文章