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(如何實現(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ā)、留言、點贊、分享給你的朋友,感謝您的支持!
長按識別二維碼關(guān)注獲取更多內(nèi)容
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!