学习使用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.xdnf.cn/news/17366.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【数据库】组合索引生效规则及索引失效

文章目录 索引演示示例组合索引索引失效 索引演示示例 # 创建表结构 CREATE TABLE Employees (EmployeeID INT PRIMARY KEY,FirstName VARCHAR(50),LastName VARCHAR(50),DepartmentID INT,Salary DECIMAL(10, 2),HireDate DATE );# 插入示例数据 INSERT INTO Employees (Empl…

力扣 LeetCode 145. 二叉树的后序遍历(Day6:二叉树)

解题思路&#xff1a; 方法一&#xff1a;递归&#xff08;左右中&#xff09; class Solution {List<Integer> res new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {recur(root);return res;}public void recur(TreeNode ro…

用指针遍历数组

#include<stdio.h> int main() {//定义一个二维数组int arr[3][4] {{1,2,3,4},{2,3,4,5},{3,4,5,6},};//获取二维数组的指针int (*p)[4] arr;//二维数组里存的是一维数组int[4]for (int i 0; i < 3; i){//遍历一维数组for (int j 0; j <4; j){printf("%d &…

[HCTF 2018]Warmup 详细题解

知识点: 目录穿越_文件包含 static静态方法 参数传递引用 mb_strpos函数 mb_substr函数 正文: 页面有一张 滑稽 的表情包,查看一下页面源代码,发现提示 那就访问/source.php 得到源码 <?phphighlight_file(__FILE__);class emmm{public static function checkFil…

从0-1训练自己的数据集实现火焰检测

随着工业、建筑、交通等领域的快速发展,火灾作为一种常见的灾难性事件,对生命财产安全造成了严重威胁。为了提高火灾的预警能力,减少火灾损失,火焰检测技术应运而生,成为火灾监控和预防的有效手段之一。 传统的火灾检测方法,如烟雾探测器、温度传感器等,存在响应时间慢…

小程序20-样式:自适应尺寸单位 rpx

手机设备的宽度逐渐多元化&#xff0c;也就需要开发者开发过程中&#xff0c;去适配不同屏幕宽度的手机&#xff0c;为了解决屏幕适配问题&#xff0c;微信小程序推出了 rpx 单位 rpx&#xff1a;小程序新增的自适应单位&#xff0c;可以根据不同设备的屏幕宽度进行自适应缩放 …

在Ubuntu系统中,默认情况下会安装`apt`作为包管理工具(Advanced Package Tool)

文章目录 方法一&#xff1a;使用命令行检查apt是否存在方法二&#xff1a;尝试运行一个apt命令方法三&#xff1a;查看包列表如果apt没有安装主要功能高级用法注意事项 在Ubuntu系统中&#xff0c;默认情况下会安装 apt作为包管理工具。你可以通过以下几种方法来检查系统中是…

Github 2024-11-16Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-11-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Go项目1Python项目1Lapce:用 Rust 编写的极快且强大的代码编辑器 创建周期:2181 天开发语言:Rust协议类型:Apache License 2.0St…

C++:基于红黑树封装map和set

目录 红黑树的修改 红黑树节点 红黑树结构 红黑树的迭代器 红黑树Insert函数 红黑树的默认成员函数 修改后完整的红黑树 set、map的模拟实现 set map 测试封装的set和map 红黑树的修改 想要用红黑树封装map和set&#xff0c;需要对之前实现的key-value红黑树进行修…

LeetCode 3240.最少翻转次数使二进制矩阵回文 II:分类讨论

【LetMeFly】3240.最少翻转次数使二进制矩阵回文 II&#xff1a;分类讨论 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-ii/ 给你一个 m x n 的二进制矩阵 grid 。 如果矩阵中一行或者一列从前往后与从后…

在kile 5中一个新工程的创建

这两天博主学习到了在kile5中创建一个工程&#xff0c;当然博主不会忘了小伙伴们的&#xff0c;这就和你们分享。 本次创建以STM32F103C8为例 创建过程&#xff1a; 1首先创建文件 名字随意&#xff0c;但也不要太随意&#xff0c;因为是外国软件&#xff0c;所以多少对中文…

深度学习工具和框架详细指南:PyTorch、TensorFlow、Keras

引言 在深度学习的世界中&#xff0c;PyTorch、TensorFlow和Keras是最受欢迎的工具和框架&#xff0c;它们为研究者和开发者提供了强大且易于使用的接口。在本文中&#xff0c;我们将深入探索这三个框架&#xff0c;涵盖如何用它们实现经典深度学习模型&#xff0c;并通过代码…

2024-11-16 特殊矩阵的压缩存储

一、数组的存储结构 1.一维数组&#xff1a;各元素大小相同&#xff0c;且物理上连续存放。a[i]起始地址i*siezof(数组元素大小) 2.二维数组&#xff1a;b[j][j]起始地址&#xff08;i*Nj&#xff09;*sizeof(数组元素大小) 二、特殊矩阵 1.普通矩阵的存储&#xff1a;使用…

ISCTF2024

ezlogin 源码审计 先审源码,纯js题 const express require(express); const app express(); const bodyParser require(body-parser); var cookieParser require(cookie-parser); var serialize require(node-serialize); app.use(bodyParser.urlencoded({ e…

leetcode226:反转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]示例 3&#x…

Excel365和WPS中提取字符串的五种方法

一、问题的提出 如何在WPS或者Excel365中提取A列指定的字符串&#xff0c;从"面"开始一直到".pdf"? 问题的提出 二、问题的分析 我们可以采用多种方法解决这个问题&#xff0c;由于A列到B列的提取是非常有规律的&#xff0c;因此我们可以采用如下几种方…

下载jakarta-taglibs-standard-current.zip

官网&#xff1a;https://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ 下载版本&#xff1a;

Qt信号和槽

信号和槽的概念 在Linux中我们也学过信号 Signal&#xff0c;这是进程间通信的一种方式&#xff0c;这里大致分为三个要素&#xff1a; 信号源&#xff1a;谁发送的信号&#xff08;用户进程&#xff0c;系统内核&#xff0c;终端或者作业控制&#xff0c;&#xff09; 信号的类…

MATLAB绘图

一、实验内容和步骤 MATLAB的图形功能非常强大&#xff0c;可以对二维、三维数据用图形表现&#xff0c;并可以对图形的线形、曲面、视觉、色彩和光线等进行处理。 1、绘制二维曲线 绘制如下图所示的图形&#xff0c;把图形窗口分割为2列2行&#xff0c;在窗口1中绘制一条正弦…

H3C NX30Pro刷机教程-2024-11-16

H3C NX30Pro刷机教程-2024-11-16 ref: http://www.ttcoder.cn/index.php/2024/11/03/h3c-nx30pro亲测无需分区备份 路由器-新机初始化设置路由器登录密码telnet进入路由器后台 刷机上传uboot到路由器后台在Windows环境下解压后的软件包中打开 tftpd64.exe在NX30Pro环境下通过以…