学习使用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_BUTTON

static 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_EXAMPLES

static 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_SLIDER

static 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 start
	HAL_UART_Receive_DMA(&huart1,(uint8_t*)HardInt_receive_str,25);
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);

	//PWM Start
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
	
  //sys delay
	delay_init();

	//key
	Key_Port_Init();
	
	//touch
	CST816_GPIO_Init();//触摸芯片芯片
	CST816_RESET();
	
	//lcd
	LCD_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*16
	LCD_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 init
	lv_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 start
	HAL_UART_Receive_DMA(&huart1,(uint8_t*)HardInt_receive_str,25);
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);

	//PWM Start
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
	
  //sys delay
	delay_init();

	//key
	Key_Port_Init();
	
	//touch
	CST816_GPIO_Init();//触摸芯片芯片
	CST816_RESET();
	
	//lcd
	LCD_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*16
	LCD_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 init
	lv_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博客

### RP2040 使用 LVGL 开发指南 #### 创建工程 为了在 RP2040 上使用 LVGL 图形库进行开发,首先需要创建一个新的工程项目。可以选择使用 Arduino IDE 或者 PlatformIO 来简化这个过程。 #### 下载 LVGL 依赖库 TFT_eSPI 安装 `TFT_eSPI` 库是必要的一步,因为这将提供驱动显示屏所需的底层支持函数。通过 Arduino 库管理器来获取最新版本的 `TFT_eSPI`[^2]。 ```cpp #include <TFT_eSPI.h> ``` #### 配置 LVGL 库 接着要下载并配置 LVGL 库本身。可以从官方 GitHub 仓库克隆最新的源码,并按照说明集成到项目中去。确保选择了适合微控制器平台的构建选项。 #### 初始化硬件资源 设置好模拟器之后,应该初始化与显示有关的具体参数,比如分辨率、颜色模式等。对于 RP2040 而言,还需要特别注意 SPI 总线的速度设定以及 GPIO 映射关系。 ```cpp // Initialize the display and touch screen (if available) void setup() { tft.init(); // Set up LVGL library with custom configuration } ``` #### 编写 GUI 界面代码 现在可以开始编写具体的用户界面逻辑了。利用 LVGL 提供的各种组件如按钮、滑动条等快速搭建交互式的应用程序原型。 ```cpp lv_obj_t *btn; btn = lv_btn_create(lv_scr_act()); lv_obj_set_pos(btn, 10, 10); lv_obj_set_size(btn, 100, 50); static void btn_event_cb(lv_event_t *e) { lv_event_code_t code = lv_event_get_code(e); if(code == LV_EVENT_CLICKED){ Serial.println("Button clicked"); } } lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL); ``` #### 测试和调试 完成上述步骤后,在真实环境中测试编写的程序非常重要。可以通过串口监视器观察日志输出,也可以借助于在线仿真工具来进行初步验证。 #### 进阶学习路径 深入理解 LVGL 可以参考官方网站提供的文档资料[^1],特别是关于各个部件特性的详细介绍部分;另外积极参与社区交流也是提升技能的好办法之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值