#define BaseTime 10 //时间基准10 ms ,如果设计的时基是5ms 则前面的10就用该变成5
#define number_init 0xfffffffd // 初始化相关的utime(unsigned long)变量(如果是unsigned int 就应该是0xfffd),采用这个值的好处是,即使发生时钟计数器溢出,也不影响其他的程序
typedef unsigned long utime; //这个类型是为了方便移植专门给时间相关变量使用
typedef unsigned long ulong;
typedef unsigned int uint;
typedef unsigned char uchar;
enum ButtonModel{noneClick=0,singalClick,doubleClick,repeatClick,longPress}; //doubleClick目前未定义完整动作 pressDownHold,按下保持
enum ButtonStaus{nonePress=1,pressDown,pressUp,pressDownHold}; /
struct button
{
uchar outPutEn:1; //发送数据使能
uchar lastButton:1; //按键上次变动后的状态 默认 1
uchar init_leavel:1; //设置默认按键电平
uchar longPressFlag:1; //长按释放标志 默认0,一旦开始长按则置1
uchar Gpio_level :3;
uchar applyUseOpenMaxPwm:1; //在关机状态下,若本按键按下启动了系统,则需要申请全局变量标明,禁止其他按键关闭被本按键打开的系统(自己打开自己负责关闭)
uchar ticks; //按键按下次数
enum ButtonStaus lastButtonStaus; //按键上个循环的状态
enum ButtonStaus thisButtonStaus; //按键本循环的状态
enum ButtonModel lastButtonModel; //按键上个循环所处的模式
enum ButtonModel thisButtonModel; //按键本循环应该所处的模式
uint changeModelTime; //10ms基准 //长按时间定义
uint pressLongTime; //10ms基准 //多击时间定义
utime lastPressDownMoment; //上次按键按下所处的时刻
utime thisPressDownMoment; //本次按键按下所处的时刻
uint tempTime; //缓存按键两次按下之间的时长
utime buttonConfir; //按键防抖时长
utime getTimer; //获取时钟精准时刻,用于设定按键扫描周期
utime acquisitionMoment; //获取时钟精准时刻,用于记录相同按键状态持续时长
uchar (*read_gpio)(void); //获取按键状态方法
};
/*================================
outPutEn 是为后面接收按键是单击、多击长按函数准备的参数。比如按键扫描程序10ms运行一次,输出的是单击,如果没有outPutEn这个参数,后面的接收程序会在10ms内一直都接收的是单击指令,这样就会一直执行单击需要进行的操作,本来单击一次档位变化1,结果现在档位变化了n
applyUseOpenMaxPwm 是为多按键且按键操作有优先权做准备,,有优先权的操作不会被其他按键操作打断
===============================*/
struct button button1,button2,button3;
void Scan_key(struct button *Key,utime timer ,uint enOutTime ,uint noiseProofTime)
{
enOutTime/=BaseTime;
noiseProofTime/=BaseTime;
if(number_init==Key->getTimer) //如果是第一次运行,则更新时间
{
Key->getTimer=timer;
}
else
{
if(timer-Key->getTimer>=enOutTime) //如果时间足够“定义的循环时间” ,则更新时间并允许运行
{
Key->getTimer=timer;
Key->Gpio_level=Key->read_gpio();
if(Key->Gpio_level>1);
else
{
if(Key->lastButton^Key->Gpio_level)//按键有电平变化模块处理开始----------------------------------------------------------------------------//
{
if(number_init==Key->buttonConfir)
Key->buttonConfir=timer;
if(timer-Key->buttonConfir>=noiseProofTime)//按键防抖,必须再确认状态
{
Key->lastButton=Key->Gpio_level;
Key->acquisitionMoment=number_init;
Key->buttonConfir=number_init; //二次确认标志重置
if(Key->init_leavel^Key->Gpio_level)//本次按键状态改变后与定义的电平不一致模块处理开始
{
switch(Key->lastButtonStaus)
{
case nonePress: //上个循环是定义的初始电平
case pressUp:
{
if(number_init==Key->lastPressDownMoment)//是第一次记录按键按下时刻
{
Key->thisPressDownMoment=Key->lastPressDownMoment=timer;
}
else //不第一次记录
{
Key->thisPressDownMoment=timer;
Key->tempTime+=Key->thisPressDownMoment-Key->lastPressDownMoment; //获取两次按键按下之间的时间间隔
Key->lastPressDownMoment=Key->thisPressDownMoment; //更新
}
Key->ticks++;
//不在此处增加pressLongTime判断的原因是,buftime0记录的是两次按键按下之间的时长,在两次按下之间必有弹起,一旦弹起,pressLongTime 就置零
switch(Key->ticks)
{
case 1:
{
if(Key->tempTime>=Key->changeModelTime)//ticks未初始化。
{
Key->ticks=0;
Key->tempTime=0;
}
Key->thisButtonModel=singalClick;
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』