AVR 矩阵键盘程序源代码V3.5(有连续按键功能,有组合键功能)

发布者:ByteChaser最新更新时间:2016-10-08 来源: eefocus关键字: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_NULL: break;
        case 0xEB: p_Key_0(); break;
        case 0x77: p_Key_1(); break;
        case 0x7B: p_Key_2(); break;
        case 0x7D: p_Key_3(); break;
        case 0xB7: p_Key_4(); break;
        case 0xBB: p_Key_5(); break;
        case 0xBD: p_Key_6(); break;
        case 0xD7: p_Key_7(); break;
        case 0xDB: p_Key_8(); break;
        case 0xDD: p_Key_9(); break;
        case 0x7E: p_Key_A(); break;
        case 0xBE: p_Key_B(); break;
        case 0xDE: p_Key_C(); break;
        case 0xEE: p_Key_D(); break;
        case 0xE7: p_Key_Xing(); break;  // *
        case 0xED: p_Key_Jin();  break;  // #
        case 0x3E: p_Key_A_B();  break;  // A + B 组合键
        // 此处添加其它组合键
        default  : break;
    }
}

关键字:AVR  矩阵键盘  连续按键  组合键 引用地址:AVR 矩阵键盘程序源代码V3.5(有连续按键功能,有组合键功能)

上一篇:AVR 串口收发 使用循环链表实现的程序源代码
下一篇:AVR单片机使用JTAG口作为普通I/O口方法

推荐阅读最新更新时间:2024-03-16 15:14

基于AVR单片机的数控直流稳压电源的设计
   从20世纪90年代末起,随着对系统更高效率和更低功耗的需求,电信与数据通讯设备的技术更新推动电源行业中直流/直流电源转换器向更高灵活性和智能化方向发展。本文设计的直流稳压电源主要由单片机系统、键盘、数码管显示器、指示灯及报警电路、检测电路、D/A转换电路、直流稳压电路等部分组成。其中数控电源采用按键盘,可对输出电压及报警阈值以快慢两种方式进行设置,输出由单片机通过D/A控制驱动模块输出一个稳定电压。同时稳压方法采用单片机控制, 单片机通过A/D采样输出电压,与设定值进行比较,若有偏差则调整输出,越限则输出报警信号并截流。工作过程中,稳压电源的工作状态(输出电压、电流等各种工作状态)均由单片机输出驱动LCD显示,由键盘控制进行
[电源管理]
基于<font color='red'>AVR</font>单片机的数控直流稳压电源的设计
AVR CTC模式波形输出实验
注:频率为488HZ 既 64分频 8us计数一次 256次即2048ns ==2.048ms 所以频率488HZ CTC模式 比较匹配我设置为置位 当定时器值==OCR0 输出口为高电平,然后定时器自动清零重新计数开始如此反复。 输出电压为占空比值。一下是源码: #include iom16.h #include intrinsics.h #define uchar unsigned char #define uint unsigned int __flash uchar seg ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //段码 0x7f,0x6f}; __f
[单片机]
基于AVR单片机对热敏电阻的温度测量
1 负温热敏电阻 PSB型负温热敏电阻由Co,Mn,Ni等过渡金属元素的氧化物组成,经高温烧成半陶瓷,利用半导体毫微米的精密加工工艺,采用玻璃管封装,耐温性好,可靠性高,反应速度快、灵敏度高。他采用轴向型结构,便于安装,能承受更高温度,且玻璃封装耐高低温(-50~350℃)。PT-25E2热敏电阻温度阻值变化曲线图如图1所示。 2 AVR单片机测温原理 温度测量电路如图2所示,标准电阻Rp,热敏电阻Rt,电容C1与AVR单片机三个引脚相连。其中PC0,PC1为一般普通IO引脚,CP1为捕获触发输入引脚,可以设定上升沿触发捕获中断。 Rp为100 kΩ的精密电阻;Rt为100 kΩ精度为1%的热敏电阻;C1为0.1μF的瓷片电
[单片机]
基于<font color='red'>AVR</font>单片机对热敏电阻的温度测量
Atmel 90系列AVR单片机烧录器
AVRPRO烧录器,是针对ATMEL公司的90系列AVR精简指令单片机设计的专用烧录工具该产品只有软件部分,无需硬件支持,仅仅只需4根线,将计算机并口和用户板相连,这都是因为采用了ISP串行编程。软件支持擦、写、校验、写保护位以及批处理。使用极其方便。 该产品的最大优点有: 1.使用串行编程,达到了在线编程,节省了购买万用编程器和适配器的费用(万用编程器需2千元左右,适配器需3、4百元,并各个芯片和封装需不同适配器)。用户板也无需在焊插座(带来可靠性下降),而且为软件升级带来了极大的便利。 2.使用方便,无需硬件,给现场调试带来了极大的便利,不用再带笨重的编程器,而且为AVR单片机的使用上带来了方便。 3.价格实在太便
[单片机]
AVR单片机ATmega8工业总线项目的通信处理以及实现
这两天带博主的工程师给了一个小任务给我,使用7个小器件进行半双工的工业485总线通信,使用公司内部标准帧格式,采用主动上传方式每隔一定的定量时间进行数据上传。当然,实现一个器件的数据上传是十分简单的,但是使用大于两个器件进行485工业数据传输的时候就必须要考虑数据碰撞的问题了,因为由于485半双工的特性,同一时间数据只能上传或者下载,但是当多个数据进行数据通信的时候就要小心数据的交叉碰撞。 项目要求,在符合帧格式的前提下使用6台工作器件进行数据主动上传,因为前期设定每台设备的主动上传时间为2min,所以不可避免的遇到一个问题,就是如何进行数据的总线判“忙”检测,并且在其他的数据帧发送完毕后进行数据的发送? 经过博主的资料的查询和带
[单片机]
AVR单片机串口红外线传输试验程序
为了验证串口红外传输速度,我搭建了这个小系统。 问题从红外线接收头开始,我使用现成的红外遥控接收头,这就省去了搭建放大整形等等麻烦,但限制也就此产生,后述。红外头内部有40KHZ的选通,所以数字信号必须搭载在40KHZ上。 用74LS00作40KHZ方波发生器,使用如图阻容,产生的方波大致在需求范围。 先想用40KHZ晶振,拆了两个遥控器,445KHZ,不能用,所以还是阻容法,这个50000P是我反复调整的结果。 选用74LS00主要看上它有与门,我们用10脚、9脚入,8脚出这个与非门,把数字信号和载波信号“与”在一起。 遥控接收的要求是,无信号就无载波,串口输出等待状态为高电平,所以用与非门反向一下,13、12脚入,11脚出即是
[单片机]
<font color='red'>AVR</font>单片机串口红外线传输试验程序
第十六节:矩阵键盘的组合按键触发
开场白: 上一节讲了矩阵键盘单个触发的压缩代码编程。这节讲矩阵键盘的组合按键触发。要教会大家三个知识点: 第一点:如何把矩阵键盘翻译成独立按盘的处理方式。然后按独立按键的方式来实现组合按键的功能。 第二点:要提醒大家在设计矩阵键盘时,很容易犯的一个错误。任意两个组合按键不能处于同一行,否则触发性能大打折扣。在做产品的时候,硬件电路设计中,除了四路行输入的要加上拉电阻,四路列输出也应该串入一个470欧左右的限流电阻,否则当同一行的两个按键同时按下时,很容易烧坏单片机IO口。为什么?大家仔细想想原因。因为如果没有限流电阻,同一行的两个按键同时按下时,在某一瞬间,输出的两路高低电平将会直接短接在一起,引起短路。在朱兆祺的学习板中,S1至S
[单片机]
Atmel推出基于AVR32内核的32位数字信号控制器
Atmel推出AP7000系列32位数字信号控制器(DSC),这是首个基于该公司二月份推出的大流量AVR32内核。 AVR32内核在性能和代码密度等方面一直超过32位内核,并可以执行C/C++算法。AP7000是首个集成了所有多媒体系统所需功能的单芯片处理器,适合手机、数码相机、PDA、汽车信息系统、STB和家庭娱乐系统及网络交换机/路由器和打印机。该DSC包括向量化乘法协处理器、32K字节片上SRAM、16K字节指令和16K字节数据缓存、存储器管理单元、用于高速外设的DMA及可在外设和存储器间传输数据的外设DMA控制器。 它的外设包括16位立体声DAC、2048 x 2048像素TFT/STN LCD控制器、具有片上收发器(
[新品]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved