在大多数应用中,UI需以某种方式连接到系统的其余部分,并发送和接收数据。 它可能会与硬件外设(传感器数据、模数转换和串行通信等)或其他软件模块进行交互通讯。

Model类

所有TouchGFX应用都有Model类,Model类除了存储UI状态信息,还可用作面向周围系统的接口。 这里周围系统我们指的是在你整个系统中用到的硬件外设以及需要进行通讯的其他任务。 通常来讲,在各自的View类中直接访问其他软件模块或者硬件外设并不是个好的设计。

Model类非常适合放置任何此类接口代码,原因在于:

  1. Model类有 tick() 函数,会在每一帧自动调用,并且可实现用于查找来自其他子模块的事件或对事件作出反应。
  2. Model类有一个指向当前活动Presenter的指针,它能够将传入事件通知给UI。

以下示例为:通过button控件,触发数据发送给系统其他任务;该任务再将数据发回touchgfx任务。

首先程序需要touchgfx以外的一个任务,和两个用来收发数据的队列

TouchGFX之后端通信-LMLPHP

然后创建一个button控件,并设置交互为调用虚函数

TouchGFX之后端通信-LMLPHP

编写向周围系统发送数据的程序

screenView.hpp


#ifndef SCREENVIEW_HPP
#define SCREENVIEW_HPP

#include <gui_generated/screen_screen/screenViewBase.hpp>
#include <gui/screen_screen/screenPresenter.hpp>

class screenView : public screenViewBase
{
public:
    screenView();
    virtual ~screenView() {}
    virtual void setupScreen();
    virtual void tearDownScreen();
		virtual void function1();
protected:
};

#endif // SCREENVIEW_HPP
screenView.cpp


#include <gui/screen_screen/screenView.hpp>

screenView::screenView()
{

}

void screenView::setupScreen()
{
    screenViewBase::setupScreen();
}

void screenView::tearDownScreen()
{
    screenViewBase::tearDownScreen();
}

void screenView::function1()
{
	presenter->bc();
}
screenPresenter.hpp


#ifndef SCREENPRESENTER_HPP
#define SCREENPRESENTER_HPP

#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>

using namespace touchgfx;

class screenView;

class screenPresenter : public touchgfx::Presenter, public ModelListener
{
public:
    screenPresenter(screenView& v);

    /**
     * The activate function is called automatically when this screen is "switched in"
     * (ie. made active). Initialization logic can be placed here.
     */
    virtual void activate();

    /**
     * The deactivate function is called automatically when this screen is "switched out"
     * (ie. made inactive). Teardown functionality can be placed here.
     */
    virtual void deactivate();

    virtual ~screenPresenter() {}

		void bc();

private:
    screenPresenter();

    screenView& view;
};

#endif // SCREENPRESENTER_HPP
screenPresenter.cpp


#include <gui/screen_screen/screenView.hpp>
#include <gui/screen_screen/screenPresenter.hpp>

screenPresenter::screenPresenter(screenView& v)
    : view(v)
{

}

void screenPresenter::activate()
{

}

void screenPresenter::deactivate()
{

}

void screenPresenter::bc()
{
	model->toggleState();
}
Model.hpp


#ifndef MODEL_HPP
#define MODEL_HPP

class ModelListener;

class Model
{
public:
    Model();

    void bind(ModelListener* listener)
    {
        modelListener = listener;
    }

    void tick();
		
		void toggleState();
		
protected:
    ModelListener* modelListener;
		bool state;
};

#endif // MODEL_HPP
Model.cpp


#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>
#include "../../../../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h"

#ifndef SIMULATOR

//*******************************************************
//   Define Queue handles
//*******************************************************
extern "C" {
    extern osMessageQueueId_t myQueue01Handle;
    extern osMessageQueueId_t myQueue02Handle;
}
#else
#include <stdio.h>
#endif

Model::Model() : modelListener(0), state(0)
{

}

void Model::tick()
{

}

void Model::toggleState()
{
	state = !state;

#ifndef SIMULATOR
    uint16_t msg = state;

    if (myQueue01Handle)
    {
        osMessageQueuePut(myQueue01Handle, &msg, 0, 0);
    }
#endif
}
freertos.c


void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
	uint16_t msg = 0;
  /* Infinite loop */
  for(;;)
  {
        if (osMessageQueueGet(myQueue01Handle, &msg, 0U, 1000) == osOK)
        {

        }
  }
  /* USER CODE END StartDefaultTask */
}

编写向UI发送数据的程序

freertos.c


void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
	uint16_t msg = 0;
	uint16_t color;
  /* Infinite loop */
  for(;;)
  {
        if (osMessageQueueGet(myQueue01Handle, &msg, 0U, 1000) == osOK)
        {
					if(msg)
						color = 0x0000;
					else
						color = 0xFFFF;
					osMessageQueuePut(myQueue02Handle, &color, 0U, 0);
        }
  }
  /* USER CODE END StartDefaultTask */
}
Model.hpp


#ifndef MODEL_HPP
#define MODEL_HPP

class ModelListener;

class Model
{
public:
    Model();

    void bind(ModelListener* listener)
    {
        modelListener = listener;
    }

    void tick();
		
		void toggleState();
		void setboxColor(unsigned short color);
protected:
    ModelListener* modelListener;
		bool state;
};

#endif // MODEL_HPP
Model.cpp


#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>
#include "../../../../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h"

#ifndef SIMULATOR

//*******************************************************
//   Define Queue handles
//*******************************************************
extern "C" {
    extern osMessageQueueId_t myQueue01Handle;
    extern osMessageQueueId_t myQueue02Handle;
}
#else
#include <stdio.h>
#endif

Model::Model() : modelListener(0), state(0)
{

}

void Model::tick()
{
#ifndef SIMULATOR

    //*******************************************************
    //
    //  HANDLE MESSAGES
    //
    //  Check for messages from backend, with zero timeout to
    //  avoid blocking the UI.
    //
    //*******************************************************
    //

    uint16_t msg = 0;
    if (osMessageQueueGet(myQueue02Handle, &msg, 0U, 0) == osOK)
    {
			setboxColor(msg);
    }

#endif
}

void Model::toggleState()
{
	state = !state;

#ifndef SIMULATOR
    uint16_t msg = state;

    if (myQueue01Handle)
    {
        osMessageQueuePut(myQueue01Handle, &msg, 0, 0);
    }
#endif
}

void Model::setboxColor(unsigned short color)
{
    modelListener->setboxColor(color);
}
#ifndef MODELLISTENER_HPP
#define MODELLISTENER_HPP

#include <gui/model/Model.hpp>

class ModelListener
{
public:
    ModelListener() : model(0) {}
    
    virtual ~ModelListener() {}

    void bind(Model* m)
    {
        model = m;
    }
		
		virtual void setboxColor(unsigned short color) {}
protected:
    Model* model;
};

#endif // MODELLISTENER_HPP
#ifndef SCREENPRESENTER_HPP
#define SCREENPRESENTER_HPP

#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>

using namespace touchgfx;

class screenView;

class screenPresenter : public touchgfx::Presenter, public ModelListener
{
public:
    screenPresenter(screenView& v);

    /**
     * The activate function is called automatically when this screen is "switched in"
     * (ie. made active). Initialization logic can be placed here.
     */
    virtual void activate();

    /**
     * The deactivate function is called automatically when this screen is "switched out"
     * (ie. made inactive). Teardown functionality can be placed here.
     */
    virtual void deactivate();

    virtual ~screenPresenter() {}

		void bc();
		virtual void setboxColor(unsigned short color);
private:
    screenPresenter();

    screenView& view;
};

#endif // SCREENPRESENTER_HPP
#include <gui/screen_screen/screenView.hpp>
#include <gui/screen_screen/screenPresenter.hpp>

screenPresenter::screenPresenter(screenView& v)
    : view(v)
{

}

void screenPresenter::activate()
{

}

void screenPresenter::deactivate()
{

}

void screenPresenter::bc()
{
	model->toggleState();
}

void screenPresenter::setboxColor(unsigned short color)
{
	view.setbox1Color(color);
}
#ifndef SCREENVIEW_HPP
#define SCREENVIEW_HPP

#include <gui_generated/screen_screen/screenViewBase.hpp>
#include <gui/screen_screen/screenPresenter.hpp>

class screenView : public screenViewBase
{
public:
    screenView();
    virtual ~screenView() {}
    virtual void setupScreen();
    virtual void tearDownScreen();
		virtual void function1();
		void setbox1Color(unsigned short color);
protected:
};

#endif // SCREENVIEW_HPP
#include <gui/screen_screen/screenView.hpp>

screenView::screenView()
{

}

void screenView::setupScreen()
{
    screenViewBase::setupScreen();
}

void screenView::tearDownScreen()
{
    screenViewBase::tearDownScreen();
}

void screenView::function1()
{
	presenter->bc();
}

void screenView::setbox1Color(unsigned short color)
{
	box1.setColor(color);
	box1.invalidate();
}

烧录进开发板,现象(点击按钮,box颜色在黑白之间切换)

TouchGFX之后端通信-LMLPHPTouchGFX之后端通信-LMLPHP

10-04 00:56