江科大學長又發布了第二期的編寫技巧!
大家可以看看: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 100u8 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=1Key_Flag[i]|=KEY_HOLD;}else{//HOLD=0Key_Flag[i]&=~KEY_HOLD;}if(CurrState[i]==KEY_PRESSED&&PrevState[i]==KEY_UNPRESSED){//Down=1Key_Flag[i]|=KEY_DOWN;}if(CurrState[i]==KEY_UNPRESSED&&PrevState[i]==KEY_PRESSED){//UP=1Key_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;//2s3¤°′ê±???D?μ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=1Key_Flag[i]|=KEY_LONG;S[i]=4;}}else if(S[i]==2){if(CurrState[i]==KEY_PRESSED){//DOUBLE=1Key_Flag[i]|=KEY_DOUBLE;S[i]=3;}else if(Time>0){//SINGLE=1Key_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=1Key_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];}}
}
``