STMCU小助手
发布时间:2022-2-18 23:02
|
前言 TouchGFX 为 MCU 带来了炫彩丰富的 GUI 界面,使得基于 STM32 芯片的人机界面开发非常方便而友好,比如可以在 TouchGFX Designer 中创建一个按键,在 interaction 中给按键添加响应;或者创建多个界面,在界面间进行切换;这些功能由 designer 帮我们自动生成代码实现了,那与之对应的功能响应代码具体是如何实现的呢? TouchGFX 是用 C++编写的,借助 C++的模板特性,TouchGFX 定义了一组Callback 模板,基于此模板来实现上述响应的功能。' m2 l( }" o4 B% s0 g / | U8 g7 i" M Callback 模板 在 TouchGFX 中,Callback 模板的描述放在 Callback.hpp 文件中,在此定义了两组模板:GenericCallback 与 Callback 模板。+ I2 N2 h+ `- c4 ~9 X GenericCallback 模板组 GenericCallback 为 Callback 模板的模板基类。在 GenericCallback 模板中,定义了两个接口函数:isValid 与 execute;其中 isValid 是来检测 Callback 是否被初始化过,而 execute 函数用于调用实际要执行的函数。GenericCallback 模板组总共定义了 4 个模板,模板之间的差别在于 execute 函数的参数个数不同,4个模板分别对应 execute 函数带有 0 个参数,1 个参数,2 个参数与 3 个参数。本文中仅列出 execute 带一个参数的情况。9 T1 h' S, m. f! ^0 O 下面是 execute 函数带 1 个参数的 GenericCallback 模板:$ d/ o' J5 k3 J/ e. I3 g; q+ H
Callback 模板组* {: J5 K: K2 G5 ` E6 a+ [1 C* ^ Callback 模板由 GenericCallback 派生而来。Callback 模板组也有 4 个模板,分别对应于包含不同参数个数 execute 函数的 GenericCallback 模板,继承关系如下图:
下面是 execute 函数带 1 个参数的 Callback 模板:
在 Callback 结构中定义了两个私有的成员指针,pobject 为 dest_type 类型对象的指针,pmemfun_1 为 dest_type 对象的成员函数指针,是指向 dest_type 类型的成员函数。这样当 Callback 结构初始化好了以后,再调用 execute 函数时,就是直接调用了 dest_type 类型对象的成员函数 pmemfun_1。+ w0 X' p! g- m4 c% k 在使用 Callback 模板时,根据模板的特性,C++编译器会自动选择最准确的模板匹配,来生成对应的模板类或模板函数。因此在使用 Callback 模板时,可以使用不同的类型参数个数来匹配使用不同的模板。( B; z2 d* u/ s- F. s$ A : i/ p: ?& X6 ?/ R m1 L Callback 模板在 TouchGFX 中的使用0 z1 r. j1 z& O. A' o7 c 页面切换 - pendingScreenTransitionCallback 在 TouchGFX 启动过程中会初始化 MVPApplication 对象,在 MVPApplication类中定义了一个成员 pendingScreenTransitionCallback,它是GenericCallback*类型的指针,并初始化为 0;; @% O! d: {8 r4 w1 W; f TouchGFX 会调用 handlePendingScreenTransition 函数进行页面切换,最终调用 evaluatePendingScreenTransition 函数,在此函数中会用 isValid()函数来检查 Callback 是否已经初始化;如果初始化了,就调用 execute 函数 (因为Callback 为 GenericCallback*类型,因此 execute 函数不带参数) 。9 z- |% f( P2 _" u( w3 v( Q: }
具体的页面切换过程(进入第一个 screen):7 l( u; g6 ]% |. C 在 TouchGFX 初始化过程中,会初始化 FrontendApplication 对象 app,在此对象的基类中包含一个 transitionCallback 成员,其类型为: touchgfx::Callback transitionCallback2 R( O! V' l) {( R' u 在进入第一个 Screen 时,会调用 app.gotoScreen1ScreenNoTransition(),在此函数中,会将 pendingScreenTransitionCallback 设置为指向 transitionCallback的指针,最终由 TouchGFX 框架调用 execute 函数,执行 makeTransition 完成页面的切换。 // 初始化 FrontendApplicationBase::transitionCallback,transitionCallback 的私有成员初始化: // pobject 赋值为 this(指向 FrontendApplicationBase) // pmemfun_1 赋值为 &FrontendApplication::gotoScreen1ScreenNoTransitionImpl, i: @! z: C: {- k8 K; d2 h* z1 f
6 U" h! K% z. _$ A //execute 函数内实际执行的函数(pobject->*pmemfun_1)(),即为如下函数:
按键响应 - flexButtonCallback 在 TouchGFX designer 中创建一个按键,并设置 interaction 后,会在MainViewBase 类中创建两个私有成员: //按键响应函数,实现用户的动作响应 void flexButtonCallbackHandler(const touchgfx::AbstractButtonContainer& src)8 s5 O& U5 [9 ?# o //Callback 对象( T+ q0 r1 M* T, q$ _3 U touchgfx::Callback0 p/ o# S% i7 X1 ]& d5 G( F flexButtonCallback 以及一个按键成员,例如 clickButton: touchgfx::TextButtonStyle > clickButton; 在 MainViewBase 的构造函数中,会初始化 flexButtonCallback 成员,并且调用clickButton->setAction 函数,设置此按键的 AbstractButton::action 为! k h" Y& G; m flexButtonCallback,: J9 ~( E. l6 G9 y. J/ b/ P1 `8 ], j MainViewBase::MainViewBase():flexButtonCallback(this,. J2 T _. i P! o ~4 d' r8 ] MainViewBase::flexButtonCallbackHandler), \% K' \& [' L0 [4 w6 L* r+ M 其中: flexButtonCallback 的 pobject 成员初始化为 this(指向 MainViewBase 的指针)6 P% P: G) h! H7 v2 V9 ? flexButtonCallback 的 pmemfun_1 成员初始化为5 D8 V$ i3 D, H$ b' }5 e &MainViewBase::flexButtonCallbackHandler B/ p- j* ^* A5 b 由于 flexButtonCallback 的类型是 struct Callback<dest_type, T1, void, void> : public GenericCallback<T1>/ |; d/ l9 W k% m6 \ 因此 flexButtonCallback 的 execute 函数带有一个参数,参数类型为 const touchgfx::AbstractButtonContainer&,最终此参数会传递给flexButtonCallbackHandler 函数。 在程序运行时,点击按键后,TouchGFX 框架会捕获此事件,并在AbstractButton::handleClickEvent 函数中调用 action->execute(*this)函数,最终即执行了 flexButtonCallbackHandler 函数,实现了用户的动作响应。 小结 本文介绍了 TouchGFX 中 Callback 模板的基本原理,并结合两个例子,简要说明了 Callback 模板在框架中的使用方法。只要注意 Callback 的类型、初始化过程,以及最终 execute 函数执行的函数主体,就能理解 Callback 模板了,这对深入理解 TouchGFX 也有一定帮助。 % h7 ~4 Q) Q( X5 I% W |
【经验分享】STM32语音识别的智能蓝牙音箱(源程序+原理图+PCB+设计说明书+PPT)
想找个ST芯片
[GPIO] 使用新型抽象开始C++嵌入式编程,从GPIO开始
技术手册stm32f1xx中的一个小问题
【经验分享】STM32 HAL库移植FreeModbus详细步骤
【逢7发帖赢大礼】STM32开发之IC门禁卡UID读取方法!
实战经验 | Keil工程使用NEAI库的异常问题
经验分享 | FDCAN数据段波特率增加后发送失败的问题分析
STM32几种流行开发环境的优缺点
好用软件推荐-TouchGFX Designer
微信公众号
手机版