Chinaunix首页 | 论坛 | 博客
  • 博客访问: 93620
  • 博文数量: 24
  • 博客积分: 1066
  • 博客等级: 少尉
  • 技术积分: 277
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-02 21:07
文章分类
文章存档

2012年(1)

2011年(19)

2010年(4)

我的朋友

分类: BSD

2011-07-11 14:10:07

AVR 矩阵键盘 程序参考
程序特点:
1.有连续按键功能
2.有组合键功能
3.连续按键起始时间和间隔时间自定义
4.可根据需要扩展组合键

使用方法:
将文件"Keypad.h"和"Keypad.c"放入您的工程,将按键需要执行的函数赋值给对应的函数指针
注:需要执行的函数必须为无参数,无返回值
例:您按下A时需要执行以下函数:
void fun(void)
{
    printf("我按下了A");
}
只需执行下列语句
p_Key_A = MenuExit;
并在主循环中调用
KeypadPoll();

以下是两个文件源码
Keypad.h
/******** AVR 4*4矩阵键盘扫描程序 ********
* 版本.........: 3.5
* 作者.........: 陈利栋
* 目标.........: AVR
* 文件名.......: Keypad.h
* 编译器.......: IAR for AVR V5.5
* 创建时间.....: 2010.09.12
* 最后修改.....: 2010.10.09
*****************************************/
#ifndef __KEYPAD_H__
#define __KEYPAD_H__

#include
#include "delay.h"

#define KEYPAD_PORT                   PORTC
#define KEYPAD_DDR                    DDRC
#define KEYPAD_PIN                    PINC

/* 以下3个值根据实际情况调整 */
#define KEY_READY_COUNT               2000          // 检测按键稳定持续的次数

#define KEY_CONTINUE_START_COUNT      40000         // 检测连续按键开始需要的次数

#define KEY_CONTINUE_RUNNING_COUNT    3000          // 连续按键间隔检测次数

#define KEY_NULL                      0xff

inline void NullFunction(void{ }                  // 空函数
#define NULL_FUNC                     NullFunction  // 空函数宏定义
#define NULL_FUNC2       ((void(*)(unsigned char))NULL_FUNC)

// 矩阵键盘函数指针声明(一个按键一个指针)
extern void (*p_Key_1)(void);
extern void (*p_Key_2)(void);
extern void (*p_Key_3)(void);
extern void (*p_Key_4)(void);
extern void (*p_Key_5)(void);
extern void (*p_Key_6)(void);
extern void (*p_Key_7)(void);
extern void (*p_Key_8)(void);
extern void (*p_Key_9)(void);
extern void (*p_Key_0)(void);
extern void (*p_Key_A)(void);
extern void (*p_Key_B)(void);
extern void (*p_Key_C)(void);
extern void (*p_Key_D)(void);
extern void (*p_Key_Xing)(void);  // 星号键
extern void (*p_Key_Jin)(void);   // 井号键
extern void (*p_Key_A_B)(void);   // A+B的组合键
// 任意按键按下或弹起的函数指针声明(参数为按键值的ascii字符)
extern void (*p_Key_Down)(unsigned char c);
extern void (*p_Key_Up)(unsigned char c);

// 连续按键的标记
extern volatile unsigned char key_continue_flag;
// 在主循环中调用此函数
extern void KeypadPoll(void);


#endif /* __KEYPAD_H__ */

Keypad.c
/******** AVR 4*4矩阵键盘扫描程序 ********
* 版本.........: 3.5
* 作者.........: 陈利栋
* 目标.........: AVR
* 文件名.......: Keypad.c
* 编译器.......: IAR for AVR V5.5
* 创建时间.....: 2010.09.12
* 最后修改.....: 2010.10.09
*****************************************/
#include "Keypad.h"

volatile unsigned char key_continue_flag = 0;
static volatile unsigned char _key_last = KEY_NULL;
static volatile unsigned int  _key_count = 0;
static volatile unsigned int  _key_continue_count = 0;

// 矩阵键盘函数指针(一个按键一个指针)
void (*p_Key_1)(void= NULL_FUNC;
void (*p_Key_2)(void= NULL_FUNC;
void (*p_Key_3)(void= NULL_FUNC;
void (*p_Key_4)(void= NULL_FUNC;
void (*p_Key_5)(void= NULL_FUNC;
void (*p_Key_6)(void= NULL_FUNC;
void (*p_Key_7)(void= NULL_FUNC;
void (*p_Key_8)(void= NULL_FUNC;
void (*p_Key_9)(void= NULL_FUNC;
void (*p_Key_0)(void= NULL_FUNC;
void (*p_Key_A)(void= NULL_FUNC;
void (*p_Key_B)(void= NULL_FUNC;
void (*p_Key_C)(void= NULL_FUNC;
void (*p_Key_D)(void= NULL_FUNC;
void (*p_Key_Xing)(void= NULL_FUNC// 星号键
void (*p_Key_Jin)(void= NULL_FUNC;  // 井号键
void (*p_Key_A_B)(void= NULL_FUNC;  // A+B的组合键
// 任意按键按下或弹起的函数指针(参数为按键值的ascii字符)
void (*p_Key_Down)(unsigned char c= NULL_FUNC2;
void (*p_Key_Up)(unsigned char c= NULL_FUNC2;

static unsigned char _hex_to_ascii(unsigned char h)
{
    switch (h)
    {
        case 0xEB : return '0';
        case 0x77 : return '1';
        case 0x7B : return '2';
        case 0x7D : return '3';
        case 0xB7 : return '4';
        case 0xBB : return '5';
        case 0xBD : return '6';
        case 0xD7 : return '7';
        case 0xDB : return '8';
        case 0xDD : return '9';
        case 0x7E : return 'A';
        case 0xBE : return 'B';
        case 0xDE : return 'C';
        case 0xEE : return 'D';
        case 0xE7 : return '*';
        case 0xED : return '#';
        default   : return ' ';
    }
}

// 内部函数
static inline unsigned char _keypad_scan(void)
{
    static unsigned char temp = 0;

    KEYPAD_DDR = 0x0f;
    KEYPAD_PORT = 0xf0;
    _delay_us(5);
    temp = KEYPAD_PIN;

    KEYPAD_DDR = 0xf0;
    KEYPAD_PORT = 0x0f;
    _delay_us(5);
    temp |= KEYPAD_PIN;

    if (temp != _key_last)
    {
        _key_count++;
        if (_key_count >= KEY_READY_COUNT)
        {
            if (temp == KEY_NULL)
            {
                p_Key_Up(_hex_to_ascii(_key_last));
            }
            _key_last = temp;
            _key_count = 0;
            return _key_last;
        }
        key_continue_flag = 0;
        _key_continue_count = 0;
    }
    else
    {
        _key_count = 0;
        if (_key_last != KEY_NULL)
        {
            _key_continue_count++;
            if (key_continue_flag == 0)
            {
                if (_key_continue_count >= KEY_CONTINUE_START_COUNT)
                {
                    key_continue_flag = 1;
                    _key_continue_count = 0;
                    return _key_last;
                }
            }
            else
            {
                if (_key_continue_count >= KEY_CONTINUE_RUNNING_COUNT)
                {
                    _key_continue_count = 0;
                    return _key_last;
                }
            }
        }
    }

    return KEY_NULL;
}

// 在主循环中调用此函数
void KeypadPoll(void)
{
    static unsigned char temp = 0;
    temp = _keypad_scan();
    if (temp == KEY_NULL)
    {
        return ;
    }
    p_Key_Down(_hex_to_ascii(temp));
    switch (temp)
    {
        case KEY_NULLbreak;
        case 0xEBp_Key_0(); break;
        case 0x77p_Key_1(); break;
        case 0x7Bp_Key_2(); break;
        case 0x7Dp_Key_3(); break;
        case 0xB7p_Key_4(); break;
        case 0xBBp_Key_5(); break;
        case 0xBDp_Key_6(); break;
        case 0xD7p_Key_7(); break;
        case 0xDBp_Key_8(); break;
        case 0xDDp_Key_9(); break;
        case 0x7Ep_Key_A(); break;
        case 0xBEp_Key_B(); break;
        case 0xDEp_Key_C(); break;
        case 0xEEp_Key_D(); break;
        case 0xE7p_Key_Xing(); break;  // *
        case 0xEDp_Key_Jin();  break;  // #
        case 0x3Ep_Key_A_B();  break;  // A + B 组合键
        // 此处添加其它组合键
        default  : break;
    }
}
阅读(2043) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~