

typedef enum{KEY_LEVEL_DOWN, // 假设低电平为按下KEY_LEVEL_UP,}KeyLevelTypedef;KeyLevelTypedef get_key_level(){return (KeyLevelTypedef)HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);}// V0.1void key_scan(){ // 欢迎关注:鱼鹰谈单片机if(get_key_level() == KEY_LEVEL_DOWN){HAL_Delay(20); // 假设抖动时间 20 msif(get_key_level() == KEY_LEVEL_DOWN){key_flag = 1;// 按键按下标志位}}}
typedef enum{KEY_STATE_IDLE, // 按键空闲KEY_STATE_DOWN, // 按键按下KEY_STATE_FINISH, // 按键处理完成(由应用程序设置)}KeyStateTypedef;KeyStateTypedef key_state;KeyLevelTypedef key_last_level; // 上次电平状态// V1.0// 函数调用周期 20 ms(如何实现应该不需要再说明了吧)void key_scan(){ // 欢迎关注:鱼鹰谈单片机KeyLevelTypedef temp; // 可不可以不使用这个中间变量?temp = get_key_level();if(temp != key_last_level){key_last_level = temp;return;}// 当运行到这里,说明电平已经稳定下来了if(temp == KEY_LEVEL_DOWN){if(key_state == KEY_STATE_IDLE){// 确保曾经释放过按键,这样可以保证在按下时不会不停设置该标志位key_state = KEY_STATE_DOWN;// 按键按下标志位}}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; // 上次电平状态}FilterParaTypedef;// V2.0// para 滤波变量,level 当前检测电平状态, time 当前时间戳,单位 1 ms, stable_time希望电平稳定的时间uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 欢迎关注:鱼鹰谈单片机if(level != para->last_level){para->last_level = level; // 更新当前电平状态para->last_time = time; // 更新电平变化的时刻return 0; // 电平未稳定}if(time - para->last_time > stable_time){ // 这两个条件可以放在一起进行 && 判断吗?return 1; // 需要上报}return 0; // 电平稳定时间不够长}

typedef enum{LEVEL_LOW, //LEVEL_HIGH,}LevelTypedef;typedef struct{uint32_t last_time; // 上次时间LevelTypedef last_level; // 上次电平状态LevelTypedef last_stable_level; // 上次稳定的电平状态}FilterParaTypedef;// V2.0// para 滤波变量,level 当前检测电平状态, time 当前时间戳,单位 1 ms, stable_time希望电平稳定的时间uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 欢迎关注:鱼鹰谈单片机if(level != para->last_level){para->last_level = level; // 更新当前电平状态para->last_time = time; // 更新电平变化的时刻return 0; // 电平未稳定}if(time - para->last_time > stable_time){ // 这两个条件可以放在一起进行 && 判断吗?if(level != para->last_stable_level){ // 电平稳定时间够长且电平发生了变化para->last_stable_level = level;return 1; // 需要上报}}return 0; // 电平稳定时间不够长}

typedef struct{uint32_t last_time; // 上次时间LevelTypedef last_stable_level; // 上次稳定的电平状态}FilterParaTypedef;// V2.5// para 滤波变量,level 当前检测电平状态, time 当前时间戳,单位 1 ms, stable_time希望电平稳定的时间uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 欢迎关注:鱼鹰谈单片机if(level != para->last_stable_level){if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果这次电平稳定时间足够长,那么记录这次稳定的电平return 1; // 上报}return 0; // 不上报,同时不更新时间戳(稳定时间不够)}para->last_time = time; // 不断更新电平稳定时间,保存电平稳定时的时间戳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 当前检测电平状态, time 当前时间戳,单位 1 ms, stable_time希望电平稳定的时间uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 欢迎关注:鱼鹰谈单片机if(level != para->last_stable_level){if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果这次电平稳定时间足够长,那么记录这次稳定的电平if(level == LEVEL_HIGH) // LEVEL_HIGH 可以作为 para 的成员变量参数传入,方便适应其他电平{return 1; // 上报}}return 0; // 不上报,同时不更新时间戳(稳定时间不够)}para->last_time = time; // 不断更新电平稳定时间,保存电平稳定时的时间戳return 0; // 不上报}

// V3.1// para 滤波变量,level 当前检测电平状态, time 当前时间戳,单位 1 ms, stable_time希望电平稳定的时间uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 欢迎关注:鱼鹰谈单片机if(level != para->last_stable_level){if(level != LEVEL_HIGH) // LEVEL_HIGH 可以作为 para 的成员变量参数传入,方便适应其他电平{para->last_stable_level = level; // 快速切换状态// para->last_time = time; // 是否有必要同时更新时间戳呢?}else if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果这次电平稳定时间足够长,那么记录这次稳定的电平if(level == LEVEL_HIGH) // LEVEL_HIGH 可以作为 para 的成员变量参数传入,方便适应其他电平{return 1; // 上报}}return 0; // 不上报,同时不更新时间戳(稳定时间不够)}para->last_time = time; // 不断更新电平稳定时间,保存电平稳定时的时间戳return 0; // 不上报}
typedef enum{LEVEL_LOW, //LEVEL_HIGH,}LevelTypedef;typedef struct{uint32_t last_time; // 上次时间LevelTypedef last_stable_level; // 上次稳定的电平状态LevelTypedef filter_level; // 希望滤波的电平}FilterParaTypedef;// V3.2// para 滤波变量,level 当前检测电平状态, time 当前时间戳,单位 1 ms, stable_time希望电平稳定的时间uint8_t filter(FilterParaTypedef *para, LevelTypedef level, uint32_t time, uint32_t stable_time){ // 欢迎关注:鱼鹰谈单片机if(level != para->last_stable_level){if(level != para->filter_level) // LEVEL_HIGH 可以作为 para 的成员变量参数传入,方便适应其他电平{para->last_stable_level = level; // 快速切换状态// para->last_time = time; // 是否有必要同时更新时间戳呢?}else if(time - para->last_time > stable_time){para->last_stable_level = level; // 如果这次电平稳定时间足够长,那么记录这次稳定的电平if(level == para->filter_level) // LEVEL_HIGH 可以作为 para 的成员变量参数传入,方便适应其他电平{return 1; // 上报}}return 0; // 不上报,同时不更新时间戳(稳定时间不够)}para->last_time = time; // 不断更新电平稳定时间,保存电平稳定时的时间戳return 0; // 不上报}
推荐阅读:
-THE END-
原创不易,如果对你有帮助,记得转发分享哦!
微信公众号「鱼鹰谈单片机」
每周一更单片机知识

长按后前往图中包含的公众号关注