本帖最后由 babyqym 于 2012-9-19 15:18 编辑
//======================按键头文件================
//title key.h
#ifndef KEY_H
#define KEY_H
/********************************************************/
/* Include File */
/********************************************************/
//#include "ADC.h"
/********************************************************/
/* Macro Define */
/********************************************************/
//define key value
#define KEY_BLANK 0
#define KEY_1 1
#define KEY_2 2
#define KEY_3 3
#define KEY_POWER KEY_1
#define KEY_VOL_DOWN KEY_2
#define KEY_VOL_UP KEY_3
//define key state
#define KEY_RELEASE 0
#define KEY_FIRST_DOWN 1
#define KEY_DOWN 2
#define KEY_FIRST_RPT 3
#define KEY_PRT_DOWN 4
#define KEY_REPEAT 5
#define KEY_LONG_DOWN 6
#define KEY_SHORT_UP 7
#define KEY_LONG_UP 8
/********************************************************/
/* Extern reference variable */
/********************************************************/
extern unsigned char KeyAction;
extern unsigned char KeyState;
extern unsigned char KeyValue;
/********************************************************/
/* Extern reference Function Prototype */
/********************************************************/
extern void InitinalKey(void);
extern void ScanKey(void);
#endif
//=========================按键程序文件==============
/********************************************************/
/* Include File */
/********************************************************/
#include "GPIO.h"
#include "Key.h"
#include "SM39R04G1.h"
/********************************************************/
/* Macro Define */
/********************************************************/
/*K1 K2 K3
0 133 265
66 199 331*/
#define Key1Limit 207
#define Key2Limit 522
#define Key3Limit 830
#define KeyGapCount 5 //155ms=5*31.03ms old 6
#define KeyRPTCount 10 //1000ms=32*32.266ms old 40
#define KeyLongTime 6 //1930ms=1000ms+6*155ms
/********************************************************/
/* Prototype of static function */
/********************************************************/
static unsigned char ReadKey(void);
/********************************************************/
/* RAM Define */
/********************************************************/
static unsigned char LastKey;
static unsigned char keyCount;
static unsigned char LongCount;
unsigned char KeyAction;
unsigned char KeyState;
unsigned char KeyValue;
/********************************************************/
/* Function Define */
/********************************************************/
void InitinalKey(void)
{
SetPortProperty(PORT3,2,Q_BIDIRECT);
SetPortProperty(PORT3,3,Q_BIDIRECT);
P3_2=1;
P3_3=1;
KeyAction = 0;
KeyState = KEY_RELEASE;
KeyValue = KEY_BLANK;
}
/**************************************************************************
* *
**************************************************************************/
static unsigned char ReadKey(void)
{
unsigned char keyID;
keyID=0;
if ((P3&0x08)==0x00)
{
keyID=1;
}
else if((P3&0x04)==0x00)
{
keyID=2;
}
return keyID;
}
/**************************************************************************/
/* */
/**************************************************************************/
void ScanKey(void)
{
unsigned char CurrentKeyValue;
KeyAction = 0;
CurrentKeyValue = ReadKey();
if (CurrentKeyValue != LastKey)
{
LastKey = CurrentKeyValue;
}
else
{
if (CurrentKeyValue != KEY_BLANK)
{
KeyValue = CurrentKeyValue;
switch (KeyState)
{
case KEY_RELEASE:
keyCount = 0;
KeyAction = 1;
KeyState = KEY_FIRST_DOWN;
break;
case KEY_FIRST_DOWN:
KeyAction =0;
KeyState =KEY_DOWN;
keyCount = 1;
break;
case KEY_DOWN:
if (keyCount > KeyRPTCount)
{
KeyAction = 1;
KeyState = KEY_FIRST_RPT;
}
else
{
keyCount++;
}
break;
case KEY_FIRST_RPT:
KeyAction =0;
KeyState =KEY_PRT_DOWN;
keyCount = 0;
LongCount = 1;
break;
case KEY_PRT_DOWN:
if (keyCount > KeyGapCount)
{
KeyAction = 1;
if(LongCount==KeyLongTime)
{
KeyState = KEY_LONG_DOWN;
LongCount++;
}
else
{
KeyState = KEY_REPEAT;
if(LongCount<KeyLongTime)
{
LongCount++;
}
}
}
else
{
keyCount++;
}
break;
case KEY_REPEAT:
KeyAction =0;
KeyState =KEY_PRT_DOWN;
keyCount = 1;
break;
case KEY_LONG_DOWN:
KeyAction =0;
KeyState =KEY_PRT_DOWN;
keyCount = 0;
break;
}
}
else
{
switch (KeyState)
{
case KEY_RELEASE:
break;
case KEY_FIRST_DOWN:
case KEY_DOWN:
KeyAction =1;
KeyState =KEY_SHORT_UP;
break;
case KEY_FIRST_RPT:
case KEY_PRT_DOWN:
case KEY_REPEAT:
case KEY_LONG_DOWN:
KeyAction =1;
KeyState =KEY_LONG_UP;
break;
case KEY_SHORT_UP:
case KEY_LONG_UP:
KeyAction =0;
KeyState =KEY_RELEASE ;
break;
}
}
}
}
//===========================主程序中的调用=======
#include "SM39R04G1.h"
#include "GPIO.h"
#include "Time0.h"
#include "key.h"
#include "AS44CE373.h"
void main(void)
{
CKCON=0;//set 1T mode
EA=0;
SetPort(PORT3,PUSH_PULL);
P3_2=0;
InitinalT0();
InitinalKey();
AS44CE373Init();
EA=1;
for(;;)
{
if(TFlag==1)
{
ScanKey();
if(KeyAction)
{
switch(KeyState)
{
case KEY_FIRST_DOWN:
if(KeyValue==1)
{
SetChannelDirect(1);
}
else if(KeyValue==2)
{
SetChannelDirect(2);
}
break;
case KEY_FIRST_RPT:
if(KeyValue==1)
{
}
else if(KeyValue==2)
{
}
break;
case KEY_REPEAT:
if(KeyValue==1)
{
SetChannelDirect(1);
}
else if(KeyValue==2)
{
SetChannelDirect(2);
}
break;
case KEY_SHORT_UP:
if(KeyValue==1)
{
}
else if(KeyValue==2)
{
}
break;
}
KeyAction=0;
}
P3_7=!P3_7;
//P3_3=!P3_2;
// P3_4=!P3_3;
// P3_5=!P3_4;
TFlag=0;
}
}
}
//===========================设计思路=============
定时器T0每隔32ms中断一次,设置全局标志TFlag,主程序中,判断TFlag,如果为真则进入执行,执行完成后设置TFlag=0, 完成一次32ms周期执行过程,等待下一个32ms执行周期。
ScanKey();在32ms周期内执行一次,来看看这个函数:
首先设置KeyAction=0,设置按键为没有动作态,这个变量是全局的,在后面按键任务中用来判断按键是否有动作,说说按键动作,在这里按键有9种状态,头文件中有定义:
#define KEY_RELEASE 0 //按键处于释放的状态
#define KEY_FIRST_DOWN 1//按键第一次有效按下
#define KEY_DOWN 2// 按键在first down 和first rpt 之间的n次按下
#define KEY_FIRST_RPT 3//按键第一次长按下
#define KEY_PRT_DOWN 4
#define KEY_REPEAT 5//按键长按下后的重复
#define KEY_LONG_DOWN 6//超长按下态
#define KEY_SHORT_UP 7//第一次长按下前按键释放
#define KEY_LONG_UP 8//第一次长按下后的释放
这里做了个注视,希望可以看懂,
这些状态我们不一定全部用到,KEY_DOWN,KEY_PRT_DOWN只是过渡态。
KeyAction只在KEY_FIRST_DOWN,KEY_FIRST_RPT ,KEY_REPEAT,KEY_LONG_DOWN,KEY_SHORT_UP,KEY_LONG_UP的时候才被置位。
废话有点多,看看下一行:
CurrentKeyValue = ReadKey();
这里只是读取按键的值,即使没有按键按下也要读取的,只不过这里读取到的是空值,
需要说明的ReadKey()只需要读取按键的键值就好了,其他的不要做,这里可以是读取
矩阵扫描的键值,也可以是AD键盘的键值,这里程序中简单的读取了两个段口的电平。
再看看下面的判断:这里是精华了。
判断CurrentKeyValue是否和上次的按键值LastKey相同,LastKey是全局变量,
如果按键处于释放状态,LastKey一定是空值,连续两次读取的值是相同的,则会进入到else后的程序,
如果不同,则说明有按键按下或是有抖动,这里主要是通过连续两次读取按键值来确定按键是否处于稳定状态(按下或松开,
而不是抖动态,由于前面的是32ms的周期,所以一次有效的按键至少要2个周期64ms,如果诸位嫌长可以修改前面的T0定时器)
下面看看else中的内容,这里有连个部分一个是键值不等于KEY_BLANK,一个是键值等于KEY_BLANK,先说不等于KEY_BLANK,
由于CurrentKeyValue是局部变量,我们得把键值保存到全局变量KeyValue中,后面按键任务中使用它,后面的Switch语句不祥说,
按键的各种状态在这里头转换和设置。键值等于KEY_BLANK得部分也是一样,这是按键松开的动作,直到释放。
按键执行的任务在主程序中ScanKey()之后
这部分可以写成函数,实际我没有这样写,由于程序简单,就直接写在主程序中了:
if(KeyAction)
{
switch(KeyState)
{
case KEY_FIRST_DOWN:
if(KeyValue==1)
{
SetChannelDirect(1);
}
else if(KeyValue==2)
{
SetChannelDirect(2);
}
break;
case KEY_FIRST_RPT:
if(KeyValue==1)
{
}
else if(KeyValue==2)
{
}
break;
case KEY_REPEAT:
if(KeyValue==1)
{
SetChannelDirect(1);
}
else if(KeyValue==2)
{
SetChannelDirect(2);
}
break;
case KEY_SHORT_UP:
if(KeyValue==1)
{
}
else if(KeyValue==2)
{
}
break;
}
KeyAction=0;
}
这个就不需要详细说明了,判断是否有动作,有动作则对不同动作状态做不同处理,在不同的动作状态下对不同的按键调用不同的按键程序。
需要注意的是之后一定要把KeyAction置0。另外需要在程序初始化中调用InitinalKey()。
写的不尽如人意,望泼水。
附件中是AD按键的扫描。
Key.rar
(1.14 KB)
|