江科大学长又发布了第二期的编写技巧!
大家可以看看:https://space.bilibili.com/383400717
最后面给了一个未完成的任务:
这里我已经把这个问题给解决了!
总代码放在资源里面,key.c放在文章最后面!同时感兴趣的同学可以看看我的Linux驱动讲解!
1、保存上一次的标志位:
2、清零目标标志位
计划在同一个按键事件后的标志位发生变化时,判断上一个标志位和目前标志位不一样时进行清理:
为了简单理解,我们就以同一个按键,两位2进制标志位来讲。
假设上一个的标志位是10;如果按照之前的代码,切换模式的时候,那目前标志位就是11,因为假设并没有进行检查操作就想清零。解决标志位积累的问题!
所以进行:
if(Last_Key_Flag[i]!=Key_Flag[i])
{
Key_Flag[i]&=~Last_Key_Flag[i];
}
Last_Key_Flag[i]=Key_Flag[i];
3、同一个按键空闲的时候也清零标志位:
这样就行了!不过这里有一个问题,就是按键松开和按压时间交替太快了,程序会认为是清零标志位,而不是双击,太慢了,就会认为是单击。但是如果不这样设置,就会保留最后一次的标志位,目前我没有想到好的方法!就留给后来者了!
4、Key.c代码:
#include "stm32f10x.h" // Device header
#include "Key.h"
#define KEY_PRESSED 1
#define KEY_UNPRESSED 0
#define KEY_TIME_DOUBLE 200
#define KEY_TIME_LONG 2000
#define KEY_TIME_REPEAT 100
u8 Key_Flag[KEY_COUNT];
void Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //¶ÁÈ¡°´¼ü
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //¶ÁÈ¡°´¼ü
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
u8 Key_Getstate(u8 n)
{
if(n==KEY_1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)
{
return KEY_PRESSED ;
}
}
else if(n==KEY_2)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0)
{
return KEY_PRESSED ;
}
}
else if(n==KEY_3)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==1)
{
return KEY_PRESSED ;
}
}
else if(n==KEY_4)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==1)
{
return KEY_PRESSED ;
}
}
return KEY_UNPRESSED;
}
u8 Key_Check(u8 n,u8 Flag)
{
if(Key_Flag[n]&Flag)
{
if(Flag!=KEY_HOLD)
{
Key_Flag[n]&=~Flag;
}
return 1;
}
return 0;
}
void Key_Tick(void)
{
static u8 Count,i;
static u8 CurrState[KEY_COUNT],PrevState[KEY_COUNT];
static u8 S[KEY_COUNT];
static u16 Time[KEY_COUNT];
static u8 Last_Key_Flag[KEY_COUNT];
for(i=0;i<KEY_COUNT;i++)
{
if(Time[i]>0)
{
Time[i]--;
}
}
Count++;
if(Count>=20)
{
Count=0;
for(i=0;i<KEY_COUNT;i++)
{
PrevState[i]=CurrState[i];
CurrState[i]=Key_Getstate(i);
if(CurrState[i]==KEY_PRESSED)
{
//HOLD=1
Key_Flag[i]|=KEY_HOLD;
}else{
//HOLD=0
Key_Flag[i]&=~KEY_HOLD;
}
if(CurrState[i]==KEY_PRESSED&&PrevState[i]==KEY_UNPRESSED)
{
//Down=1
Key_Flag[i]|=KEY_DOWN;
}
if(CurrState[i]==KEY_UNPRESSED&&PrevState[i]==KEY_PRESSED)
{
//UP=1
Key_Flag[i]|=KEY_UP;
}
if(PrevState[i]==KEY_UNPRESSED&&CurrState[i]==KEY_UNPRESSED)
{
Key_Flag[i]&=0x00;
}
if(S[i]==0)
{
if(CurrState[i]==KEY_PRESSED)
{
Time[i]=KEY_TIME_LONG;//2s³¤°´Ê±¼äãÐÖµ
S[i]=1;
}
}
else if(S[i]==1)
{
if(CurrState[i]==KEY_UNPRESSED)
{
Time[i]=KEY_TIME_DOUBLE;
S[i]=2;
}
else if(Time[i]==0)
{
Time[i]=KEY_TIME_REPEAT;
//LONG=1
Key_Flag[i]|=KEY_LONG;
S[i]=4;
}
}
else if(S[i]==2)
{
if(CurrState[i]==KEY_PRESSED)
{
//DOUBLE=1
Key_Flag[i]|=KEY_DOUBLE;
S[i]=3;
}
else if(Time>0)
{
//SINGLE=1
Key_Flag[i]|=KEY_SINGLE;
S[i]=0;
}
}
else if(S[i]==3)
{
if(CurrState[i]==KEY_UNPRESSED)
{
S[i]=0;
}
}
else if(S[i]==4)
{
if(CurrState[i]==KEY_UNPRESSED)
{
S[i]=0;
}
else if(Time[i]==0)
{
Time[i]=KEY_TIME_REPEAT;
//REPEAT=1
Key_Flag[i]|=KEY_REPEAT;
S[i]=4;
}
}
if(Last_Key_Flag[i]!=Key_Flag[i])
{
Key_Flag[i]&=~Last_Key_Flag[i];
}
Last_Key_Flag[i]=Key_Flag[i];
}
}
}
``