typedef enum
{
KEY_LEVEL_DOWN, // 假設(shè)低電平為按下
KEY_LEVEL_UP,
}KeyLevelTypedef;
KeyLevelTypedef get_key_level()
{
return (KeyLevelTypedef)HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
}
// V0.1
void key_scan()
{ // 歡迎關(guān)注:魚鷹談單片機(jī)
if(get_key_level() == KEY_LEVEL_DOWN)
{
HAL_Delay(20); // 假設(shè)抖動時間 20 ms
if(get_key_level() == KEY_LEVEL_DOWN)
{
key_flag = 1;// 按鍵按下標(biāo)志位
}
}
}
typedef enum
{
KEY_STATE_IDLE, // 按鍵空閑
KEY_STATE_DOWN, // 按鍵按下
KEY_STATE_FINISH, // 按鍵處理完成(由應(yīng)用程序設(shè)置)
}KeyStateTypedef;
KeyStateTypedef key_state;
KeyLevelTypedef key_last_level; // 上次電平狀態(tài)
// V1.0
// 函數(shù)調(diào)用周期 20 ms(如何實(shí)現(xiàn)應(yīng)該不需要再說明了吧)
void key_scan()
{ // 歡迎關(guān)注:魚鷹談單片機(jī)
KeyLevelTypedef temp; // 可不可以不使用這個中間變量?
temp = get_key_level();
if(temp != key_last_level){
key_last_level = temp;
return;
}
// 當(dāng)運(yùn)行到這里,說明電平已經(jīng)穩(wěn)定下來了
if(temp == KEY_LEVEL_DOWN){
if(key_state == KEY_STATE_IDLE){
// 確保曾經(jīng)釋放過按鍵,這樣可以保證在按下時不會不停設(shè)置該標(biāo)志位
key_state = KEY_STATE_DOWN;// 按鍵按下標(biāo)志位
}
}
else{
if(key_state == KEY_STATE_FINISH){ // 防止多線程情況下同時修改
key_state = KEY_STATE_IDLE; // 釋放按鍵
}
}
}
typedef enum{LEVEL_LOW, //LEVEL_HIGH,}LevelTypedef;typedef struct{uint32_t last_time; // 上次時間????LevelTypedef?last_level;?//?上次電平狀態(tài)}FilterParaTypedef;// V2.0// para 濾波變量,level 當(dāng)前檢測電平狀態(tài), time 當(dāng)前時間戳,單位 1 ms, stable_time希望電平穩(wěn)定的時間uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 歡迎關(guān)注:魚鷹談單片機(jī)if(level != para->last_level){para->last_level = level; // 更新當(dāng)前電平狀態(tài)para->last_time = time; // 更新電平變化的時刻return 0; // 電平未穩(wěn)定}if(time - para->last_time > stable_time){ // 這兩個條件可以放在一起進(jìn)行 && 判斷嗎?return 1; // 需要上報???}return 0; // 電平穩(wěn)定時間不夠長}
typedef enum{LEVEL_LOW, //LEVEL_HIGH,}LevelTypedef;typedef struct{uint32_t last_time; // 上次時間LevelTypedef last_level; // 上次電平狀態(tài)LevelTypedef last_stable_level; // 上次穩(wěn)定的電平狀態(tài)}FilterParaTypedef;// V2.0// para 濾波變量,level 當(dāng)前檢測電平狀態(tài), time 當(dāng)前時間戳,單位 1 ms, stable_time希望電平穩(wěn)定的時間uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 歡迎關(guān)注:魚鷹談單片機(jī)if(level != para->last_level){para->last_level = level; // 更新當(dāng)前電平狀態(tài)para->last_time = time; // 更新電平變化的時刻return 0; // 電平未穩(wěn)定}if(time - para->last_time > stable_time){ // 這兩個條件可以放在一起進(jìn)行 && 判斷嗎?if(level != para->last_stable_level){ // 電平穩(wěn)定時間夠長且電平發(fā)生了變化para->last_stable_level = level;return 1; // 需要上報}}return 0; // 電平穩(wěn)定時間不夠長}
typedef struct{uint32_t last_time; // 上次時間LevelTypedef last_stable_level; // 上次穩(wěn)定的電平狀態(tài)}FilterParaTypedef;// V2.5// para 濾波變量,level 當(dāng)前檢測電平狀態(tài), time 當(dāng)前時間戳,單位 1 ms, stable_time希望電平穩(wěn)定的時間uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 歡迎關(guān)注:魚鷹談單片機(jī)if(level != para->last_stable_level){if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果這次電平穩(wěn)定時間足夠長,那么記錄這次穩(wěn)定的電平return 1; // 上報}return 0; // 不上報,同時不更新時間戳(穩(wěn)定時間不夠)}para->last_time = time; // 不斷更新電平穩(wěn)定時間,保存電平穩(wěn)定時的時間戳return 0; // 不上報}
FilterParaTypedef FilterPara;void task(void *parameter){while(1){LevelTypedef temp = (LevelTypedef)HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);if(filter(&FilterPara, temp, rt_tick_get(), 100)){rt_kprintf("stable level is %u\n",temp);}rt_thread_delay(5);}}
// V3.0// para 濾波變量,level 當(dāng)前檢測電平狀態(tài), time 當(dāng)前時間戳,單位 1 ms, stable_time希望電平穩(wěn)定的時間uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 歡迎關(guān)注:魚鷹談單片機(jī)if(level != para->last_stable_level){if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果這次電平穩(wěn)定時間足夠長,那么記錄這次穩(wěn)定的電平if(level == LEVEL_HIGH) // LEVEL_HIGH 可以作為 para 的成員變量參數(shù)傳入,方便適應(yīng)其他電平{return 1; // 上報}}return 0; // 不上報,同時不更新時間戳(穩(wěn)定時間不夠)}para->last_time = time; // 不斷更新電平穩(wěn)定時間,保存電平穩(wěn)定時的時間戳return 0; // 不上報}
// V3.1// para 濾波變量,level 當(dāng)前檢測電平狀態(tài), time 當(dāng)前時間戳,單位 1 ms, stable_time希望電平穩(wěn)定的時間uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 歡迎關(guān)注:魚鷹談單片機(jī)if(level != para->last_stable_level){if(level != LEVEL_HIGH) // LEVEL_HIGH 可以作為 para 的成員變量參數(shù)傳入,方便適應(yīng)其他電平{para->last_stable_level = level; // 快速切換狀態(tài)// para->last_time = time; // 是否有必要同時更新時間戳呢?}else if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果這次電平穩(wěn)定時間足夠長,那么記錄這次穩(wěn)定的電平if(level == LEVEL_HIGH) // LEVEL_HIGH 可以作為 para 的成員變量參數(shù)傳入,方便適應(yīng)其他電平{return 1; // 上報}}return 0; // 不上報,同時不更新時間戳(穩(wěn)定時間不夠)}para->last_time = time; // 不斷更新電平穩(wěn)定時間,保存電平穩(wěn)定時的時間戳return 0; // 不上報}
typedef enum{LEVEL_LOW, //LEVEL_HIGH,}LevelTypedef;typedef struct{uint32_t last_time; // 上次時間LevelTypedef last_stable_level; // 上次穩(wěn)定的電平狀態(tài)LevelTypedef filter_level; // 希望濾波的電平}FilterParaTypedef;// V3.2// para 濾波變量,level 當(dāng)前檢測電平狀態(tài), time 當(dāng)前時間戳,單位 1 ms, stable_time希望電平穩(wěn)定的時間uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 歡迎關(guān)注:魚鷹談單片機(jī)if(level != para->last_stable_level){if(level != para->filter_level) // LEVEL_HIGH 可以作為 para 的成員變量參數(shù)傳入,方便適應(yīng)其他電平{para->last_stable_level = level; // 快速切換狀態(tài)// para->last_time = time; // 是否有必要同時更新時間戳呢?}else if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果這次電平穩(wěn)定時間足夠長,那么記錄這次穩(wěn)定的電平if(level == para->filter_level) // LEVEL_HIGH 可以作為 para 的成員變量參數(shù)傳入,方便適應(yīng)其他電平{return 1; // 上報}}return 0; // 不上報,同時不更新時間戳(穩(wěn)定時間不夠)}para->last_time = time; // 不斷更新電平穩(wěn)定時間,保存電平穩(wěn)定時的時間戳return 0; // 不上報}
原創(chuàng)不易,歡迎轉(zhuǎn)發(fā)、留言、點(diǎn)贊、分享給你的朋友,感謝您的支持!
長按識別二維碼關(guān)注獲取更多內(nèi)容
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!





