touchgfx -- Integration
将UI连接到系统
在大多数应用程序中,UI需要以某种方式连接到系统的其余部分,并发送和接收数据。这可以与硬件外围设备(传感器数据,A / D转换,串行通信等)接口,也可以与其他软件模块接口。
本文介绍了实现此连接的推荐解决方案。
第一种方法是“快速且肮脏的”方法,主要用于原型制作,而第二种方法是在架构上合理地将UI与现实应用程序中的其余组件连接的一种方法。
在本文的最后,我们链接到使用这两种方法的示例。
模型类
所有TouchGFX应用程序都有一个Model类,该类除了存储UI状态信息之外,还旨在充当您周围系统的接口。这样,我们既指硬件外围设备,也指系统中的其他OS任务。通常,访问各个View类中的其他软件模块或硬件不是一个好的设计。
Model类非常适合放置任何此类接口代码,因为:
- Model类具有tick()函数,该函数会在每帧中自动调用,并且可以实现为查找其他子模块中的事件并对事件做出反应。
- Model类具有指向您当前活动的Presenter的指针,以便能够将传入事件通知UI。
硬件接口
方法1:直接从GUI任务采样
与硬件接口的最佳方法取决于您需要采样的频率,采样的时间和时间的紧迫性。如果您在这些方面的要求比较宽松,那么最简单的方法就是直接在Model::tick功能中对硬件进行采样 。如果采样发生的频率低于帧速率(通常在60Hz左右),则可以添加一个计数器,并且仅在第N个时钟间隔进行一次采样。用这种方法完成后,您的采样操作必须快一些(通常为1ms或更短),否则您的帧速率将开始受到影响,因为采样是在GUI任务的上下文中完成的,并且会延迟绘制帧。
方法2:从辅助任务采样
或者,如果不希望将硬件交互直接放在GUITask的上下文中,则可以创建一个新的OS任务来执行采样。您可以配置此任务以在特定情况下所需的确切时间间隔上运行。另外,根据您的需要,此新任务的优先级可以比GUI任务低或高。如果它具有更高的优先级,那么可以保证它在指定的时间准确运行,而不管GUI任务在做什么。这样做的缺点是,如果这是占用CPU的进程,则可能会影响UI的帧速率。另一方面,如果采样不是时间紧迫的,则可以为任务分配比GUI任务更低的优先级,这样UI帧速率就不会受到硬件采样的影响。
如果您使用辅助任务方法,我们建议您利用RTOS提供的任务间消息传递系统。大多数(如果不是全部)RTOS具有队列/邮件机制,可让您将数据(通常是用户定义的C结构,字节数组或简单整数)从一个任务发送到另一个任务。为了将新数据传递到GUI任务,请为UI tast设置邮箱或消息队列,然后使用此消息传递系统将数据发送到GUI任务。然后,您可以Model::tick轮询GUI任务的邮箱,以检查是否有新数据到达。以防万一,读取数据并相应地更新UI。
将数据传播到UI
无论使用方法1还是方法2,该Model::tick功能都是GUITask知道要在UI中显示的新数据的地方。除了充当与周围系统的接口之外,还记得以前Model该类还负责保存状态数据,因此可能还需要更新一些状态变量。
让我们考虑一个简单的示例,其中将温度传感器连接到系统,并且当前温度将显示在UI中。在准备中,我们将扩展Model类以支持此操作:
Model.hpp:
class Model
{
public:
// Function that allow your presenters to read current temperature.
int getCurrentTemperature() const { return currentTemperature; }
// Called automatically by framework every tick.
void tick();
...
private:
// Variable storing last received temperature;
int currentTemperature;
...
};
通过上述操作,您Presenters 可以向模型询问当前温度,从而允许演示者在进入显示温度的屏幕时在UI(视图)中设置此值。我们现在需要做的是能够在收到新的温度信息时再次更新UI。为此,我们利用了模型具有指向您当前活动的演示者的指针这一事实。该指针的类型是接口(ModelListener),您可以对其进行修改以反映适当的应用程序特定事件:
ModelListener.hpp:
class ModelListener
{
public:
// Call this function to notify that temperature has changed.
// Per default, use an empty implementation so that only those
// Presenters interested in this specific event need to
// override this function.
virtual void notifyTemperatureChanged(int newTemperature) {}
};
现在我们已经连接了该接口,剩下的就是对传入的“新温度”事件进行实际采样了。 Model::tick
Model.cpp
void Model::tick()
{
// Pseudo-code for Method 1 or Method 2. Depends on your concrete Operating System
if (OS_Poll(GuiTaskMBox))
{
// Here we assume that you have defined a "Message" struct containing type and data,
// along with some event definitions.
struct Message msg = OS_Read(GuiTaskMBox);
if (msg.eventType == EVT_TEMP_CHANGED)
{
// We received information that temperature has changed.
// First, update Model state variable
currentTemperature = msg.data;
// Second, notify the currently active presenter that temperature has changed.
// The modelListener pointer points to the currently active presenter.
if (modelListener != 0)
{
modelListener->notifyTemperatureChanged(currentTemperature);
}
}
}
}
上面的方法可以确保两件事:
- currentTemperature变量始终是最新的,以便您的Presenter可以随时获取当前温度。
- 主持人会立即收到有关温度变化的通知,并可以采取适当的措施。
MVP模式的优点之一是,您可以根据当前所处的屏幕来单独处理通知。例如,假设在显示某种与当前温度无关的设置菜单(例如,MainMenuPresenter / MainMenuView处于活动状态)时发生了温度变化事件。
由于notifyTemperatureChanged函数具有默认的空实现,因此MainMenuPresenter完全忽略了此通知。另一方面,如果您有TemperatureControlPresenter,则可以在此演示者中重写notifyTemperatureChanged函数,并通知View它应显示更新的温度:
TemperatureControlPresenter.hpp:
class TemperatureControlPresenter : public ModelListener
{
public:
// override the empty function.
virtual void notifyTemperatureChanged(int newTemperature) {
view.setTemp(newTemperature);
}
};
将数据从UI传输到周围的系统
数据/事件从UI传输到周围系统的相反方向是通过Model进行的,方法大致相同。如果需要添加配置新设定点(目标温度)的功能,则从上一个示例继续进行,我们将在模型中添加以下内容:
Model.hpp:
void setNewTargetTemperature(int newTargetTemp)
{
// Pseudo-code for sending an event to a task responsible for controlling temperature.
struct Message msg;
msg.eventType = EVT_SET_TARGET_TEMP;
msg.data = newTargetTemp;
OS_Send(SystemTaskMBox, &msg);
}
如果用户在UI中设置新的目标温度,则视图可以通知Presenter,该Presenter拥有指向Model对象的指针,因此可以调用该 setNewTargetTemperature函数。
例子
方法1-从GUI任务
下载此链接可找到STM32F746的工作示例,该示例演示如何在Model类中对按钮进行采样并直接控制LED。该示例使用MVP体系结构在两个视图和Model类之间传递值和事件。Model类对按钮进行采样并更新LED以匹配应用程序的状态。
下载此链接可找到STM32F429的工作示例,其中显示了如何对Model类中的按钮进行采样。该示例使用MVP架构将按钮事件传输到视图。
方法2-从其他任务
方法3-从多个任务(4.9.3)
该工作示例已在2018年5月28日举行的TouchGFX网络研讨会“与硬件集成”中进行了演示。
该应用程序是为STM32F769-DISCO板设计的,并与LED和用户按钮交互,以显示如何将C代码和硬件外围设备集成到您的TouchGFX应用程序中。
应用程序以GPIO模式配置按钮。行为是在btntask.c中采样按钮的状态,如果按下按钮,则将消息通过GUI消息队列传递。这使我们可以通过按住按钮来在应用程序中推进动画。
该应用程序使用三个FreeRTOS任务。一个用于GUI,每个用于外围设备(LED和用户按钮)。
方法4-从任务和外部中断线(4.9.3)
该工作示例已在2018年5月28日举行的TouchGFX网络研讨会“与硬件集成”中进行了演示。
该应用程序是为STM32F769-DISCO板设计的,并与LED和用户按钮交互,以显示如何将C代码和硬件外围设备集成到您的TouchGFX应用程序中。
该应用程序将按钮配置为EXTI模式(外部中断线0)。行为是在按下按钮后接收中断,然后清除中断。这不允许与GPIO中的行为相同,但是我们将单步执行动画,因为仅在接收到中断时才通过gui消息队列发送消息。
该应用程序使用两个FreeRTOS任务。一个用于GUI,一个用于LED。(方法3中的Button任务在此应用程序中保持活动状态,以说明外围设备交互代码已移至中断处理程序中)。
【原文】
touchgfx -- Integration的更多相关文章
- 在 Laravel 中使用图片处理库 Integration/Image
系统需求 PHP >= 5.3 Fileinfo Extension GD Library (>=2.0) … or … Imagick PHP extension (>=6.5.7 ...
- 按照Enterprise Integration Pattern搭建服务系统
在前一篇文章中,我们已经对Enterprise Integration Pattern中所包含的各个组成进行了简单地介绍.限于篇幅(20页Word以内),我并没有深入地讨论各个组成.但是如果要真正地按 ...
- Enterprise Integration Pattern - 组成简介
近些年来,越来越多的Web应用正在逐渐向大型化的方向发展.它们通常都会包含一系列相互协作的子服务.在开发过程中,如何让这些子服务协同工作常常是软件开发人员所最为头疼的问题,如各个子服务之间的数据表示不 ...
- Spring 4 + Quartz 2.2.1 Scheduler Integration Example
In this post we will see how to schedule Jobs using Quartz Scheduler with Spring. Spring provides co ...
- OpenCASCADE Gauss Integration
OpenCASCADE Gauss Integration eryar@163.com Abstract. Numerical integration is the approximate compu ...
- MAGENTO - APACHE SOLR INTEGRATION - PART II (SETUP)
MAGENTO - APACHE SOLR INTEGRATION - PART II (SETUP) Tue, 03/01/2011 - 18:30 Tweet Development E-Comm ...
- POSTMAN as debugger for integration APPs
Chrome Menu: Window > Extensions > Postman - REST Client 0.8.4.10 起个标题,有空总结一下一个经验,关于Netsuite i ...
- [转](六)unity4.6Ugui中文教程文档-------概要-UGUI Animation Integration
5.Animation Integration(动画集成) 动画允许控件的所有状态之间相互转换,充分使用unity的动画系统.这是最强大的的转换模式的在处理很多属性的同时可以进行动画. 要使用动画转换 ...
- Informatica相同环境与不同环境的导入导出( Repository Name,Integration Service Name,Folder Name是否相同):
Informatica相同环境与不同环境的导入导出( Repository Name,Integration Service Name,Folder Name是否相同): 1.repository N ...
随机推荐
- 如何调试JS查看异常信息
如果页面上有错误,html页面的控制台会报错,可以查看报错信息,找到对应的行,找到出错的位置.也可以通过editplus运行调试,editplus会以弹框的形式出现提示,哪行的什么位置什么错误,需要记 ...
- ubuntu16.04 下通过rc.d(rc.local)实现开机启动(未登录)anydesk
先编辑anydesk-X.X.X/init/anydesk文件,将"DAEMON=//usr/bin$NAME"改成"DAEMON=/XXX/anydesk-5.1.1/ ...
- 欢迎访问我的csdn博客
csdn博客:https://blog.csdn.net/qq_27307175 这个里面有:许许多多的专业文章. 本人主要研究:网络工程,VMware虚拟化,docker容器,以及Linux等技术, ...
- 【编程开发】非对称加密过程详解(基于RSA非对称加密算法实现)
1.非对称加密过程: 假如现实世界中存在A和B进行通讯,为了实现在非安全的通讯通道上实现信息的保密性.完整性.可用性(即信息安全的三个性质),A和B约定使用非对称加密通道进行通讯,具体 ...
- openssl交叉编译
目录 openssl交叉编译 title: openssl交叉编译 date: 2019/12/18 21:09:33 toc: true --- openssl交叉编译 tar xvf openss ...
- Collection集合常用的功能
package demo06; import java.util.ArrayList;import java.util.Collection; /** java.util接口 Collection&l ...
- C语言--分支结构
一.PTA实验作业 题目1:7-1 计算分段函数[2] 1.实验代码 float x, y; printf("Enter x:\n"); scanf("%f", ...
- 《你必须知道的495个C语言问题》读书笔记之第4-7章:指针
1. Q:为什么我不能对void *指针进行算术运算? A:因为编译器不知道所值对象的大小,而指针的算法运算总是基于所指对象的大小的. 2. Q:C语言可以“按引用传参”吗? A:不可以.严格来说,C ...
- poj3347(扩大数据,避免小数)
题目链接:https://vjudge.net/problem/POJ-3347 题意:摆放n个正方形,问俯视视角来看时哪些正方形可见. 思路:在刷计算几何专题时刷到这题,但不需要用计算几何的知识.我 ...
- 什么是Java多线程?
第五阶段 多线程 前言: 一个场景:周末,带着并不存在的女票去看电影,无论是现场买票也好,又或是手机买票也好,上一秒还有位置,迟钝了一下以后,就显示该座位已经无法选中,一不留神就没有座位了,影院的票是 ...