打印
[STM32H7]

【STM32H750B-DK评测】6.传感器数据读取及TouchGFX界面显示实战

[复制链接]
491|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
在之前的学习研究过程中,已经了解并实践了通过I2C接口读取MPU6050运动传感器数据,以及了解了如何使用TouchGFX。
经过进一步的学习了解,弄明白了读取传感器数据和TouchGFX界面显示之间的关联逻辑。

屏幕刷新需要很快的速度,所以我们一般不能在TouchGFX主任务中,去做数据读取的操作,除非是速度非常非常的快。

因为使用的FreeRTOS可以是多任务的,那么在实际开发中,往往是在一个任务读取传感器数据,然后通过一定的方式,通知TouchGFX任务可以更新数据了。这样就只在数据发生变更的时候,才更新界面,大大提高了效率。

要在两个任务之间进行通信,可以有多种方式,例如通过消息队列,来发送消息,也可以通过信号量,来进行简单信息的传递。

因为我要做的这个实例中,只有从MPU6050读取数据然后显示,所以并不复杂很简单,那最终我使用了信号量的方式。

一、逻辑设计:
最终实现的逻辑如下:


二、MVP架构了解:
因为TouchGFX使用的是MVP架构,所以需要先了解一下这个MVP架构。


上图是从官方资料中看到的。如果是做过互联网开发,可能对上面这个图非常眼熟。没错,这个和MVC基本上就是一个概念了。
简单来说:
Model:这个部分,负责界面状态信息的存储,以及与底层系统部分的接**互
View:顾名思义,用于界面的呈现
Presenter:负责业务逻辑的逻辑,从Model获取数据,然后操控View来进行显示。
这么做的目的,就是为了有效的把各个部分进行接偶,各行其是。

一个更完整的交互图,是下面这样的:


其中就包含了,与底层系统打交道。

三、代码实例:
打开之前用ToucGFX Designer设计的界面,并输出的代码,可以找到MVP各个部分的代码:


下面,对这个部分的代码,做一些简单的讲解,以便大家明白MVP架构。

要实现我之前的逻辑中TouchGFX部分的功能:

那么我就需要在Model中,检测信号量,如果可用,就获取MPU6050数据读取任务传递过来的,然后提供给Presenter,Presenter再调用View的方法,去显示获取的数据。

1:Model
首先是M部分,打开Model.hpp和Model.cpp,可以看到下面的代码:

在Model.hpp部分,我添加了一个mpu6050MsgBody()的方法,在该方法中,负责将数据提供给Presenter的部分。



在Model.cpp中,有一个tick方法,每秒会被Touchgfx后台执行60次,是用来更新屏幕的。在这个方法中的调用,要狠准快,速度慢了,拖累屏幕刷新。所以,在这里,使用了一个信号量来确定是否需要刷新数据。这样就可以确保数据更新的时候,才会刷新。

而这个信号量,是在main.c重定义的,所以这里需要使用extern定义。后面讲到main.c部分再详细说明。

当发现信号量可用的时候,就马上申请获取信号量标记,然后刷新屏幕,也就是调用modelListener->mpu6050MsgRdy()。如果信号量不可用,那么就直接跳过了。

2. Presenter
然后,我们再打开Presenter部分的代码:

在其中,也定义了一个mpu6050MsgRdy()方法。

因为其继承自ModelListener,所以在Model.cpp中调用modelListener->mpu6050MsgRdy(),最终到了这里。

因为逻辑很简单,所以这里的方法实现,就是再调用View对应的嗯方法,去刷新数据了。

上述代码中的方法名称,大家可以根据自己的需要进行,进行定义。

3. View:
最后我们再看View的部分:


这个部分其实逻辑也很简单,就是将rawAccelX的值,给更新到屏幕上的AccelX控件中。

rawAccelX会在MPU6050数据读取任务中使用,所以这里需要视同extern定义。

4. 界面控件定义:
这里的AccelX是一个Text控件,在TouchGFX Designer中,通过如下方式进行定义:

在上面显示的具体内容中,使用了X: <value>,这里的value,就可以在我们的代码中进行修改,从而刷新显示。

另外,还需要设置可以输入的字符串范围,也就是不能随便显示,以免弄乱了屏幕。



通过上面的方式,可以定义Typographies,来规范Texts中的value变量,可显示的字符串范围。

上面使用了默认的Default,在实际开发中,可以根据需要进行设置。其中的定义,可以试用ASCII自负,也可以用十六进制定义。

5. 界面定义代码:
上述定义,最终会在代码中体现:

打开上面两个代码,找到AccelX的定义:


上述界面的定义,完全手写,也是可以的。
TouchGFX则以图形化的方式,方便我们进行设计定义。

6. 实际呈现:
在之前View部分的代码中:


当刷新数据的时候,实际上是修改了在界面中定义的AccelXBuffer,修改这个值,那么AccelX对应的【X:<value>】中的value就会自动变化,从而屏幕刷新。


晃动MPU6050的摇杆,数值就会发生变化了:


7. 传感器数据读取:
上面是TouchGFX处理的部分,下面在简单说一下MPU6050数据读取的部分:

在PollingRoutines中,负责具体的数据读取处理。

在main.c中,负责启动对应的任务,并在任务重调用读取函数即可。

上述代码的三个部分,分别为初始化MPU6050,新建信号量,然后启动读取任务。


读取任务重,每两秒进行一次读取处理调用。

这里可以根据实际需要,提高读取间隔时间。如果有printf输出的话,就要注意读取速度别太快了,要么就先注释掉。

然后是PollingRoutines的定义了:


其中的核心部分,就是我们之前读取MPU6050数据的部分了。

读取后,再释放信号量。当信号量释放后,TouchGFX的Model就能知道了:


8. 最终效果:
最后,我们再看一下最开始的逻辑图:

通过RTOS的多任务,启动一个传感器数据读取的任务,读取导数据后,就释放信号量;
再启动一个TouchGFX(默认)进程,当检测到信号量可用的时候,就赶紧刷新界面。

就这样,我们就能把传感器和屏幕呈现关联起来了。
如法**制,我们可以把其他的控件也参考AccelX做处理,从而显示更多的传感器信息。

具体的视频效果如下:https://www.bilibili.com/video/BV1WW4y1v7eQ




30623632bdd3e5427b.png (27.45 KB )

30623632bdd3e5427b.png

使用特权

评论回复
沙发
朝生| | 2022-10-4 12:22 | 只看该作者
用的是VSCode开发?TouchGFX有提供这个环境的工程吗?

使用特权

评论回复
板凳
tpgf| | 2022-10-17 16:13 | 只看该作者
我感觉最重要的就是要处理好采集的传感器数据同显示之间的时序关系

使用特权

评论回复
地板
zljiu| | 2022-10-17 18:00 | 只看该作者
传感器数据和TouchGFX界面显示之间是否仅仅存在字库以及字符转换的关系呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

86

帖子

2

粉丝