ARM平台TouchGFX接入硬件编码器滚轮的触发式通信方案问询
TouchGFX 编码器触发式交互实现方案
1. C/C++混合调用与上下文绑定方案
TouchGFX的Model类本身为全局单例,无需额外获取GFX上下文,按以下方式实现C到C++的回调桥接即可:
- 首先在
Model.hpp中声明C可调用的全局触发函数与编码器处理方法:
// Model.hpp class Model : public ModelListener { public: // 原有代码逻辑全部保留 void handleEncoderRotate(int delta); // 处理编码器旋转,正为顺时针、负为逆时针 void handleEncoderPress(); // 处理编码器按键按下 private: static Model* instance; // 声明单例指针,用于绑定GFX上下文 }; // 对外暴露C可调用的全局函数声明 extern "C" void encoder_rotate_trigger(int delta); extern "C" void encoder_press_trigger();
- 之后在
Model.cpp中实现单例绑定与触发逻辑:
// Model.cpp Model* Model::instance = nullptr; Model::Model() : modelListener(0), // 原有初始化参数全部保留 { instance = this; // 构造时自动绑定当前生效的Model实例 } void Model::handleEncoderRotate(int delta) { // 直接将事件传递给当前活跃UI页面对应的Presenter if (modelListener != nullptr) { modelListener->encoderRotated(delta); } } void Model::handleEncoderPress() { if (modelListener != nullptr) { modelListener->encoderPressed(); } } // 实现C可调用的全局触发函数 extern "C" void encoder_rotate_trigger(int delta) { if (Model::instance != nullptr) { Model::instance->handleEncoderRotate(delta); } } extern "C" void encoder_press_trigger() { if (Model::instance != nullptr) { Model::instance->handleEncoderPress(); } }
- 后端C代码中只需引入上述头文件,在编码器中断或事件触发位置直接调用
encoder_rotate_trigger()、encoder_press_trigger()即可,无需关心GFX上下文逻辑。
2. 触发式事件的UI适配方案
TouchGFX本身为帧驱动渲染,直接在C回调中修改UI控件会触发线程安全问题,上述方案将事件先投递到Model层,会在接下来的帧刷新周期同步到UI层,完全避免上下文冲突:
- 在
ModelListener.hpp中新增编码器事件的虚函数,所有需要响应编码器的Presenter只需继承实现即可:
// ModelListener.hpp class ModelListener { public: virtual ~ModelListener() {} // 原有代码逻辑全部保留 virtual void encoderRotated(int delta) {} // 空默认实现,无需响应的页面不用重写 virtual void encoderPressed() {} };
- 对应页面的Presenter中重写上述两个方法,直接调用View层的控件操作逻辑即可,和TouchGFX原生按键事件的处理逻辑完全一致,无需额外适配。
3. 注意事项
- 编码器的消抖、旋转方向判断、步长计算逻辑全部放在后端C的中断处理中,C++层仅接收最终有效事件,符合你原本的架构设计
- 如果后端和TouchGFX运行在不同RTOS线程上,可给两个触发函数加轻量队列缓存事件,避免中断调用时的锁冲突,Model的tick函数每次取队列事件处理即可,本质仍是事件触发,开销远低于轮询硬件寄存器
内容的提问来源于stack exchange,提问作者Damien
相关产品推荐
相关产品推荐

