很少发贡献类的东东,这是自己写了几年的一个按键通用驱动,好久没有改动了,目前可以满足应用;
这个驱动模块可以提供按键的单次,连续,抬起,以及按下的有效时间,只是处理按键代码,如果用单个字节,可以表示8个可以组合的按键或255个没有组合的按键,不过由于我用的多数按键在4个左右,没有对255的键码做优化,好了上代码:
#ifndef _KEY_H
#define _KEY_H
#include "Typedef.h"
#define K1 0x01
#define K2 0x02
#define K3 0x04
#define K4 0x08
#define K5 0x10
#define K6 0x20
#define K7 0x40
#define K8 0x80
#define K_TIM(T) (T/5)
#define K_ONE_TIM (K_TIM(24))
#define K_CON_TIM (K_TIM(700))
#define K_MAX_TIM (K_TIM(10000))
typedef struct
{
u8 Key; // 按键状态
u16 Tim; // 按键时间
u8 One; // 单次有效按键,只用一次
u8 Up; // 按键放开,只用一次
u8 Con; // 连续有效按键,
}KeyType;
extern KeyType Key;
//////////////////////
void Key_Init(void);
u8 GetKeyPin(void); // 按键引脚
void KeyDrv(void); // 驱动
////////////////////////
KeyType GetKey(void);
#endif
#include "io.h"
#include "stdlib.h"
#include "key.h"
static KeyType KeyVol;
KeyType Key;
//////////////////////////////////////
// Key IO 操作
//////////////////////////////////////
void Key_Init(void)
{
IO_Key_Init( );
}
u8 GetKeyPin(void)
//按键引脚
{
return IO_GetKeyPin( );
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
KeyType GetKey(void)
{
static KeyType _key;
// 禁用中断,也可以用标志位实现
// disable_interrupt( );
_key = KeyVol;
KeyVol.One = 0;
KeyVol.Up = 0;
// enableInterrupts( ); //开中断
return _key;
}
void KeyDrv(void)
//驱动
{
static u8 Tmp_u8;
Tmp_u8 = GetKeyPin();
//没有按键 调用频率,最高到最低排列,减少CPU占用时间
if(Tmp_u8 == 0)
{
//按键放开
if(KeyVol.Key != 0) KeyVol.Up = KeyVol.Key;
KeyVol.Con = 0; KeyVol.Tim = 0;KeyVol.Key = 0;
return;
}
//按键没变
if(Tmp_u8 == KeyVol.Key)
{
//最大按键有效时间
if(KeyVol.Tim < K_MAX_TIM) KeyVol.Tim++;
//按键连按有效
if(KeyVol.Tim > K_CON_TIM) {KeyVol.Con = Tmp_u8;return;}
//按键首次有效
if(KeyVol.Tim == K_ONE_TIM) {KeyVol.One = Tmp_u8;}
return;
}
//按键改变
{KeyVol.Key = Tmp_u8; KeyVol.Tim = 0; return;}
}
修改以下两个函数,对应硬件
void Key_Init(void)
u8 GetKeyPin(void) //按键引脚
void KeyDrv(void) 这个是周期调用的,一般我是和LED动态显示一起处理,调好.H文件的时间定义就好了;
KeyType GetKey(void) 用户调用,返回按键值
没有测试的一个例子:
main()
{
int cont;
Timer_Inti(); //200HZ
Key_Init();
while(1)
{
Key = GwtKey();
switch(Key.One) 单次有效,如果怕与连续有冲突可以用Key.up,就是按键放开
{
case: break;.....
}
switch(Key.One | Key.Con) 单次和连续有效,表现为按下K1后数值加1,之后大约800MS左右就连续加1,速度是主循环的时间,常用100MS处理一次就是10HZ
{
case K1:
Cont ++;
break;.....
}
if(Key.Tim > TIM(2) && (Key.Con == K2) ){长按2秒处理}
print(cont);
wait(100);
}
}
|