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

[复制链接]
1131|0
 楼主| ddllxxrr 发表于 2014-9-17 21:17 | 显示全部楼层 |阅读模式
这个是另一种解决方法,proteus仿真结果:


以下是程序:
  1. /*
  2. * GccApplication23.c
  3. *
  4. * Created: 2014-9-17 20:39:58
  5. *  Author: Administrator
  6. */


  7. #include <avr/io.h>
  8. #define uchar unsigned char
  9. #define uint unsigned int
  10. uchar tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,  //共阳极LED  0~F的段码
  11. 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF,};
  12. uchar dis_buff[8];
  13. uchar key_flag;
  14. void  delay(uint k)            //延时约0.1ms
  15. {
  16.         uint  m,n;
  17.         for(m=0;m<k;m++)
  18.         {
  19.                 for(n=0;n<114;n++);
  20.         }
  21. }
  22. void display(void)
  23. {
  24.         PORTB=0x01;
  25.         PORTC=tab[dis_buff[0]];
  26.         delay(10);
  27.         PORTB=0x02;
  28.         PORTC=tab[dis_buff[1]];
  29.         delay(10);
  30.         PORTB=0x04;
  31.         PORTC=tab[dis_buff[2]];
  32.         delay(10);
  33.         PORTB=0x08;
  34.         PORTC=tab[dis_buff[3]];
  35.         delay(10);
  36.         PORTB=0x10;
  37.         PORTC=tab[dis_buff[4]];
  38.         delay(10);
  39.         PORTB=0x20;
  40.         PORTC=tab[dis_buff[5]];
  41.         delay(10);
  42.         PORTB=0x40;
  43.         PORTC=tab[dis_buff[6]];
  44.         delay(10);
  45.         PORTB=0x80;
  46.         PORTC=tab[dis_buff[7]];
  47.         delay(10);
  48. }
  49. uchar ScanKey()               //键盘扫描
  50. {
  51.         uchar temp,temp1,key;
  52.         temp=PIND;                //读取PD端口状态
  53.         temp&=0x0F;                //判断行线状态
  54.         switch(temp)
  55.         {
  56.                 case 0x0E:                //行线的PD0为低电平
  57.                 {
  58.                         DDRD=0x0F;       //改变端口方向,准备进行列线的状态判断
  59.                         PORTD=0xF0;
  60.                         delay(5);            //延时片刻,以利于状态的获取
  61.                         temp1=PIND;         //读取PD端口状态
  62.                         temp1&=PIND;        //判断列线状态
  63.                         switch(temp1)
  64.                         {
  65.                                 case 0x70:          //列线的PD7为低电平,表示“0”键按下
  66.                                 key=0;         //键值为0
  67.                                 break;          //跳出列线状态判断
  68.                                 case 0xB0:         //列线的PD6为低电平,表示“1”键按下
  69.                                 key=1;          //键值为1
  70.                                 break;          //跳出列线状态判断
  71.                                 case 0xD0:         //列线的PD5为低电平,表示“2”键按下
  72.                                 key=2;
  73.                                 break;
  74.                                 case 0xE0:          //列线的PD4为低电平,表示“3”键按下
  75.                                 key=3;
  76.                                 break;
  77.                                 default:              //列线没发生状态改变
  78.                                 key=0;
  79.                                 break;
  80.                         }
  81.                         DDRD=0xF0;          //改变PD端口方向,为下次行线判断做好准备
  82.                         PORTD=0x0F;
  83.                         break;
  84.                 }
  85.                 case 0x0D:                  //行线的PD1为低电平
  86.                 {
  87.                         DDRD=0x0F;         //改变端口方向,准备进行列线的状态判断
  88.                         PORTD=0xF0;
  89.                         delay(5);
  90.                         temp1=PIND;          //读取PD端口状态
  91.                         temp1&=PIND;         //判断列线状态
  92.                         switch(temp1)
  93.                         {
  94.                                 case 0x70:           //列线的PD7为低电平,表示“4”键按下
  95.                                 key=4;
  96.                                 break;
  97.                                 case 0xB0:           //列线的PD6为低电平,表示“5”键按下
  98.                                 key=5;
  99.                                 break;
  100.                                 case 0xD0:          //列线的PD5为低电平,表示“6”键按下
  101.                                 key=6;
  102.                                 break;
  103.                                 case 0xE0:          //列线的PD4为低电平,表示“7”键按下
  104.                                 key=7;
  105.                                 break;
  106.                                 default:              //列线没发生状态改变
  107.                                 key=0;
  108.                                 break;
  109.                         }
  110.                         DDRD=0xF0;          //改变PD端口方向,为下次行线判断做好准备
  111.                         PORTD=0x0F;
  112.                         break;
  113.                 }
  114.                 case 0x0B:                  //行线的PD2为低电平
  115.                 {
  116.                         DDRD=0x0F;         //改变端口方向,准备进行列线的状态判断
  117.                         PORTD=0xF0;
  118.                         delay(5);
  119.                         temp1=PIND;          //读取PD端口状态
  120.                         temp1&=PIND;          //判断列线状态
  121.                         switch(temp1)
  122.                         {
  123.                                 case 0x70:           //列线的PD7为低电平,表示“8”键按下
  124.                                 key=8;
  125.                                 break;
  126.                                 case 0xB0:           //列线的PD6为低电平,表示“9”键按下
  127.                                 key=9;
  128.                                 break;
  129.                                 case 0xD0:           //列线的PD5为低电平,表示“A”键按下
  130.                                 key=10;
  131.                                 break;
  132.                                 case 0xE0:           //列线的PD4为低电平,表示“B”键按下
  133.                                 key=11;
  134.                                 break;
  135.                                 default:               //列线没发生状态改变
  136.                                 key=0;
  137.                                 break;
  138.                         }
  139.                         DDRD=0xF0;           //改变PD端口方向,为下次行线判断做好准备
  140.                         PORTD=0x0F;
  141.                         break;
  142.                 }
  143.                 case 0x07:                   //行线的PD3为低电平
  144.                 {
  145.                         DDRD=0x0F;          //改变端口方向,准备进行列线的状态判断
  146.                         PORTD=0xF0;
  147.                         delay(5);
  148.                         temp1=PIND;           //读取PD端口状态
  149.                         temp1&=PIND;          //判断列线状态
  150.                         switch(temp1)
  151.                         {
  152.                                 case 0x70:            //列线的PD7为低电平,表示“C”键按下
  153.                                 key=12;
  154.                                 break;
  155.                                 case 0xB0:           //列线的PD6为低电平,表示“D”键按下
  156.                                 key=13;
  157.                                 break;
  158.                                 case 0xD0:            //列线的PD5为低电平,表示“E”键按下
  159.                                 key=14;
  160.                                 break;
  161.                                 case 0xE0:            //列线的PD4为低电平,表示“F”键按下
  162.                                 key=15;
  163.                                 break;
  164.                                 default:              //列线没发生状态改变
  165.                                 key=0;
  166.                                 break;
  167.                         }
  168.                         DDRD=0xF0;           //改变PD端口方向,为下次行线判断做好准备
  169.                         PORTD=0x0F;
  170.                         break;
  171.                 }
  172.                 default:                    //行线没发生状态改变
  173.                 key=0;
  174.                 break;
  175.         }
  176.         return(key);                     //返回键值
  177. }
  178. int main(void)
  179. {
  180.         uchar x;
  181.         uchar temp,keynum;
  182.         DDRB=0xFF;
  183.         PORTB=0xFF;
  184.         DDRD=0xF0;
  185.         PORTD=0x0F;
  186.         DDRC=0xFF;
  187.         PORTC=0xFF;
  188.         for(x=0;x<8;x++)            //初始状态显示8个"-"
  189.         {
  190.                 dis_buff[x]=16;
  191.         }
  192.         while (1)
  193.         {
  194.                 temp=PIND;               //判断是否有按键
  195.                 temp&=0x0F;
  196.                 if(temp==0x0F)
  197.                 {
  198.                         key_flag=0;
  199.                 }
  200.                 else
  201.                 {
  202.                         delay(100);              //约10ms延时去抖
  203.                         temp=PIND;               //判断是否有按键
  204.                 temp&=0x0F;}
  205.                 if(temp==0x0F)
  206.                 {
  207.                         key_flag=0;
  208.                 }
  209.                 else
  210.                 {
  211.                         key_flag=1;
  212.                         keynum=ScanKey();        //键值送keynum
  213.                 }
  214.                 while(temp!=0x0F)
  215.                 {
  216.                         temp=PIND;
  217.                         temp&=0x0F;
  218.                 }
  219.                 if(key_flag==1)
  220.                 {
  221.                         dis_buff[0]=dis_buff[1];
  222.                         dis_buff[1]=dis_buff[2];
  223.                         dis_buff[2]=dis_buff[3];
  224.                         dis_buff[3]=dis_buff[4];
  225.                         dis_buff[4]=dis_buff[5];
  226.                         dis_buff[5]=dis_buff[6];
  227.                         dis_buff[6]=dis_buff[7];
  228.                         dis_buff[7]=keynum;
  229.                 }
  230.                 display();
  231.         }
  232. }



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

2404

主题

7001

帖子

68

粉丝
快速回复 在线客服 返回列表 返回顶部