在之前的学习研究过程中,已经了解并实践了通过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
|