LVGL_V8.3入门七---手表页面管理、任务调度(完结篇)

系列文章目录


前言

用过手环或者手表的朋友,手表页面切换主要有两种方式。第一种是利用触摸屏进行页面的切换,第二种是利用物理按键例如手表侧面的按钮。然后就会涉及到如何进行页面的管理,从一个页面如何切换到另外页面,如果我想要返回,返回到哪个页面。本文介绍如何利用栈的方式进行LVGL页面的管理以及利用FreeRTOS进行页面管理。

实验现象一:利用STM32F7开发板上面的物理按键实现从手表主页面切换到菜单页面,再次按下切换到主页面
在这里插入图片描述
实验现象二:利用触摸屏进行页面切换。FreeRTOS进行任务管理
在这里插入图片描述


一、如何利用按键进行页面切换

1、利用一个进程要不断的扫描按键检测按键是否按下。并且利用一个长度为1的队列进行保存按键值。需要注意的是KeyTask的任务阻塞时间要设置小一下因为按键检测时间间隔较短

//Key task
osThreadId_t KeyTaskHandle;
const osThreadAttr_t KeyTask_attributes = {
  .name = "KeyTask",
  .stack_size = 128 * 8,
  .priority = (osPriority_t) osPriorityNormal,
};

KeyTaskHandle 			 = osThreadNew(KeyTask, NULL, &KeyTask_attributes);
Key_MessageQueue  = osMessageQueueNew(1, 1, NULL);
void KeyTask(void *argument)
{
	uint8_t keystr=0;

	while(1)
	{
		switch(KeyScan())
		{
		    case 0:
		    	//printf("keyvalue=0\r\n");

		    	break;


			case 1:
				keystr = 1;
				osMessageQueuePut(Key_MessageQueue, &keystr, 0, 1);

				break;
		}

		osDelay(1);
	}
}

2、另外一个进程进行切面的切换。
读取队列的值。在裸机系统中,两个程序间需要共享某个资源通常使用全局变量来实现;但在含操作系统(下文就拿FreeRTOS举例)的开发中,则使用消息队列完成。在FreeRTOS系统中,引入了消息队列来实现某个资源共享,其不仅仅实现临界资源共享,也给临界资源提供保护,使得程序更加稳定。

//ScrRenew task
osThreadId_t ScrRenewTaskHandle;
const osThreadAttr_t ScrRenewTask_attributes = {
  .name = "ScrRenewTask",
  .stack_size = 128 * 8,
  .priority = (osPriority_t) osPriorityLow1,
};
ScrRenewTaskHandle   = osThreadNew(ScrRenewTask, NULL, &ScrRenewTask_attributes);

通过读取队列的值,检测如果按键按下则将当前的页面出栈,加载菜单页面然后将主页面和菜单页面id进行进栈。

void ScrRenewTask(void *argument)
{
	uint8_t keystr=0;
	user_Stack_Push(&ScrRenewStack,(long long int)&ui_HomePage);
	while(1)
	{
		if(osMessageQueueGet(Key_MessageQueue,&keystr,NULL,0)==osOK)
		{
			if(keystr == 1)
			{
				//
				user_Stack_Pop(&ScrRenewStack);
				//
				if(user_Stack_isEmpty(&ScrRenewStack))
				{

					ui_MenuPage_screen_init();
					lv_scr_load_anim(ui_MenuPage,LV_SCR_LOAD_ANIM_MOVE_RIGHT,0,0,true);
					user_Stack_Push(&ScrRenewStack,(long long int)&ui_HomePage);
					user_Stack_Push(&ScrRenewStack,(long long int)&ui_MenuPage);
				}
				else if(ScrRenewStack.Data[ScrRenewStack.Top_Point-1] == (long long int)&ui_HomePage)
				{
					ui_HomePage_screen_init();
					lv_scr_load_anim(ui_HomePage,LV_SCR_LOAD_ANIM_MOVE_RIGHT,0,0,true);
				}
				else if(ScrRenewStack.Data[ScrRenewStack.Top_Point-1] == (long long int)&ui_MenuPage)
				{
					ui_MenuPage_screen_init();
					lv_scr_load_anim(ui_MenuPage,LV_SCR_LOAD_ANIM_MOVE_RIGHT,0,0,true);
				}
			}
		osDelay(10);
	}
}

进栈、出栈、判断栈是否为空,清空栈,用于保存LVGL页面对象的ID

#include "PageStack.h"

uint8_t user_Stack_Push(user_Stack_T* stack, StackData_t datain)
{
  if(stack->Top_Point == MAX_DEPTH - 1)
	{return -1;}
	
	stack->Data[stack->Top_Point++] = datain;
	return 0;
}

uint8_t user_Stack_Pop(user_Stack_T* stack)
{
  if(stack->Top_Point == 0)
	{return -1;}
	
	stack->Data[--stack->Top_Point] = NULL;
	return 0;
}

uint8_t user_Stack_isEmpty(user_Stack_T* stack)
{
	if(stack->Top_Point == 0)
	{return 1;} 

	return 0;
}

void user_Stack_Clear(user_Stack_T* stack)
{
	while(!user_Stack_isEmpty(stack))
	{
		user_Stack_Pop(stack);
	}
}


二、FreeRTOS进行任务管理

举例说明,两个手表表盘通过两个进程进行管理。

SeaTimeTaskHandle   = osThreadNew(SeaTimeTask, NULL, &SeaTimeTask_attributes);
CirWatchTaskHandle   = osThreadNew(CirWatchTask, NULL, &CirWatchTask_attributes);

两个进程不断的进行扫描栈顶元素,如果栈顶元素是SeaTimeTask页面,则进行数据的更新。

void SeaTimeTask(void)
{
	while(1)
	{
		if(ScrRenewStack.Data[ScrRenewStack.Top_Point-1] == (long long int)&ui_Screen1)
		{
//			vTaskSuspendAll();
			 /* Get the RTC current Time */
			HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
		    /* Get the RTC current Date */
		    HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);


		    lv_img_set_angle(ui_Sea_secImage5, GetTime.Seconds * 60);//s秒表
		    lv_img_set_angle(ui_Sea_minImage4, GetTime.Minutes * 60);//m分钟
		    lv_img_set_angle(ui_Sea_hourImage3, GetTime.Hours * 300);//h时
//		    xTaskResumeAll();
		}
		osDelay(50);
	}

}

void CirWatchTask(void)
{
	uint8_t timeStr[10];
	uint8_t dataStr[10];
	while(1)
	{
		if(ScrRenewStack.Data[ScrRenewStack.Top_Point-1] == (long long int)&ui_Screen2)
		{
			  /* Get the RTC current Time */
			   	   HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
			       /* Get the RTC current Date */
			       HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
			//
			       sprintf(timeStr, "%02d:%02d:%02d", GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
			       lv_label_set_text(ui_Label1,timeStr);

			       sprintf(dataStr, "%02d/%02d", GetData.Month, GetData.Date);
			       lv_label_set_text(ui_Label7,dataStr);
		}
       osDelay(50);
	}
}


  • 13
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值