学习使用LVGL,依赖官方网址

LVGL Basics — LVGL documentation

LVGL基础知识

LVGL是一个开源的图形库,提供创建嵌入式GUI的一切

LVGL数据流

您为每个物理显示面板 创建一个显示器 (lv_display) ,在其上创建屏幕小部件,将小部件添加到这些屏幕上。要处理触摸、鼠标、键盘等,您需要 为每个屏幕创建一个输入设备。Tick接口告诉 LVGL 现在几点了。 计时器处理程序 驱动 LVGL 的计时器,而计时器又执行 LVGL 所有与时间相关的任务:

定期刷新显示,

读取输入设备,

火灾事件,

运行任何动画,并且

运行用户创建的计时器。

也就是 我们要在单片机的的RTC或者其他定时器去驱动LVGL的计时器吗?

freertos也有自己的软件定时器

应用程序的工作

初始化后,应用程序的工作仅仅是在需要时创建 Widget 树、管理这些 Widget 生成的事件(通过用户交互和其他方式)、并在不再需要它们时删除它们。LVGL 负责其余的工作。

这些组件生成的事件有我们来管理 

主要概念

显示器与屏幕

在我们详细了解 Widget 之前,让我们首先澄清一下您以后会经常看到的两个术语之间的区别:

显示器或显示面板是显示像素的物理硬件。

显示(lv_display)对象是 RAM 中的对象,代表供 LVGL 使用的显示。

屏幕是上面提到的 Widget 树中的“根”Widget,并且“附加到”特定的显示器(lv_display)。

不同组件存在不同的RAM中吗?

默认显示

当第一个Display (lv_display)对象被创建时,它将成为默认显示。许多与屏幕小部件相关的功能都使用默认显示。有关更多信息,请参阅默认显示

屏幕小部件

在本文档中,“屏幕小部件”一词经常缩写为“屏幕”。但重要的是要理解,“屏幕”只是任何 没有父级(每个小部件树的“根”)的小部件。

请参阅屏幕以了解更多详细信息。

活动屏幕

活动屏幕是当前正在显示的屏幕(及其子控件)。有关更多信息,请参阅活动屏幕。

小部件

初始化 LVGL 后(参见初始化 LVGL),为了创建交互式用户界面,应用程序接下来创建一个 Widget 树,LVGL 可将其渲染到相关显示器,并可与用户进行交互。

小部件是“智能” LVGL 图形元素,例如基本小部件(简单的矩形和屏幕)、按钮、标签、复选框、开关、滑块、图表等。转到小部件查看完整列表。

要构建此 Widget 树,应用程序首先获取指向 Screen Widget 的指针。系统设计人员可以自由使用通过 Display (lv_display)创建的默认 Screen 和/或创建自己的 Screen。要创建新的 Screen Widget,只需创建一个 Widget 并将 NULL 作为父参数传递即可。从技术上讲,这可以是任何类型的 Widget,但在大多数情况下,它是一个Base Widget。(用作 Screen 的另一种 Widget 类型的示例是Image (lv_image) Widget,用于为背景提供图像。)

然后,应用程序将 Widget 作为树中的子项添加到此屏幕。Widget 在创建时会自动作为子项添加到其父 Widget 中 — Widget 的父项作为第一个参数传递给创建 Widget 的函数。添加后,我们说父 Widget“包含”子 Widget。

任何 Widget 都可以包含其他 Widget。例如,如果您希望按钮包含文本,请创建一个标签 Widget 并将其作为子项添加到按钮。 

每个子 Widget 都成为其父 Widget 的“一部分”。由于以下关系:

当父Widget移动时,其子Widget也会随之移动

当父Widget被删除时,其子Widget也会随之删除;

子 Widget 仅在其父 Widget 的边界内可见;

子 Widget 在其父 Widget 边界之外的任何部分都会被剪裁(即不会渲染)。

也就是父组件会限定占用的RAM,子组件只是可以在父组件内部RAM进行覆盖吗?

除 Screen 为Active Screen外,可以随时创建和删除 Screen(及其子小部件)。如果要在加载新 Screen 时删除当前 Screen,请调用lv_screen_load_anim()并传递true参数 auto_del。如果要在加载新 Screen 时将当前 Screen 保留在 RAM 中,请传递false参数auto_del或调用 lv_screen_active()以加载新 Screen。

系统设计人员可以自由地在 RAM 中保留任意数量的屏幕(及其子窗口小部件)(例如,以便稍后快速重新显示)。这样做:需要更多 RAM,但是可以节省重复创建Screen及其子Widget的时间

当屏幕很复杂和/或可以频繁地设为活动屏幕时,它会很方便。

如果在 RAM 中同时维护多个屏幕,则如何管理它们由系统设计人员决定。

只要RAM足够大就可以说实现把所有的屏幕都装下,刷新逻辑就是将缓冲区更换为不同RAM就行了吗?

创建小部件

通过调用如下函数来创建小部件

lv_<type>_create(parent)

该调用将返回一个指针,稍后可用于引用 Widget 来设置其属性。lv_obj_t *

例如:创建一个滑块

lv_obj_t * slider1 = lv_slider_create(lv_screen_active());

修改小部件

所有小部件共有的属性由如下函数设置:

lv_obj_set_<attribute_name>(widget, <value>)

例如:

横坐标设置为 30。这决定了 slider1 在其父容器中的水平位置

纵坐标设置为 10。这决定了 slider1 在其父容器中的垂直位置

将 slider1 的宽度设置为 200,高度设置为 50。这决定了 slider1 的大小尺寸

lv_obj_set_x(slider1, 30);
lv_obj_set_y(slider1, 10);
lv_obj_set_size(slider1, 200, 50);

除了这些属性之外,小部件还可以具有特定于类型的属性,这些属性由如下函数设置:

lv_<type>_set_<attribute_name>(widget, <value>)

例如:

lv_slider_set_value(slider1, 70, LV_ANIM_ON);

要查看完整的 API,请访问Widgets下相关 Widget 的文档 ,或研究源代码中的相关头文件,例如

lvgl/src/widgets/slider/lv_slider.h at master · lvgl/lvgl · GitHub

删除小部件

要删除任何小部件及其子部件:

lv_obj_delete(lv_obj_t * widget)

活动

事件用于通知应用程序某个 Widget 发生了某些事情。您可以为某个 Widget 分配一个或多个回调,这些回调将在 Widget 被点击、释放、拖动、删除等操作时调用。

回调分配如下:

lv_obj_add_event_cb(btn, my_btn_event_cb, LV_EVENT_CLICKED, NULL);...void my_btn_event_cb(lv_event_t * e)
{printf("Clicked\n");
}

LV_EVENT_ALL可以用来代替LV_EVENT_CLICKED 调用所有事件的回调。(注意:事件数量非常多!这对于调试或了解给定 Widget 发生的事件非常方便,或者如果应用程序出于某种原因需要处理所有事件时,这确实非常方便。)

事件回调接收参数lv_event_t * e ,其中包含当前事件代码和其他事件相关信息。可以使用以下命令检索当前事件代码:

lv_event_code_t code = lv_event_get_code(e);

 可以使用以下方法检索触发事件的小部件:

lv_obj_t * obj = lv_event_get_target(e);

要了解活动的所有特点,请转到活动部分。

部分

小部件由一个或多个部件构成。例如,按钮只有一个名为的部件LV_PART_MAIN。但是, 滑块 (lv_slider)有LV_PART_MAIN、LV_PART_INDICATOR 和LV_PART_KNOB。

通过使用部件,您可以将不同的样式应用于小部件的子元素。(见下文。)

阅读Widget的文档来了解它使用了哪些部分。

州(谷歌翻译应该是有些问题)

例如,如果您按下一个小部件,它将自动进入 LV_STATE_FOCUSEDLV_STATE_PRESSED状态,而当您释放它时,LV_STATE_PRESSED状态将被删除,而 LV_STATE_FOCUSED状态仍然保持活动状态。

要检查 Widget 是否处于给定状态,请使用 lv_obj_has_state ( widget , LV_STATE_ ... ) true 。如果 Widget 当前处于该状态,它将返回。

要手动添加或删除状态,请使用:

lv_obj_add_state(widget, LV_STATE_...);
lv_obj_remove_state(widget, LV_STATE_...);

样式

样式实例包含描述 Widget 外观的背景颜色、边框宽度、字体等属性。

样式以对象的形式承载lv_style_t。只有它们的指针保存在 Widget 中,因此需要将它们定义为静态或全局变量。在使用样式之前,需要使用lv_style_init ( & style1 )对其进行初始化。之后,可以添加属性来配置样式。例如

static lv_style_t style1;
lv_style_init(&style1);
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080))
lv_style_set_border_width(&style1, 2))

样式是使用小部件的部分和状态的或组合来分配的。例如,当按下滑块时,在滑块的指示器上使用此样式:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);

如果该部分是LV_PART_MAIN可以省略:

lv_obj_add_style(btn1, &style1, LV_STATE_PRESSED); /* Equal to LV_PART_MAIN | LV_STATE_PRESSED */

类似地,LV_STATE_DEFAULT可以省略:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR); /* Equal to LV_PART_INDICATOR | LV_STATE_DEFAULT */

对于LV_STATE_DEFAULT|LV_PART_MAIN只需传递0:

lv_obj_add_style(btn1, &style1, 0); /* Equal to LV_PART_MAIN | LV_STATE_DEFAULT */

样式可以级联(类似于 CSS)。这意味着您可以为 Widget 的某个部分添加更多样式。例如,style_btn可以设置默认按钮外观,并style_btn_red可以覆盖背景颜色以使按钮变为红色:

lv_obj_add_style(btn1, &style_btn, 0);
lv_obj_add_style(btn1, &style1_btn_red, 0);

如果当前状态未设置属性LV_STATE_DEFAULT则将使用带有的样式。如果默认状态下未定义该属性,则使用默认值。

某些属性(尤其是与文本相关的属性)可以继承。这意味着如果某个属性未在 Widget 中设置,则会在其父级中搜索该属性。例如,您可以在屏幕的样式中设置一次字体,该屏幕上的所有文本将默认继承该字体。

还可以将本地样式属性添加到小部件中。这将创建一个位于小部件内部且仅由该小部件使用的样式:

lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);

主题

主题是小部件的默认样式。创建小部件时会自动应用主题的样式。

您的应用程序的主题是在中设置的编译时配置 lv_conf.h。

也就是说不对裁剪文件进行修改,是可以使用默认格式的。第一次移植完全可以只修改接口文件。

MicroPython

深入了解

下次找个临睡前看吧,少刷抖音,哈哈。开启贤者的一天

基本示例

下面是几个基本示例。它们包括生成 Widget Tree 的应用程序代码,这些 Widget Tree 是使 LVGL 渲染所示示例所需的。每个示例都假设 LVGL 已进行正常初始化,这意味着lv_display_t已创建了一个对象,因此具有Active Screen。

示例1一个非常简单的hello world标签

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_LABEL/*** Basic example to create a "Hello world" label*/
void lv_example_get_started_1(void)
{/*Change the active screen's background color*/lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);/*Create a white label, set its text and align it to the center*/lv_obj_t * label = lv_label_create(lv_screen_active());lv_label_set_text(label, "Hello world");lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}#endif

示例2 带有标签并对点击事件做出反应的按钮

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_BUTTONstatic void btn_event_cb(lv_event_t * e)
{lv_event_code_t code = lv_event_get_code(e);lv_obj_t * btn = lv_event_get_target(e);if(code == LV_EVENT_CLICKED) {static uint8_t cnt = 0;cnt++;/*Get the first child of the button which is the label and change its text*/lv_obj_t * label = lv_obj_get_child(btn, 0);lv_label_set_text_fmt(label, "Button: %d", cnt);}
}/*** Create a button with a label and react on click event.*/
void lv_example_get_started_2(void)
{lv_obj_t * btn = lv_button_create(lv_screen_active());     /*Add a button the current screen*/lv_obj_set_pos(btn, 10, 10);                            /*Set its position*/lv_obj_set_size(btn, 120, 50);                          /*Set its size*/lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);           /*Assign a callback to the button*/lv_obj_t * label = lv_label_create(btn);          /*Add a label to the button*/lv_label_set_text(label, "Button");                     /*Set the labels text*/lv_obj_center(label);
}#endif

示例3 从头开始创建按钮样式

#include "../lv_examples.h"
#if LV_USE_BUTTON && LV_BUILD_EXAMPLESstatic lv_style_t style_btn;
static lv_style_t style_button_pressed;
static lv_style_t style_button_red;static lv_color_t darken(const lv_color_filter_dsc_t * dsc, lv_color_t color, lv_opa_t opa)
{LV_UNUSED(dsc);return lv_color_darken(color, opa);
}static void style_init(void)
{/*Create a simple button style*/lv_style_init(&style_btn);lv_style_set_radius(&style_btn, 10);lv_style_set_bg_opa(&style_btn, LV_OPA_COVER);lv_style_set_bg_color(&style_btn, lv_palette_lighten(LV_PALETTE_GREY, 3));lv_style_set_bg_grad_color(&style_btn, lv_palette_main(LV_PALETTE_GREY));lv_style_set_bg_grad_dir(&style_btn, LV_GRAD_DIR_VER);lv_style_set_border_color(&style_btn, lv_color_black());lv_style_set_border_opa(&style_btn, LV_OPA_20);lv_style_set_border_width(&style_btn, 2);lv_style_set_text_color(&style_btn, lv_color_black());/*Create a style for the pressed state.*Use a color filter to simply modify all colors in this state*/static lv_color_filter_dsc_t color_filter;lv_color_filter_dsc_init(&color_filter, darken);lv_style_init(&style_button_pressed);lv_style_set_color_filter_dsc(&style_button_pressed, &color_filter);lv_style_set_color_filter_opa(&style_button_pressed, LV_OPA_20);/*Create a red style. Change only some colors.*/lv_style_init(&style_button_red);lv_style_set_bg_color(&style_button_red, lv_palette_main(LV_PALETTE_RED));lv_style_set_bg_grad_color(&style_button_red, lv_palette_lighten(LV_PALETTE_RED, 3));
}/*** Create styles from scratch for buttons.*/
void lv_example_get_started_3(void)
{/*Initialize the style*/style_init();/*Create a button and use the new styles*/lv_obj_t * btn = lv_button_create(lv_screen_active());/* Remove the styles coming from the theme* Note that size and position are also stored as style properties* so lv_obj_remove_style_all will remove the set size and position too */lv_obj_remove_style_all(btn);lv_obj_set_pos(btn, 10, 10);lv_obj_set_size(btn, 120, 50);lv_obj_add_style(btn, &style_btn, 0);lv_obj_add_style(btn, &style_button_pressed, LV_STATE_PRESSED);/*Add a label to the button*/lv_obj_t * label = lv_label_create(btn);lv_label_set_text(label, "Button");lv_obj_center(label);/*Create another button and use the red style too*/lv_obj_t * btn2 = lv_button_create(lv_screen_active());lv_obj_remove_style_all(btn2);                      /*Remove the styles coming from the theme*/lv_obj_set_pos(btn2, 10, 80);lv_obj_set_size(btn2, 120, 50);lv_obj_add_style(btn2, &style_btn, 0);lv_obj_add_style(btn2, &style_button_red, 0);lv_obj_add_style(btn2, &style_button_pressed, LV_STATE_PRESSED);lv_obj_set_style_radius(btn2, LV_RADIUS_CIRCLE, 0); /*Add a local style too*/label = lv_label_create(btn2);lv_label_set_text(label, "Button 2");lv_obj_center(label);
}#endif

示例4 创建一个滑块并将其值写在标签上

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_SLIDERstatic lv_obj_t * label;static void slider_event_cb(lv_event_t * e)
{lv_obj_t * slider = lv_event_get_target(e);/*Refresh the text*/lv_label_set_text_fmt(label, "%"LV_PRId32, lv_slider_get_value(slider));lv_obj_align_to(label, slider, LV_ALIGN_OUT_TOP_MID, 0, -15);    /*Align top of the slider*/
}/*** Create a slider and write its value on a label.*/
void lv_example_get_started_4(void)
{/*Create a slider in the center of the display*/lv_obj_t * slider = lv_slider_create(lv_screen_active());lv_obj_set_width(slider, 200);                          /*Set the width*/lv_obj_center(slider);                                  /*Align to the center of the parent (screen)*/lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);     /*Assign an event function*//*Create a label above the slider*/label = lv_label_create(lv_screen_active());lv_label_set_text(label, "0");lv_obj_align_to(label, slider, LV_ALIGN_OUT_TOP_MID, 0, -15);    /*Align top of the slider*/
}#endif

怎么我把examples的文件都填进去,去主函数调用demo它没有反应刚啊,接口也初始化了。我以为 我的配置有问题,我去手表源代码也试了一下把ui和rtos都注释掉,依然没有反应?这是怎么回事。

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_SPI1_Init();MX_I2C1_Init();MX_RTC_Init();MX_TIM2_Init();/* USER CODE BEGIN 2 *///usart startHAL_UART_Receive_DMA(&huart1,(uint8_t*)HardInt_receive_str,25);__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//PWM StartHAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//sys delaydelay_init();//keyKey_Port_Init();//touchCST816_GPIO_Init();//触摸芯片芯片CST816_RESET();//lcdLCD_Init();LCD_Fill(0,0,LCD_W,LCD_H,RED);delay_ms(10);LCD_Set_Light(50);LCD_ShowString(72,LCD_H/2-20,(uint8_t*)"Welcome!",WHITE,BLACK,24,0);//12*6,16*8,24*12,32*16LCD_ShowString(42,LCD_H/2+48-20,(uint8_t*)"OV-Watch V2.3",WHITE,BLACK,24,0);delay_ms(1000);LCD_Fill(0,LCD_H/2-24-20,LCD_W,LCD_H/2+49-20,BLACK);//LVGL initlv_init();//初始化 LVGL 图形用户界面库lv_port_disp_init();//显示和输入设备初始化函数lv_port_indev_init();//lv_example_get_started_2();/* Init scheduler */osKernelInitialize();/* Call init function for freertos objects (in cmsis_os2.c) */MX_FREERTOS_Init();/* Start scheduler */osKernelStart();/* We should never get here as control is now taken by the scheduler *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

于是我决定去把找找DMA的问题,因为用到了DMA进行区域填充,而不是画点,但是我好像也没有开启它。

使能DMA之后还是没有效果,我决定换成画点函数试一下。

换成画点函数依然没工作

这个问题等以后搞定了再来弄

我好像找到问题所在了

多谢这位老哥的文章

LVGL的使用-CSDN博客

我好像添加了一个定时器,然后多加了一个函数,它就可以显示了,我去

我去Cubemx加了一个定时器10作为1ms的定时周期,也可以用开始的定时器11.定时器10是我来测试中断功能的。

在定时器回调服务函数里 加入lv_tick_inc(1),给1ms心跳值

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM11) {HAL_IncTick();}if (htim->Instance == TIM10){// 在这里添加定时器中断处理逻辑flag ++;lv_tick_inc(1);//lvgl 1ms的心跳}/* USER CODE BEGIN Callback 1 *//* USER CODE END Callback 1 */
}

开头的时候开启定时器中断即可

// 开启定时器中断HAL_TIM_Base_Start_IT(&htim10);

然后整个main的话就是这样,当然还是基于手表修改的,先关闭了任务相关的部分

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "dma.h"
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32f4xx_it.h"
#include "cst816.h"
#include "key.h"
#include "iic_hal_hard.h"
#include "iic_hal.h"
#include "lcd.h"
#include "lcd_init.h"
#include "lv_examples.h"
#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint16_t flag = 0;/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_FREERTOS_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_SPI1_Init();MX_I2C1_Init();MX_RTC_Init();MX_TIM2_Init();MX_TIM10_Init();/* USER CODE BEGIN 2 */
// 开启定时器中断HAL_TIM_Base_Start_IT(&htim10);/* USER CODE END 2 *///usart startHAL_UART_Receive_DMA(&huart1,(uint8_t*)HardInt_receive_str,25);__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//PWM StartHAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//sys delaydelay_init();//keyKey_Port_Init();//touchCST816_GPIO_Init();//触摸芯片芯片CST816_RESET();//lcdLCD_Init();LCD_Fill(0,0,LCD_W,LCD_H,RED);delay_ms(10);LCD_Set_Light(50);LCD_ShowString(72,LCD_H/2-20,(uint8_t*)"Welcome!",WHITE,BLACK,24,0);//12*6,16*8,24*12,32*16LCD_ShowString(42,LCD_H/2+48-20,(uint8_t*)"OV-Watch V2.3",WHITE,BLACK,24,0);delay_ms(1000);LCD_Fill(0,LCD_H/2-24-20,LCD_W,LCD_H/2+49-20,BLACK);//LVGL initlv_init();//初始化 LVGL 图形用户界面库lv_port_disp_init();//显示和输入设备初始化函数lv_port_indev_init();//lv_example_get_started_1();/* Init scheduler */// osKernelInitialize();/* Call init function for freertos objects (in cmsis_os2.c) */// MX_FREERTOS_Init();/* Start scheduler */// osKernelStart();/* We should never get here as control is now taken by the scheduler *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */if(flag == 500){printf("interrupt\r\n");flag=0;}lv_task_handler();/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.LSIState = RCC_LSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 12;RCC_OscInitStruct.PLL.PLLN = 96;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 3;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  Period elapsed callback in non blocking mode* @note   This function is called  when TIM11 interrupt took place, inside* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment* a global variable "uwTick" used as application time base.* @param  htim : TIM handle* @retval None*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM11) {HAL_IncTick();}if (htim->Instance == TIM10){// 在这里添加定时器中断处理逻辑flag ++;lv_tick_inc(1);//lvgl 1ms的心跳}/* USER CODE BEGIN Callback 1 *//* USER CODE END Callback 1 */
}/*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

有反馈是很重要的事情。

接下来我要将其他的demo也试一下。

剩下的内容直接去老哥博客学习。

NXP的GUI Builder使用,虽然版本是8.3 我觉得跟8.2也不会很不兼容

点击运行下的编译部署

然后就可以出现一个仿真的触控

导出代码

8.2版本的anim函数函数不支持,新增了很多功能,除非我直接替换这个,但是可能会引起其他问题。暂时我就不插入图片了。

不行还是得用8.3版本,绕不过。或者换个软件使。我就暂时不弄了

弄成了大致就是这样 

LVGL的使用-CSDN博客

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

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

相关文章

计算机网络HTTP——针对实习面试

目录 计算机网络HTTP什么是HTTP&#xff1f;HTTP和HTTPS有什么区别&#xff1f;分别说明HTTP/1.0、HTTP/2.0、HTTP/3.0请说明访问网页的全过程请说明HTTP常见的状态码Cookie和Session有什么区别&#xff1f;HTTP请求方式有哪些&#xff1f;请解释GET和POST的区别&#xff1f;HT…

大数据-226 离线数仓 - Flume 优化配置 自定义拦截器 拦截原理 了 拦截器实现 Java

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

无人机动力系统测试-实测数据与CFD模拟仿真数据关联对比分析

我们经常被问到这样的问题&#xff1a;“我们计划运行 CFD 仿真&#xff0c;我们还需要对电机和螺旋桨进行实验测试吗&#xff1f;我们可能有偏见&#xff0c;但我们的答案始终是肯定的&#xff0c;而且有充分的理由。我们自己执行了大量的 CFD 仿真&#xff0c;但我们承认&…

验证双随机矩阵(doubly stochastic matrix) 满足C(P)=C(P^T)

验证双随机矩阵(doubly stochastic matrix) 满足C( P P P)C(P T ^T T) 双随机矩阵&#xff1a; 在数学中&#xff0c;一个双随机矩阵&#xff08;doubly stochastic matrix&#xff09;是一个满足以下条件的矩阵&#xff1a; 非负矩阵&#xff1a;矩阵中的每个元素都是非负的…

Chrome 浏览器开启打印模式

打开开发者工具ctrl shift p输入print 找到 Emulate CSS print media type

Vite初始化Vue3+Typescrpt项目

初始化项目 安装 Vite 首先&#xff0c;确保你的 Node.js 版本 > 12.0.0。然后在命令行中运行以下命令来创建一个 Vite Vue 3 TypeScript 的项目模板&#xff1a; npm init vitelatest进入项目目录 创建完成后&#xff0c;进入项目目录&#xff1a; cd vue3-demo启动…

24 年第十届数维杯国际数模竞赛赛题浅析

本次万众瞩目的数维杯国际大学生数学建模赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是数模届的独一档&#xff0c;含金量极高&#xff0c;可以用于综测加分、保研、简历添彩等各方面。考虑到大家解题实属不易&#xff0c;为了帮助大家取得好成绩…

自动语音识别(ASR)与文本转语音(TTS)技术的应用与发展

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

CentOS8 启动错误,enter emergency mode ,开机直接进入紧急救援模式,报错 Failed to mount /home 解决方法

先看现场问题截图&#xff1a; 1.根据提示 按 ctrld 输入 root 密码&#xff0c;进入系统。 2. 在紧急模式下运行&#xff1a;journalctl -xe &#xff0c;查看相关日志&#xff0c;找到关键点&#xff1a; Failed to mount /home 3.接着执行修复命令&#xff1a; xfs_repa…

Java项目实战II基于微信小程序的课堂助手(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在数字化教…

借助 Pause 容器调试 Pod

借助 Pause 容器调试 Pod 在 K8S 中&#xff0c;Pod 是最核心、最基础的资源对象&#xff0c;也是 Kubernetes 中调度最小单元。在介绍 Pause 容器之前需要先说明下 Pod 与容器的关系来理解为什么需要 Pause 容器来帮助调试 1. Pod 与 容器的关系 Pod 是一个抽象的逻辑概念&…

IDEA自定义文件打开格式

介绍在IDEA中自定义文件打开格式的方法&#xff0c;比如一个文件&#xff0c;可以选择用txt格式打开&#xff0c;也可以选择用xml格式打开&#xff0c;也可以用java格式打开等等&#xff0c;通过这个方法可以方便的用任意格式在idea中打开想要打开的文件。 下面分别讨论三种不…

Git 分⽀规范 Git Flow 模型

前言 GitFlow 是一种流行的 Git 分支管理策略&#xff0c;由 Vincent Driessen 在 2010 年提出。它提供了一种结构化的方法来管理项目的开发、发布和维护&#xff0c;特别适合大型和复杂的项目。GitFlow 定义了一套明确的分支模型和工作流程&#xff0c;使得团队成员可以更有效…

ECG心电前级信号提取

由于ECG信号很微弱&#xff0c;处于mV级别&#xff0c;还有很多干扰信号&#xff0c;所以采集信号时需要进行滤波和放大处理&#xff0c;然后使用模数转换。为了滤波高频干扰和工频噪声&#xff0c;需要使用低通滤波器和陷波器抑制噪声&#xff0c;有时也要使用高通滤波器滤除低…

【Android】逆向开发与反逆向开发入门知识(一)

目录 逆向开发反编译 & 反混淆反编译工具反编译反混淆 修改预置资源文件抓包前期准备二次打包重签名 如何预防 App 被逆向开发&#xff1f;代码混淆应用加固防止动态调试Root 检测二次打包检测 警告&#xff1a;逆向开发相关知识请在法律规定范围内使用&#xff0c;请勿使用…

华为Mate 70临近上市:代理IP与抢购攻略

随着科技的飞速发展&#xff0c;智能手机已经成为我们日常生活中不可或缺的一部分。而在众多智能手机品牌中&#xff0c;华为一直以其卓越的技术和创新力引领着行业的发展。近日&#xff0c;华为Mate 70系列手机的发布会正式定档在11月26日&#xff0c;这一消息引发了众多科技爱…

【Linux之权限】理论篇

前言 Linux的权限是我们学习Linux初期非常重要的基础知识&#xff0c;接下来我将通过一个系列【Linux之权限】&#xff0c;共三篇文章&#xff0c;对此进行较为全面和详细的解说。 sudo 情况&#xff1a;如果我们不是超级管理员&#xff0c;但是想执行一个权限级别比较高的指…

[C++] 智能指针

文章目录 智能指针的使用原因及场景分析为什么需要智能指针&#xff1f;异常抛出导致的资源泄漏问题分析 智能指针与RAIIC常用智能指针 使用智能指针优化代码优化后的代码优化点分析 析构函数中的异常问题解决方法 RAII 和智能指针的设计思路详解什么是 RAII&#xff1f;RAII 的…

spark性能优化调优指导性文件

1.让我们看一下前面的核心参数设置&#xff1a; num-executors10||20&#xff0c;executor-cores1||2&#xff0c;executor-memory10||20&#xff0c;driver-memory20&#xff0c;spark.default.parallelism64 假设我们的火花队列资源如下&#xff1a; 内存1T&#xff0c;内…

视频流媒体播放器EasyPlayer.js RTSP播放器视频颜色变灰色/渲染发绿的原因分析

EasyPlayer.js RTSP播放器属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;无须安装任何插件&#xff0c;起播快、延迟低、兼容性强&#xff0c;使用非常便捷。 EasyPlayer.js播放器不仅支持H.264与H.265视频编码格式&#xff0…