状态机4x4键盘实验程序

上一篇 / 下一篇  2007-10-03 14:19:26 / 天气: 阴雨 / 心情: 平静 / 精华(1) / 置顶(1) / 个人分类:AVR单片机

学习园地

/****************************************************
/****************************************************
名称:4x4键盘测试程序
参数:使用外部晶振(4M)
用法:将SAVR-51板上的PORTD--数码管的段码,PORTA.0连到第一位数码管的位。
      PORTB口接4*4键盘
设计人:kaiser-朱
日期:
/****************************************************
/****************************************************/
#include <mega16.h>
/****键盘编码定义*****/
#define No_key  255
#define K1_1 1
#define K1_2 2
#define K1_3 3
#define K2_1 4
#define K2_2 5
#define K2_3 6
#define K3_1 7
#define K3_2 8
#define K3_3 9
#define K4_1 10
#define K4_2 0
#define K4_3 11
#define Key_mask   0b00000111   
/*****IO口定义*******/
#define key_out PORTB
#define key_pin PINB


flash char tab_data[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f,/*A*/0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};
               /*   0   1     2    3    4    5    6    7    8    9         A    B    C    D    E    F    -  */
char temp;     
char    key_temp;
char key_stime_counter;  // 时间计数单元,
bit key_stime_ok;

void display(void)// 1位LED数码管动态扫描函数
 {
   PORTA = 0xff;
   PORTD = tab_data[temp];
   PORTA =0xfe;   
 }   


char read_keyboard() //状态机4*3矩阵键盘函数
 { 
   static char key_state = 0, key_value, key_line;//定义局部静态变量
   char key_return = No_key,i;
   switch (key_state)
    {
 case 0:
        key_line = 0b00001000;    //初始扫描码
        for (i=1; i<=4; i++)      //将循环扫描4次,直到有按键按下     // 扫描键盘
         { 
           key_out = ~key_line;//送出扫描码 
    key_out = ~key_line;// 必须送2次!!!(注1)
    key_value = Key_mask & key_pin;// 读列电平
    if (key_value == Key_mask)
    key_line <<= 1; // 没有按键,继续扫描
      else
           {
            key_state++; // 有按键,停止扫描
     break;  // 转消抖确认状态
    }
          }
  break;
 case 1:
        if (key_value == (Key_mask & key_pin))// 再次读列电平,
          {
            switch (key_line | key_value)// 与状态0的相同,确认按键
              {// 键盘编码,返回编码值
                 case 0b00001110:
                                 key_return = K1_1;
                                 break;
                 case 0b00001101:
                                 key_return = K1_2;
                                 break;
                        case 0b00001011:
                                 key_return = K1_3;
                                 break;
                        case 0b00010110:
     key_return = K2_1;
     break;
                        case 0b00010101:
     key_return = K2_2;
     break;
                 case 0b00010011:
     key_return = K2_3;
     break;
                        case 0b00100110:
     key_return = K3_1;
     break;
                        case 0b00100101:
     key_return = K3_2;
     break;
                 case 0b00100011:
     key_return = K3_3;
     break;
                        case 0b01000110:
     key_return = K4_1;
     break;
                        case 0b01000101:
     key_return = K4_2;
     break;
                 case 0b01000011:
     key_return = K4_3;
     break;
               }
               key_state++;// 转入等待按键释放状态
             }
         else
              key_state--;// 两次列电平不同返回状态0,(消抖处理)
              break;      
 case 2:         // 等待按键释放状态
        key_out = 0b00000111;// 行线全部输出低电平
        key_out = 0b00000111;// 重复送一次
        if ( (Key_mask & key_pin) == Key_mask)
            key_state=0;// 列线全部为高电平返回状态0
        break;
       }
       return key_return; //返回键值
}
// Timer 0 比较匹配中断服务,2ms定时
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
  display();      // LED扫描显示
  if (++key_stime_counter >=5)
  {
   key_stime_counter = 0;
   key_stime_ok = 1;    // 10ms到
  }
}

void main(void)
{
  PORTD = 0x00;     // 显示控制I/O端口初始化
  DDRD = 0xFF;
  PORTB = 0xFF;
  DDRB = 0xF8  ;
  DDRA=0xff;
  // T/C0 初始化
  TCCR0=0x0B;   // 内部时钟,64分频(4M/64=62.5KHz),CTC模式
  TCNT0=0x00;
  OCR0=0x7C;          // OCR0 = 0x7C(124),(124+1)/62.5=2ms
  TIMSK=0x02;   // 允许T/C0比较匹配中断
  #asm("sei")   // 开放全局中断
  while (1)
  {
   if (key_stime_ok)    
   {
    key_stime_ok = 0;    // 10ms到
    key_temp = read_keyboard();// 调用键盘接口函数读键盘
    if (key_temp != No_key)
    {     // 有按键按下
        temp=key_temp;
    }
   }
 
  };
}


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

我的栏目

日历

« 2008-11-21  
      1
2345678
9101112131415
16171819202122
23242526272829
30      

我的存档

数据统计

  • 访问量: 710
  • 日志数: 5
  • 商品数: 1
  • 建立时间: 2007-10-02
  • 更新时间: 2007-10-03

RSS订阅

Open Toolbar