0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

怎样使用LVGL中的timer对象显示动画呢?

冬至子 来源:安德鲁的设计笔记本 作者:安德鲁 2023-08-22 11:24 次阅读

引言

设计GUI的显示元素动起来,实际上是多张图按照一定的节奏和变化依次刷屏实现的。LVGL在内核设计了timer对象,用于实现周期回调的功能,开发者可以在周期调用的回调函数中,修改GUI显示内容的属性,触发LVGL显示内容的刷新,然后由LVGL的例行执行程序重新刷屏,从而实现动画效果。

LVGL中的timer对象

LVGL的后台是通过时间片轮询对LVGL的交互任务进行调度的。

在具体的MCU平台上适配LVGL时,通常会使用SysTick定时器中断服务程序调用lv_tick_inc()函数驱动LVGL内部的计数器递增,然后在主线程中调用lv_timer_handler()函数以时间片为节点执行LVGL的日常任务(输入事件、刷屏等操作)。从源码上看,整个LVGL的程序框架,就是建立在定时器刻度的轮询调度之上的,可见包含LVGL的MCU工程的顶级业务逻辑代码如下:

lv_ui guider_ui;  
  
int main(void)  
{  
    BOARD_Init();  
    SysTick_Config(CLOCK_SYS_FREQ / 100); /* 10ms. */  
  
    lv_init();  
    lv_port_disp_init();  
    setup_ui(&guider_ui);  
    events_init(&guider_ui);  
    custom_init(&guider_ui);  
  
    while (1)  
    {  
        lv_timer_handler(); /* 执行LVGL时间片轮询. */  
    }  
}  
  
void SysTick_Handler(void)  
{  
    lv_tick_inc(10); /* 驱动LVGL的定时器. */  
}

在LVGL中,当需要实现一些基于时间变化显示内容的效果(动画),可以借用LVGL内部的定时器对象来实现周期执行程序的效果。关于LVGL应用程序中使用定时器的API主要有两个:

  • lv_timer_create()
  • lv_timer_del()

其中,使用lv_timer_create()函数创建一个定时器实例,并会向其中传送初始化参数,指定本定时器的触发周期触发时执行的回调函数。而lv_timer_del()函数会回收这个定时器的资源(包括变量,以及挂在定时器任务列表中的指针),以减轻LVGL后台调度器的负担。

基于timer对象实现仪表走针

这里以设计一个速度表盘指针转动的样例,展示timer定时器对象的用法。实现原理,在定时器组件的回调函数中,会周期性地改变meter组件中speed_scale_1_ndline_0属性的值。当改变LVGL显示组件的任何可视化组件的属性后,LVGL会自动刷新显示内容,从而形成动画效果。

在GUI Guider的编辑页面中新建一个meter组件的对象,如图x所示。

image.png

图x 在GUI Guider中新建meter对象

将新建meter对象改名为meter_speed,这个名字将会在后面自定义编写代码时,用于引用这个meter对象实例。手工调整一下表盘的尺寸。

然后,选中主编辑区的页面区域(对应选中当前的screen对象),再在编辑区域的右侧,在事件(Events)页面中,单击加号,创建一个事件,编辑事件。

编辑事件的触发方式,即在什么时机产生当前编辑的事件,常见的事件触发方式有:Load Start(开始载入当前对象时)、Loaded(完成载入当前对象时)、Unload Start(开始从本对象切换到别处时)、Unloaded(完成从本对象切换到别处时)等,如图x所示。每种显示元素的对象都有各自的触发方式,甚至还有一些显示元素的对象没有触发事件可创建。

image.png

图x 在GUI Guider中为事件编辑触发方式

选定Trigger触发方式后,还需要选定Target目标对象。此时,目标对象的下拉列表中会自动整理出当前整个GUI Guider工程中已经创建的有所显示元素对象。如图x所示。

image.png

图x 在GUI Guider中为事件编辑目标对象

这里需要重点说明的是,触发方式描述的当前在编辑区域中选中的对象的动作,当选定触发方式后,本事件的标签名称也就自动改成了<当前对象名>_<触发方式>。目标对象反映的是即将改变属性的对象,对应部分可选的属性也在事件页面下方展示出来,可在图形页面中配置。当然,并不是所有的可编辑属性都被做成了在对话框中可配置的,本例就在最后一行,选择了执行自定义程序,在弹出的代码编辑对话框中添加了创建定时器对象timer_meter_speed的语句。如图x所示。

image.png

图x 在GUI Guider中为事件编辑自定义执行的程序代码

图x中所示,自定义编写C源码,当触发Screen的Loaded事件时,将执行图中代码,创建timer_meter_speed定时器对象实例。保存工程后生成代码,对应地,可在GUI Guider工程中的./generated/event_init.c文件中看到对应生成的代码。

#include "events_init.h"  
#include < stdio.h >  
#include "lvgl.h"  
#include "custom.h"  
  
static lv_timer_t * timer_meter_speed;  
  
void events_init(lv_ui *ui)  
{  
}  
  
static void screen_event_handler(lv_event_t *e)  
{  
 lv_event_code_t code = lv_event_get_code(e);  
 switch (code)  
 {  
 case LV_EVENT_SCREEN_LOADED:  
 {  
  timer_meter_speed = lv_timer_create(timer_meter_speed_cb, 100, &guider_ui);  
 }  
  break;  
 case LV_EVENT_SCREEN_UNLOADED:  
 {  
  lv_timer_del(timer_meter_speed);  
 }  
  break;  
 default:  
  break;  
 }  
}  
  
void events_init_screen(lv_ui *ui)  
{  
 lv_obj_add_event_cb(ui- >screen, screen_event_handler, LV_EVENT_ALL, ui);  
}

但是回调函数timer_meter_speed_cb()仍需要开发者自行在custom.c文件中自行创建,GUI Guider不会自动更新。代码如下:

static int32_t speed = 50;  
static bool is_increase = true;  
  
  
/**  
 * Create a demo application  
 */  
  
void custom_init(lv_ui *ui)  
{  
    /* Add your codes here */  
}  
  
void timer_meter_speed_cb(lv_timer_t *t)  
{  
    lv_ui * gui = t- >user_data;  
    lv_meter_set_indicator_value(gui- >screen_meter_speed, gui- >screen_meter_speed_scale_1_ndline_0, speed);  
  
    if (speed >= 90)  
    {  
        is_increase = false;  
    }  
    if (speed <= 20)  
    {  
        is_increase = true;  
    }  
    if (is_increase)  
    {  
        speed++;  
    }  
    else  
    {  
        speed--;  
    }  
}

这里实现的内容是,在MCU上运行LVGL时,一旦显示完成当前的屏幕页面后,立即创建定时器对象timer_meter_speed,这个定时器将会每隔100ms调用一次回调函数timer_meter_speed_cb(),在timer_meter_speed_cb()函数中,更新变量speed的值,然后通过lv_meter_set_indicator_value()函数,改变screen_meter_speed对象中screen_meter_speed_scale_1_ndline_0属性的值。每隔100ms改变一次screen_meter_speed对象的属性值,将会触发显示内容的刷新,从而在显示屏上显现出动画效果。

将GUI Guider生成的程序下载到MCU之前,可以先在GUI Guider的工程中模拟运行一次,一方面可以帮忙排除编译错误(GUI Guider使用armgcc将LVGL和生成的源码一起编译),另一方面也方便预览运行效果。使用LVGL组件的过程不涉及到对具体MCU硬件的依赖,因此完全可以在模拟环境中预览实际执行的效果。如图x所示。

640.gif

图x 预览在GUI Guider中创建的表盘对象

最后,编译Keil工程,下载到MCU开发板。可以看到在MCU开发板上运行动图的效果,如图x所示。

640 (1).gif

图x 在MCU开发板上运行转动指针的表盘

小结

timer对象本身只是一个实现周期调度的机制,开发者可以在周期回调的函数内部,修改和重置显示各种对象的属性,触发LVGL刷屏,从而实现动画的效果。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计数器
    +关注

    关注

    32

    文章

    2126

    浏览量

    92997
  • 定时器
    +关注

    关注

    23

    文章

    3148

    浏览量

    112051
  • GUI
    GUI
    +关注

    关注

    3

    文章

    611

    浏览量

    38801
  • 调度器
    +关注

    关注

    0

    文章

    95

    浏览量

    5161
  • LVGL
    +关注

    关注

    0

    文章

    75

    浏览量

    2409
收藏 人收藏

    评论

    相关推荐

    为全志D1开发板移植LVGL日历控件和显示天气

    main.c cJSON.c -o weather -lm”。因为cJSON会用到math库,而它需要“-lm”来动态链接。 lvgl显示图片和本地时间 1、lvgl的图片显示
    发表于 02-21 09:59

    关于winCE 开发OSD显示动画问题

    winCE OSD显示开机动画,每张图都需要存3个BYTE的内存,我们显示的时候读取地址就开始显示一张图,直到读完一幅图的最后一个BYTE
    发表于 09-10 09:25

    怎样去设置STM32F0 Timer1为PWM模式

    怎样去设置STM32F0 Timer1为PWM模式?其程序是怎样的?
    发表于 10-21 07:30

    LVGL工具使用

    文章所有资料以及代码下载途径LVGL工具使用:主要介绍下模拟器的使用/电脑组态软件(我通常把电脑拖控件软件叫做组态软件)LVGL概念概述:主要对LVGL对象/事件/风格/输入设备/
    发表于 12-15 07:17

    请问一下ESP8266播放动画的设计该怎样去实现

    请问一下ESP8266播放动画的设计该怎样去实现
    发表于 01-21 06:25

    怎样去使用NY8B072A单片机的TIMER定时器

    怎样去使用NY8B072A单片机的TIMER定时器?其代码程序该怎样去编写
    发表于 01-21 06:50

    RK3288显示LOGO过后没有动画会是什么原因造成的

    RK3288显示LOGO过后没有动画会是什么原因造成的怎样去解决
    发表于 03-03 11:29

    RK3288系统的开机动画时间该怎样去延长

    RK3288系统的开机动画时间该怎样去延长?有何解决方法?
    发表于 03-10 08:37

    开源轻量级显示框架LVGL简介

    启动嵌入式GUI设计,同时LVGL作为一个图形库,它自带着接近三十多种小工具可以供开发者使用。这些强大的构建块按钮搭配上带有非常丝滑的动画以及可以做到平滑滚动的高级图形,同时兼具着不高的配置要求以及
    发表于 03-14 09:28

    开源轻量级显示框架LVGL简介

    启动嵌入式GUI设计,同时LVGL作为一个图形库,它自带着接近三十多种小工具可以供开发者使用。这些强大的构建块按钮搭配上带有非常丝滑的动画以及可以做到平滑滚动的高级图形,同时兼具着不高的配置要求以及
    发表于 03-31 18:49

    AT32F437基于LVGL的桌面显示案例

    AT32F437基于LVGL的桌面显示案例示例目的提供AT32F437基于LVGL V8的桌面显示案例。注:本示例代码是基于雅特力提供的V2.x.x板级支持包(BSP)而开发,对于其他
    发表于 11-23 19:40

    如何使用lvgl定时器实现动画效果

    LVGL,如何使用lvgl定时器实现动画效果
    发表于 12-15 15:23

    使用单片机实现TIMER0和TIMER1与TIMER2实现外部信号计数与显示的程序

    本文档的主要内容详细介绍的是使用单片机实现TIMER0和TIMER1与TIMER2实现外部信号计数与显示的C语言程序免费下载。
    发表于 03-26 16:42 26次下载

    简析LVGL基础知识之对象模块

    LVGL 中,用户界面的基本构建块是对象,也称为小部件(widget)。本文主要是介绍LVGL对象模块。
    的头像 发表于 06-11 10:47 5996次阅读
    简析<b class='flag-5'>LVGL</b>基础知识之<b class='flag-5'>对象</b>模块

    【RISC-V &amp;amp; LVGL】现象级爆红的开源显示框架——LVGL究竟蕴藏怎样的魔力

    #01LVGL简介实用自行车码表具有科技感的奖杯实现这些DIY作品的背后,都有同样一个功能强大的GUI——LVGLLVGL的作者是来自匈牙利的GaborKiss-Vamosikisvegabor
    的头像 发表于 03-15 09:50 2339次阅读
    【RISC-V &amp;amp; <b class='flag-5'>LVGL</b>】现象级爆红的开源<b class='flag-5'>显示</b>框架——<b class='flag-5'>LVGL</b>究竟蕴藏<b class='flag-5'>怎样</b>的魔力