|
這個系統(tǒng)可以近似的看成是按鍵并發(fā)操作,單擊、雙擊等一系列的動作都已經(jīng)定義過。以下是頭文件:
#define BaseTime 10 //時基,由單片機時鐘中斷精準產(chǎn)生
#define number_init 0xfffffffd //對任何時間變量需要初始化的地方預設的初始化值
typedef unsigned char uchar ;
typedef unsigned int uint ;
typedef unsigned long ulong ;
typedef unsigned long utime ;
enum ButtonModel{noneClick=0,singalClick,doubleClick,repeatClick,longPress};
enum ButtonStaus{nonePress=1,pressDown,pressUp,pressDownHold};
struct button
{
uchar outPutEn:1; //發(fā)送數(shù)據(jù)使能
uchar lastButton:1; //緩存按鍵上次變動后的狀態(tài)
uchar init_leavel:1; //設置默認按鍵電平
uchar longPressFlag:1; //長按釋放標志 默認0,一旦開始長按則置1
uchar Gpio_level :3; //讀取IO口電平
uchar applyUseOpenAPI:1; //在關(guān)機狀態(tài)下,若本按鍵按下啟動了系統(tǒng),則需要申請全局變量標明,禁止其他按鍵關(guān)閉被本按鍵打開的系統(tǒng)(自己打開自己負責關(guān)閉)
uchar ticks; //按鍵按下次數(shù)
enum ButtonStaus lastButtonStaus; //緩存按鍵上個循環(huán)的狀態(tài)
enum ButtonStaus thisButtonStaus; //緩存按鍵本循環(huán)的狀態(tài)
enum ButtonModel lastButtonModel; //緩存按鍵上個循環(huán)所處的模式
enum ButtonModel thisButtonModel; //緩存按鍵本循環(huán)應該所處的模式
uint changeModelTime; //10ms基準 多擊時間定義
uint pressLongTime; //10ms基準 長按時間定義
utime lastPressDownMoment; //上次按鍵按下所處的時刻
utime thisPressDownMoment; //本次按鍵按下所處的時刻
uint tempTime; //緩存按鍵兩次按下之間的時長
utime buttonConfir; //按鍵防抖時長
utime getTimer; //獲取時鐘精準時刻,用于設定按鍵掃描周期
utime acquisitionMoment; //獲取時鐘精準時刻,用于記錄相同按鍵狀態(tài)持續(xù)時長
uchar (*read_gpio)(void); //獲取按鍵狀態(tài)方法
};
void Button_init(struct button *Key,uchar(*get_leavel)(),bit init_button_leavel,uint LongPressTimes,uint changeModelTime); //按鍵初始化
void Scan_key(struct button *Key,utime timer ,uint enOutTime ,uint noiseProofTime); //按鍵掃描函數(shù)
以下是DEMO:
#include"button.h"
struct button button1,button2;
uchar keyCounter=0;
uint Pwm=0;
utime COLCK=0;
inline uchar Get_gpio_level1(void)//獲取開關(guān)的電平,特別注意:如果一個IO口下有三四十個按鈕,用ADC掃描不同的電壓值來判斷是哪個按鈕動作時,要注意程序嵌套層數(shù),層數(shù)太多會有棧溢出的問題,暫時無解
{
return P10; //P10是單片機接開關(guān)的IO口
}
inline uchar Get_gpio_level2(void)
{
return P11; //P11是單片機接開關(guān)的IO口
}
uchar Pwm_excute(uchar pwmDuty); //pwm示例程序,不填充
void Get_button_model(struct button* ); //對掃描到的單擊,雙擊,長按動作響應
main()
{
Button_init(&button1,Get_gpio_level1,1,300,100);// 默認開關(guān)不動作時是高電平,定義長按時長為300個10ms,定義多擊時長為100個10ms
Button_init(&button2,Get_gpio_level2,1,300,100);
/*記得開COLCK所在的中斷!這個時間中斷程序就不填充了*/
while(1)
{
Scan_key(&button1,COLCK,50,20); //定義50ms 掃描一次,定義按鍵防抖時間20ms
Scan_key(&button2,COLCK,50,20);
Get_button_model(&button1); //對按鍵動作響應
Get_button_model(&button2);
}
}
void Get_button_model(struct button* Key )
/*注意啦!多按鍵會存在資源競爭的風險,比如按鍵1打開了某個操作只能由按鍵1關(guān)閉,
如果不仔細設計會存在按鍵2執(zhí)行某個動作時關(guān)閉掉按鍵1打開的操作,遇到這個問題記得applyUseOpenAPI這個玩意來申請權(quán)限,然后用全局變量標識這個操作已經(jīng)被占用,
目前在本DEMO例程中沒有用到這么復雜的設計
*/
{
if(Key->outPutEn)
{
switch(Key->thisButtonModel)
{
switch noneClick:
{
/*
最精華的部分,在按鍵無動作的時候該處理那些數(shù)據(jù),
*/
break;
}
switch singalClick:
{
Pwm++;
if(Pwm>255)
Pwm=255;
Pwm_excute(Pwm); //這個函數(shù)沒有填充,每個單片機的PWM定義不一樣,甚至不是PWM的動作,單擊執(zhí)行什么動作,自己發(fā)揮
break;
}
switch doubleClick:
{
/*
*/
break;
}
switch repeatClick:
{
/*
*/
break;
}
switch longPress:
{
/*
*/
break;
}
}
Key->outPutEn=0; //單片機運行的速度太快,但是按鍵掃描又設置的固定多長時間掃描一次,為了解決矛盾,才有的這么個參數(shù)
}
}
EXN interrupt N //定時器中斷
{
/*
*/
COLCK++; //每10ms加1
}
PS:公司的項目非常復雜,用的是多按鍵并發(fā),等過段時間我整一張原理圖上來。當然,公司項目的源程序有5千行,處于保密需求是不可能上傳的。
|
-
-
按鍵驅(qū)動.zip
2019-12-17 16:41 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
5.07 KB, 下載次數(shù): 34, 下載積分: 黑幣 -5
程序
評分
-
查看全部評分
|