Biu~又来更新按键功能系列了,咦嘻嘻嘻嘻~在本系列第二章的视频中简单提到一个快速使用低电平有效的按键实现方式,是小编无意中在ButtonParseXml.xsd这个文件中发现的一个元素标签声明,按字面意思就是低电平触发事件。
看到这个定义,脑袋存在的想法就是觉得这样定义很简单方便,就默默把这个方法记下来。However,戏剧性的一幕发生了,有个客户有天问问怎么将按键变成低电平有效,脑袋在闪出第一个解决方法就是将activePinFriendlyName改成negatePinFriendlyName。
完事,Perfect!
“长按有效,单击无效”,
当我听到客户反馈的时候,其实我是拒绝的,因为我觉得,某某应该不会这么坑。但我也是第一次,我也要试一下。我不能说一个功能放在那里,一用就一定是Duang~实现了,到时客户试了很久一定会骂我,根本没有这种功能,所以我说先等我试一试。
以下内容纯属个人理解,如有雷同,那一定是你抄我的╭(╯^╰)╮;如有不同,那一定是你的错( ̄_, ̄ );如是我错,你也不能在评论区评论(本来就没人评论,你的评论就额外显眼 o(╥﹏╥)o)
事件真没我想的那么简单,negatePinFriendlyName这个元素便签,能被识别,并生成对应的数据。然而这些数据在使用的时候没有被正确处理。
如果想要渔,可以回看我第二篇博文了解该数组的相关内容,点我!点我!
如果想要鱼,直接拉到最后面
我们知道按键的处理都是在input_event_manager.c 文件中,所有的按键都在inputEventsChanged函数中做识别处理,我们一个个来看这些处理函数。首先我们在第二篇说了x_bottun.buttonxml都会生成一个数组,其中数组的两个变量需要理解一下
bits是指这个IO是高有效还是低有效,高有效时和mask变量一致,低有效为0;mask是指这个这个触发的消息和哪个IO有关。这个数组在初始化时候(appInputEventMangerInit)会被引用到他的指针。
而input_event_manager_state.action_table这个变量直接搜索是找不到别的地方调用的,会懵圈不o((⊙﹏⊙))o。其实这里是随着input_event_manager_state.task这个指针变量注册成PIO处理函数了
PioMonitorRegisterTask(&input_event_manager_state.task,pio);
当PIO变化时,就会调用iemHandler函数处理,这里面的变量Task就是当时注册的input_event_manager_state.task。那怎么用呢,变量类型是Task啊,不是InputEventState_t呀,为什么他直接强制类型转换就能使用了。
童鞋们冷静点,是否还记得Task类型是指针类型,他是指向TaskData类型的一个指针,也就是指向注册PIO处理函数的input_event_manager_state.task,input_event_manager_state.task也是InputEventState_t结构体里面的第一个变量,那第一个变量的指针知道了,结构体里的其他变量自然而然的能用上了。得到这个结构体之后,后面的处理会一直使用到这个结构体(名为state)
- state->pio_state是保存当前PIO的状态
- calculateInputEvents函数是将PIO的物理状态映射到方便运算的逻辑状态,得到input_event_bits,这个input_event_bits会保存到state->input_event_bits中,通过当前状态和之前保存的状态做异或运算就知道有哪些IO状态变化了,单单处理这些变化的IO就可以了
- state->action_table是配置表,也就是buttonxml生成的数据,通过遍历,找到变化IO对应的处理动作,一一处理,后面常被赋值到input_action中使用
直到这里都是很正常的,因为改成低有效的部分在这前面都没有被使用到。真正使用到的得分是各个处理的action,请留意input_action->bits这个变量,前面说了,这是标志高低有效的变量。而在各个action中的处理就没有考虑低有效的部分,所以导致低有效的的处理不能实现预期目的。
在singleClickAction中,有个判断是否松开按键的动作
不看变量名,从逻辑理解,就是之前是状态是有效状态的,现在不是有效状态的就执行。这看上去是没啥问题,但是我们忽略了,记录状态的state->input_event_bits在上电时是没有初始化的,而这个变量本应该是跟物理状态一致的,换句话说,IO拉高时,这个变量的对应位置会是1,而在一开始没有初始化,对应位置是0。低有效时只要有其他任意一个IO检查到变化,它都会一同处理,就会错误地执行到了释放的动作,在heldAction及其他处理中也是一样的情况
所以这部分需要在初始化时把低电平有效的情况考虑进去,这里就根据配置表初始化IO初始状态
回到singleClickAction看,还有另外两个变量single_press_already_detected和held_release_detected,这两个变量是表示之前已经检查到单击按下和有长按动作。这是为了过滤一些错误情况,只有已经有按下动作,才能执行松开动作的处理;如果有长按动作就不能执行单击动作的处理,同理这部分在双击也会有使用。但是这部分记录的语句用的是input_action->bits做或运算记录,导致低有效时不会被记录, ̄□ ̄||
state->single_click_tracker.long_press |= (input_action->bits);
需要改成input_action->mask才能正确记录,同时在使用时,判断出是低有效的按键就要取反。同理在很多记录和使用的地方都要改成这样
这就是改成按键低有效的运用,其实在官方代码中低有效是配合高有效一起使用的,用来实现只要有按键变化时都触发消息
以上是本期博文的全部内容,如有疑问请在博文下方评论留言,或者有什么想了解的都可以留言,我会尽量安排上(o´ω`o)و。谢谢大家浏览,我们下期再见。
常用按键参考修改见附件
多看文档,多上官网
多看文档,多上官网
评论
Maycee
2023年3月28日
Rain Zhang
2021年2月8日
Biu~
2020年12月3日
Carrie
2020年11月27日
Carrie
2020年11月27日
Carrie
2020年11月27日
Charles Yu
2020年11月27日
Biu~
2020年11月26日
林工
2020年11月25日