STM32单片机项目实例:基于TouchGFX的智能手表设计(7)MVP架构下的交互逻辑设计

STM32单片机项目实例:基于TouchGFX的智能手表设计(7)MVP架构下的交互逻辑设计

目录

一、概述

二、MVP架构下的交互逻辑


一、概述

  本文例程是基于 TouchGFX 的智能手表设计—Designer 软件 UI 设计的例程 0B-2_STM32U575_MVP_Interactive工程的拷贝,用于MVP架构下的逻辑代码添加。

二、MVP架构下的交互逻辑

  将资料光盘中的0B-2_STM32U575_MVP_Interactive例程拷贝至工程目录,并将文件夹重命名为0B-3_STM32U575_MVP_Interactive,打开…\0B-3_STM32U575_MVP_Interactive\TouchGFX 下的0B-2_STM32U575_MVP_Interactive.touchgfx,点击DialPage,在Interactions增加GoToAPP的硬件交互,用于表盘页面与APP页面的切换(硬件按键触发)。

  点击ApplicationPage,在Interactions增加GoToDial的硬件交互,用于APP页面与表盘页面的切换(硬件按键触发)。

点击右下角的</>.生成代码,打开MDK工程,进行工程的全编译。

  点击工程管理目录下的gui,打开MenuElement.cpp与MenuElement.hpp,在MenuElement.hpp中添加Scroll Wheel的相关函数声明。

#ifndef MENUELEMENT_HPP
#define MENUELEMENT_HPP
//
#include <gui_generated/containers/MenuElementBase.hpp>
#include <BitmapDatabase.hpp>
#include <math.h>
//
class MenuElement : public MenuElementBase
{
public:MenuElement();virtual ~MenuElement() {}//virtual void initialize();int8_t number;			void offset(int16_t x);virtual void setY(int16_t y);void setNumber(int no);	
protected://声明点击事件回调函数Callback<MenuElement, const touchgfx::ScalableImage & , const touchgfx::ClickEvent &> imageClickHandler;//声明点击事件处理函数void image_click_handler(const touchgfx::ScalableImage &image , const touchgfx::ClickEvent &event);
};
#endif // MENUELEMENT_HPP

在MenuElement.cpp文件中增加以下代码:

#include <gui/containers/MenuElement.hpp>MenuElement::MenuElement():imageClickHandler(this,&MenuElement::image_click_handler)
{}
//
void MenuElement::initialize()
{MenuElementBase::initialize();
}
//重新设置组件的x轴位置
void MenuElement::offset(int16_t x)
{//设置图标位置icon.moveTo(20 + x, icon.getY());//设置文本位置,文本跟随图标移动text.moveTo(43 + icon.getX(), 5 + icon.getY());	
}
//点击图标后触发事件
void MenuElement::image_click_handler(const touchgfx::ScalableImage &image , const touchgfx::ClickEvent &event)
{touchgfx::ClickEvent::ClickEventType type = event.getType();if(type==touchgfx::ClickEvent::ClickEventType::PRESSED){if(&image == &icon){switch(number % 7){case 0:		//健康监测事件触发,健康监测图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_HEALTH_ID));icon.invalidate();//break;case 1:		//姿态读取事件触发,姿态读取图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_6050_ID));icon.invalidate();//
break;case 2:		//事件触发,环境信息图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_TEMP_ID));icon.invalidate();//break;case 3:		//芯片信息事件触发,芯片信息图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_CHIP_ID));icon.invalidate();//break;case 4:		//振动控制事件触发,振动控制图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_BUZZER_ID));icon.invalidate();//break;case 5:		//电池电量事件触发,电池电量图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_BATTERY_ID));icon.invalidate();//break;case 6:		//无线连接事件触发,无线连接图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_PRESSED_WIFI_ID));icon.invalidate();//break;}}}
}
//
void MenuElement::setY(int16_t y)
{MenuElementBase::setY(y);//设定圆弧的半径,表盘直径-图标半径const int circleRadius = 210;
//获取Y轴坐标信息	y = y + getHeight()/2 - 240 / 2;//勾股定理计算X轴位置float x_f = circleRadius - sqrtf(abs((float)(circleRadius * circleRadius) - (y * y)));//重新设置组件的x轴位置offset((int16_t)(x_f));
}
//对const的buf指针做强转去掉const
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
//设置图标与文本
void MenuElement::setNumber(int no)
{icon.setClickAction(imageClickHandler);//修改图标switch(no % 7){case 0:		//无触发事件时,健康监测图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_HEALTH_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, (Unicode::UnicodeChar*)L"健康监测");break;case 1:		//无触发事件时,姿态读取图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_6050_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, (Unicode::UnicodeChar*)L"姿态感知");break;case 2:		//无触发事件时,环境信息图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_TEMP_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, (Unicode::UnicodeChar*)L"环境信息");break;case 3:		//无触发事件时,芯片信息图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_CHIPINFO_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, (Unicode::UnicodeChar*)L"芯片信息");break;case 4:		//无触发事件时,振动控制图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_BUZZER_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, 
(Unicode::UnicodeChar*)L"外部控制");break;case 5:		//无触发事件时,电池电量图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_BATTERY_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, (Unicode::UnicodeChar*)L"电池电量");break;case 6:		//无触发事件时,无线连接图标与文字icon.setBitmap(touchgfx::Bitmap(BITMAP_APPLICATIONPAGE_IMAGE_WIFI_ID));Unicode::snprintf(textBuffer, TEXT_SIZE, (Unicode::UnicodeChar*)L"无线连接");break;}number = no;
}
点击ApplicationPageView.cpp,打开ApplicationPageView.hpp文件,添加APP页面的图标滚动与字体更变。
#ifndef APPLICATIONPAGEVIEW_HPP
#define APPLICATIONPAGEVIEW_HPP#include <gui_generated/applicationpage_screen/ApplicationPageViewBase.hpp>
#include <gui/applicationpage_screen/ApplicationPagePresenter.hpp>class ApplicationPageView : public ApplicationPageViewBase
{
public:ApplicationPageView();virtual ~ApplicationPageView() {}virtual void setupScreen();virtual void tearDownScreen();//实现APP页面的滚动图标与文字更新virtual void AppScrollWheelUpdateItem(MenuElement& item,int16_t itemIndex){item.setNumber(itemIndex);}
protected:
};#endif // APPLICATIONPAGEVIEW_HPP

  点击MDK全编译,完成后,在Designer软件中设置ApplicationPage为启动窗口,点击右下角的仿真。

  也可以在MDK中进行开发板的下载,下载完成后,复位开发板。FS-STM32U5开发板屏幕的展示效果与PC端仿真相同。

开发板的显示效果

PC端Designer仿真效果

打开ApplicationPageView.cpp /ApplicationPageView.hppApplicationPagePresenter.cpp/ ApplicationPagePresenter.hpp / Model.cpp / Model.hpp/ModelListener.hpp文件,添加硬件按键的触发。

ApplicationPageView.cpp文件中添加页面的跳转。

#include <gui/applicationpage_screen/ApplicationPageView.hpp>//
ApplicationPageView::ApplicationPageView()
{}
//
void ApplicationPageView::setupScreen()
{ApplicationPageViewBase::setupScreen();
}
//
void ApplicationPageView::tearDownScreen()
{ApplicationPageViewBase::tearDownScreen();
}
//页面跳转
void ApplicationPageView::AppPageChange(uint8_t newFiveKeyFunc)
{handleKeyEvent(newFiveKeyFunc);
}

ApplicationPageView.hpp中添加函数声明

 

#ifndef APPLICATIONPAGEVIEW_HPP
#define APPLICATIONPAGEVIEW_HPP#include <gui_generated/applicationpage_screen/ApplicationPageViewBase.hpp>
#include <gui/applicationpage_screen/ApplicationPagePresenter.hpp>class ApplicationPageView : public ApplicationPageViewBase
{
public:ApplicationPageView();virtual ~ApplicationPageView() {}virtual void setupScreen();virtual void tearDownScreen();//页面跳转void AppPageChange(uint8_t newFiveKeyFunc);//实现APP页面的滚动图标与文字更新virtual void AppScrollWheelUpdateItem(MenuElement& item,int16_t itemIndex){item.setNumber(itemIndex);}
protected:};#endif // APPLICATIONPAGEVIEW_HPP

ApplicationPagePresenter.cpp文件中添加APP页面任务使能与页面切换代码。

#include <gui/applicationpage_screen/ApplicationPageView.hpp>
#include <gui/applicationpage_screen/ApplicationPagePresenter.hpp>ApplicationPagePresenter::ApplicationPagePresenter(ApplicationPageView& v): view(v)
{}
//
void ApplicationPagePresenter::activate()
{ApplicationPagePresenterState(true);	
}
//
void ApplicationPagePresenter::deactivate()
{ApplicationPagePresenterState(false);	
}
//ApplicationPagePresenter状态
void ApplicationPagePresenter::ApplicationPagePresenterState(bool enable)
{if(enable == true)model->ApplicationPageViewTask(true);elsemodel->ApplicationPageViewTask(false);
}
//页面跳转
void ApplicationPagePresenter::AppPageChange(uint8_t newFiveKeyFunc)
{view.AppPageChange(newFiveKeyFunc);	
}

ApplicationPagePresenter.hpp文件中添加函数声明。

#ifndef APPLICATIONPAGEPRESENTER_HPP
#define APPLICATIONPAGEPRESENTER_HPP#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>using namespace touchgfx;class ApplicationPageView;class ApplicationPagePresenter : public touchgfx::Presenter, public ModelListener
{
public:ApplicationPagePresenter(ApplicationPageView& 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 ~ApplicationPagePresenter() {};//ApplicationPagePresenter状态void ApplicationPagePresenterState(bool enable);//页面跳转	virtual void AppPageChange(uint8_t newFiveKeyFunc);
private:ApplicationPagePresenter();ApplicationPageView& view;
};
#endif // APPLICATIONPAGEPRESENTER_HPP

Model.cpp中添加与底层驱动的相关获取与控制代码。

#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>#if defined LINK_HARDWARE 	//TuchGFX仿真与实际硬件操作隔离//头文件包含extern "C"{#include "user_app.h"}//底层数据extern volatile SHT20_TemRH_Val gTemRH_Val;extern RTC_DateTypeDef gSystemDate;  //获取日期结构体extern RTC_TimeTypeDef gSystemTime;   //获取时间结构体extern gTask_BitDef gTaskStateBit;  //任务执行过程中使用到的标志位extern gTask_MarkEN gTaskEnMark;  //系统任务使能标识extern volatile StruAP3216C_Val gAP3216C_Val;	//AP3216数据结构extern volatile uint8_t gLastTimeSeconds;	//上一次的时间extern volatile float pitch,roll,yaw; //欧拉角extern unsigned long gSportStep;	//运动步数extern wifiRSSI ao_wifiRSSI;extern uint8_t gFiveKeyFunc;	//定义的五向按键值功能	extern volatile uint16_t gCurrentVal;	//资源扩展板电流,通道IN8   extern volatile uint16_t gVoltageVal;	//资源扩展板电压,通道IN9  extern volatile uint16_t gChipTempVal;//内部参考电压,通道IN12  extern volatile uint16_t gVrefVal;		//内部参考电压,通道IN13   	extern volatile uint16_t gVbatVal;		//RTC电池电压,通道IN14  extern int32_t n_heart_rate;   //heart rate value=n_heart_rate/4,采样率100sps,max30102设置4点求平均extern int32_t n_sp02; //SPO2 valueextern int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is validextern int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is validextern uint8_t gWiFiInfo[40];	//用于通知View界面的Text文本显示//volatile uint8_t gSwitchSpace = 0x00;	//页面切换的时间间隙static int32_t gHeartRate = 0;  //表盘页面的心率数据
#else //Designer仿真#include <ctime>#ifndef _MSC_VER#include <sys/time.h>
#endif /* _MSC_VER*///volatile uint8_t gBacklightVal = 50;	//背光值,默认50%
#endif
/**********************************TouchGFX与底层间的访问**********************************/
Model::Model() : modelListener(0)
{}
//
void Model::tick()
{static uint8_t tickCount = 0;	//减少数据上传的次数,优化界面刷新tickCount++;	#if defined LINK_HARDWARE//if(gSwitchSpace != 0) gSwitchSpace--;	/********************************硬件页面切换*********************************///表盘页面if(gTaskEnMark.UPDATE_DIAL_EN && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace))	{modelListener->DialPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}//应用页面if(gTaskEnMark.UPDATE_APPPAGE && (gTaskStateBit.TouchPress == 0) && (!gSwitchSpace)){modelListener->AppPageChange(gFiveKeyFunc);gSwitchSpace = 0x0F;	//使能切换时间计数}/********************************更新各类信息*********************************///更新时间信息,为使表盘页面滑动操作正常,在屏幕被点按时不更新数据if(gTaskEnMark.UPDATE_DIAL_EN && (gSystemTime.Seconds != gLastTimeSeconds)&&(gTaskStateBit.TouchPress == 0))	//每秒同步一次界面时间{modelListener->updateDate(gSystemDate.Year,gSystemDate.Month,gSystemDate.Date,gSystemDate.WeekDay);modelListener->updateTime(gSystemTime.Hours, gSystemTime.Minutes,
gSystemTime.Seconds);//更新新值gLastTimeSeconds = gSystemTime.Seconds;	//更新温度/步数/心率modelListener->updateTempStepHeart(gTemRH_Val.Tem,gSportStep,gHeartRate);}
#else //Designer仿真timeval timenow;gettimeofday(&timenow, NULL);//仿真更新时间modelListener->updateTime((timenow.tv_sec / 60 / 60) % 24,(timenow.tv_sec / 60) % 60,timenow.tv_sec % 60);
#endif	
}
/*********************gTaskEnMark赋值*************************/
//DialView的任务的状态
void Model::DialPageViewTask(bool enable)
{#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_DIAL_EN = 1;	//任务使能elsegTaskEnMark.UPDATE_DIAL_EN = 0;	//任务清除
#endif
}
//ApplicationPageView的任务的状态
void Model::ApplicationPageViewTask(bool enable)
{#if defined LINK_HARDWAREif(enable == true)	gTaskEnMark.UPDATE_APPPAGE = 1;	//任务使能elsegTaskEnMark.UPDATE_APPPAGE = 0;	//任务清除
#endif
} 

Model.hpp中添加相关函数的说明。

#ifndef MODEL_HPP
#define MODEL_HPPclass ModelListener;class Model
{
public:Model();void bind(ModelListener* listener){modelListener = listener;}void tick();//DialPageView的任务的状态void DialPageViewTask(bool enable);//ApplicationPageView的任务的状态void ApplicationPageViewTask(bool enable);protected:ModelListener* modelListener;
};#endif // MODEL_HPP

ModelListener.hpp中添加相关虚函数。

 

#ifndef MODELLISTENER_HPP
#define MODELLISTENER_HPP#include <gui/model/Model.hpp>
extern "C" {
#include "stdint.h"
}
class ModelListener
{
public:ModelListener() : model(0) {}virtual ~ModelListener() {}void bind(Model* m){model = m;}//更新日期和时间virtual void updateDate(uint8_t Year, uint8_t Month, uint8_t Date, uint8_t WeekDay) {}virtual void updateTime(uint8_t Hours, uint8_t Minutes, uint8_t Seconds) {}//页面跳转virtual void DialPageChange(uint8_t newFiveKeyFunc){}virtual void AppPageChange(uint8_t newFiveKeyFunc){}//温度/步数/心率上传virtual void updateTempStepHeart(float newTem, unsigned long newStep, uint32_t newHeartRate){}
protected:Model* model;
};#endif // MODELLISTENER_HPP

  点击魔术棒图标,在C/C++选项卡增加LINK_HARDWARE的宏定义,用于PC端仿真与硬件底层驱动的隔离。

打开DialPageView.cpp / DialPageView.hppDialPagePresenter.cpp/ DialPagePresenter.hpp文件,添加手表界面的信息上传代码。

DialPageView.cpp文件中添加数字表盘与模拟表盘的数据更新代码。

 

#include <gui/dialpage_screen/DialPageView.hpp>
#include <texts/TextKeysAndLanguages.hpp>
#include "BitmapDatabase.hpp"
//标准库
#include <stdio.h>
#include <string.h>
//
DialPageView::DialPageView()
{}
//
void DialPageView::setupScreen()
{DialPageViewBase::setupScreen();
}
//
void DialPageView::tearDownScreen()
{DialPageViewBase::tearDownScreen();
}
//更新时间
void DialPageView::updateTime(uint8_t newHours, uint8_t newMinutes, uint8_t newSeconds)
{digitalClock.setTime24Hour(newHours, newMinutes, newSeconds);analogClock.setTime24Hour(newHours,newMinutes,newSeconds);
}
//更新日期
void DialPageView::updateDate(uint8_t newYear, uint8_t newMonth, uint8_t newDate, uint8_t newWeekDay)
{Unicode::snprintf(textSystemYearBuffer, TEXTSYSTEMYEAR_SIZE, "%04d", newYear + 2000);textSystemYear.invalidate();	//Unicode::snprintf(textSystemDateBuffer1, TEXTSYSTEMDATEBUFFER1_SIZE, "%02d", newMonth);Unicode::snprintf(textSystemDateBuffer2, TEXTSYSTEMDATEBUFFER2_SIZE, "%02d", newDate);textSystemDate.invalidate();//Unicode::snprintf(textWeekDayBuffer, TEXTWEEKDAY_SIZE, "%d", newWeekDay);textWeekDay.invalidate();//Unicode::snprintf(DateWindowBuffer, DATEWINDOW_SIZE, "%02d", newDate);DateWindow.invalidate();	//
}
//进入APP页面或快速设置界面
void DialPageView::DialPageChange(uint8_t newFiveKeyFunc)
{handleKeyEvent(newFiveKeyFunc);
}
//更新温度、步数、心率数据
void DialPageView::updateTempStepHeart(float newTem, unsigned long newStep, uint32_t newHeartRate)
{//更新温度-数字表盘Unicode::snprintfFloat(textTempBuffer, TEXTTEMP_SIZE, "%.1f",newTem);textTemp.invalidate();//更新温度-模拟表盘Unicode::snprintfFloat(textTemp_anBuffer, TEXTTEMP_AN_SIZE, "%.1f",newTem);textTemp_an.invalidate();//更新步数-数字表盘Unicode::snprintf(textStepBuffer, TEXTSTEP_SIZE, "%d",newStep);textStep.invalidate();//更新步数-模拟表盘Unicode::snprintf(textStep_anBuffer, TEXTSTEP_AN_SIZE, "%d",newStep);textStep_an.invalidate();//更新脉搏-数字表盘Unicode::snprintf(textPulseBuffer, TEXTPULSE_SIZE, "%d",newHeartRate);textPulse.invalidate();//更新脉搏-模拟表盘Unicode::snprintf(textPulse_anBuffer, TEXTPULSE_AN_SIZE, "%d",newHeartRate);textPulse_an.invalidate();	
}

DialPageView.hpp文件中添加声明。

#ifndef DIALPAGEVIEW_HPP
#define DIALPAGEVIEW_HPP#include <gui_generated/dialpage_screen/DialPageViewBase.hpp>
#include <gui/dialpage_screen/DialPagePresenter.hpp>class DialPageView : public DialPageViewBase
{
public:DialPageView();virtual ~DialPageView() {}virtual void setupScreen();virtual void tearDownScreen();//更新日期和时间virtual void updateDate(uint8_t newYear, uint8_t newMonth, uint8_t newDate, uint8_t newWeekDay); virtual void updateTime(uint8_t newHours, uint8_t newMinutes, uint8_t newSeconds);virtual void DialPageChange(uint8_t newFiveKeyFunc);//温度/步数/心率信息上传void updateTempStepHeart(float newTem, unsigned long newStep, uint32_t newHeartRate);
protected:
};#endif // DIALPAGEVIEW_HPP

DialPagePresenter.cpp添加屏幕任务的使能与数据交互。

#include <gui/dialpage_screen/DialPageView.hpp>
#include <gui/dialpage_screen/DialPagePresenter.hpp>
//
DialPagePresenter::DialPagePresenter(DialPageView& v): view(v)
{
}
//
void DialPagePresenter::activate()
{DialPagePresenterState(true);
}
//
void DialPagePresenter::deactivate()
{DialPagePresenterState(false);
}
//DialPagePresenter
void DialPagePresenter::DialPagePresenterState(bool enable)
{if(enable == true)model->DialPageViewTask(true);elsemodel->DialPageViewTask(false);
}
//更新时间
void DialPagePresenter::updateTime(uint8_t newHours, uint8_t newMinutes, uint8_t newSeconds)
{view.updateTime(newHours, newMinutes, newSeconds);
}
//更新日期
void DialPagePresenter::updateDate(uint8_t newYear, uint8_t newMonth, uint8_t newDate, uint8_t newWeekDay)
{view.updateDate(newYear, newMonth, newDate, newWeekDay);
}
//五向按键切换页面
void DialPagePresenter::DialPageChange(uint8_t newFiveKeyFunc)
{view.DialPageChange(newFiveKeyFunc);
}
//更新温度/步数/心率
void DialPagePresenter::updateTempStepHeart(float newTem, unsigned long newStep, uint32_t newHeartRate)
{view.updateTempStepHeart(newTem,newStep,newHeartRate);	
}

DialPagePresenter.hpp添加以下代码。

#ifndef DIALPAGEPRESENTER_HPP
#define DIALPAGEPRESENTER_HPP
#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>using namespace touchgfx;class DialPageView;class DialPagePresenter : public touchgfx::Presenter, public ModelListener
{
public:DialPagePresenter(DialPageView& 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 ~DialPagePresenter() {};//DialPagePresenter的状态void DialPagePresenterState(bool enable);//更新日期和时间virtual void updateDate(uint8_t newYear, uint8_t newMonth, uint8_t newDate, uint8_t newWeekDay); virtual void updateTime(uint8_t newHours, uint8_t newMinutes, uint8_t newSeconds);virtual void DialPageChange(uint8_t newFiveKeyFunc);//更新温度/步数/心率virtual void updateTempStepHeart(float newTem, unsigned long newStep, uint32_t newHeartRate);
private:DialPagePresenter();DialPageView& view;
};#endif // DIALPAGEPRESENTER_HPP

 点击全编译,运行PC端的仿真,下载至开发板,进行代码的验证。

PC端的仿真结果。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/298602.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postman接口测试(超详细整理)

常用的接口测试工具主要有以下几种 Postman&#xff1a;简单方便的接口调试工具&#xff0c;便于分享和协作。具有接口调试&#xff0c;接口集管理&#xff0c;环境配置&#xff0c;参数化&#xff0c;断言&#xff0c;批量执行&#xff0c;录制接口&#xff0c;Mock Server, …

国际会议口译,选择同传好还是交传好

在国际会议中&#xff0c;同传与交传是常见的两种翻译方式&#xff0c;它们各自承载着独特的使命与优势&#xff0c;为沟通世界发挥着不可替代的作用。那么&#xff0c;同传好还是交传好&#xff0c;如何选择合适的翻译方式&#xff1f; 首先&#xff0c;从费用角度来看&#x…

基于JAVA的校园电商物流云平台 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快递公司模块2.4 物流订单模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 商品表3.2.2 快递公司表3.2.3 物流订单表 四、系统展示五、核心代码5.1 查询商品5.2 查询快递公司5.3 查…

通达OA header身份认证绕过漏洞复现

通达OA是中国通达公司的一套协同办公自动化软件&#xff0c;通达OA2013&#xff0c;通达OA2016&#xff0c;通达OA2017 存在身份认证绕过漏洞&#xff0c;攻击者可以利用漏洞生成cookie&#xff0c;实现未授权访问。 1.漏洞级别 高危 2.漏洞搜索 fofa title"office An…

Linux之基础I/O

目录 一、C语言中的文件操作 二、系统文件操作I/O 三、文件描述符fd 1、文件描述符的引入 2、对fd的理解 3、文件描述符的分配规则 四、重定向 1、重定向的原理 2、重定向的系统调用dup2 五、Linux下一切皆文件 一、C语言中的文件操作 1、打开和关闭 在C语言的文…

递归如何书写?

目录 第一步&#xff1a;首先你分析问题&#xff0c;要有递归的思路&#xff0c;知道要递归什么来解决问题。 第二步&#xff1a;先按照思路&#xff08;第一层&#xff09;写出函数的定义与函数体 第三步&#xff1a;根据函数的定义与函数体进一步确定需要的参数 第四步&a…

基于ssm出租车管理系统的设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本出租车管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

Matlab仿真2ASK/OOK、2FSK、2PSK、QPSK、4QAM在加性高斯白噪声信道中的误码率与归一化信噪比的关系

本文为学习所用&#xff0c;严禁转载。 本文参考链接 https://zhuanlan.zhihu.com/p/667382398 QPSK代码及高斯白噪声如何产生 https://ww2.mathworks.cn/help/signal/ref/butter.html 滤波器 https://www.python100.com/html/4LEF79KQK398.html 低通滤波器 本实验使用matlab仿…

SparkSQL 执行底层原理解析

从Spark SQL 底层架构可以看到&#xff0c;我们写的SQL语句&#xff0c;经过一个优化器&#xff08;Catalyst&#xff09;处理&#xff0c;转化为可执行的RDD&#xff0c;提交给集群执行。 SQL到RDD中间经过了一个Catalyst&#xff0c;它便是Spark SQL的核心&#xff0c;是针对…

伙伴计划|“团团活力圈”--青少年心理游戏拓展活动— 不倒森林

开学的欢声笑语犹在耳畔&#xff0c;转眼间学期已即将过半&#xff0c;眼下期中考试将要来临&#xff0c;部分青少年处在紧张焦虑的状态之中&#xff0c;为了帮助辖区青少年们释放内心压力、建立积极心态、培养抗挫能力&#xff0c;同时提升青少年的团队意识、增强凝聚力&#…

postman的下载安装和使用

第一章、使用postman向后端发送请求 1.2&#xff09;postman下载与安装使用 我的百度网盘postman点击下载 提取码&#xff1a;bybp 下载后双击.exe文件直接安装 点击此次创建集合 点击此处创建请求 1.2&#xff09;发送get请求 选择自己的请求方式&#xff0c;输入请求…

移动开发git版本控制经验之谈

移动开发git版本控制经验之谈 团队或应用规模是否会影响发布流程&#xff1f;这取决于具体情况。让我们来想象一下一个小型团队的创业公司。在这种情况下&#xff0c;通常是团队开发一个功能&#xff0c;然后直接发布。现在我们再来想象一个大型项目&#xff0c;比如一个银行应…