如何对IO口进行高效滤波?
扫描二维码
随时随地手机看文章
typedef enum
{
KEY_LEVEL_DOWN, // 假设低电平为按下
KEY_LEVEL_UP,
}KeyLevelTypedef;
KeyLevelTypedef get_key_level()
{
return (KeyLevelTypedef)HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
}
// V0.1
void key_scan()
{ // 欢迎关注:鱼鹰谈单片机
if(get_key_level() == KEY_LEVEL_DOWN)
{
HAL_Delay(20); // 假设抖动时间 20 ms
if(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; // 不上报}
原创不易,欢迎转发、留言、点赞、分享给你的朋友,感谢您的支持!
长按识别二维码关注获取更多内容
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!





