[GUI] 通过CMSIS-PACK快速建立LVGL V9工程

[复制链接]
4273|2
 楼主| muyichuan2012 发表于 2024-7-1 16:03 | 显示全部楼层 |阅读模式
通过CMSIS-PACK快速建立LVGL V9工程



下载链接:https://www.arterytek.com/file/download/1952
前言
LVGL是一种目前非常流行的嵌入式图形库。LVGL完全开源,没有外部依赖,这使得它的移植非常简单。它适用于任何现代 MCU 或 MPU,并可与任何 (RT)OS 或裸机设置一起使用,可以驱动电子纸、单色、OLED 或 TFT 显示器,甚至显示器。此外,即使对于商业项目,它也是免费的。

由于LVGL的源文件较多,工程师在建立LVGL工程时,往往需要较多时间去导入这些文件。因此,本文主要基于LVGL库文件自带cmsis-pack文件,介绍如何在MDK上快速建立LVGL工程。

支持型号列表:
AT32F435 系列
AT32F437 系列
AT32F403A 系列
AT32F407 系列


目录
环境准备 ............................ 5
LVGL 工程建立 .................... 6
案例使用 ............................ 13
版本历史 ............................ 15


环境准备
本章节主要介绍所需的硬件资源和软件资源。
硬件资源
1. AT-SURF-F437
2. 配套3.5’ TFTLCD MODULE
Note:本文重点介绍LVGL 移植步骤,此硬件资源不是必须的,用户可根据具体情况选择合适的硬件资源。
图1. AT-SURF-F437 实物图

8172566825f8384dde.png

软件资源
1) MDK5
2) AT32F435_437_Firmware_Library_V2.x.x
官网最新版下载地址:https://www.arterytek.com/cn/product/AT32F435.jsp
3) LVGL
官网最新版下载地址:https://github.com/lvgl,注意要下载release版本


LVGL 工程建立
本章节主要介绍使用LV CMSIS-PACK 建立MDK5 工程步骤
步骤一 安装LVGL.lvgl.9.x.x.pack 文件
打开lvgl-9.x.x\env_support\cmsis-pack 文件,双击LVGL.lvgl.9.x.x.pack 文件进行安装
图2. lvgl pack 安装

1664766825fa9c7485.png

步骤二 配置MDK5 的RTE 组件
这里以AT32F435_437_Firmware_Library_V2.x.x\project\at_start_f437\templates\mdk_v5 中
template.uvprojx 举例,按下图勾选LVGL 组件

图3. lvgl RTE 组件选择
3011166825ff18c7a2.png

注意:步骤一和步骤二完成后,LVGL 组件已经已添加成功,此时选AC6 编译可能报错,这里需要选择c11 标
准。再次编译则不会报错。


图4. MDK5 AC6 选择c11 标准
608126682601c9f84b.png

注意:组件配置完成后,会在keil 工程中生成一些只读文件和若干需要用户配置的文件,这些配置文件需要打
开条件编译 #if 1 配置才会生效。

步骤三 配置 lv_conf.h 文件
a) 配置默认显示刷新率为10 ms
  1. /*Default display refresh, input device read and animation step period.*/
  2. #define LV_DEF_REFR_PERIOD 10 /*[ms]*/


b) 开启monitor,可在lcd 上显示实时帧率
/*1: Enable system monitor component*/
#define LV_USE_SYSMON 1
步骤四 修改lv_port_disp_template.c 文件,添加lvgl 显示驱动
a) 添加LCD 的actual screen width 和the actual screen height。并定义static lv_display_t * disp =
NULL;
本案例以AT-SURF-F437 配套的.3.5’ TFTLCD MODULE 举例,配置宏定义如下
  1. #include "lv_port_disp_template.h"
  2. #include <stdbool.h>
  3. #define MY_DISP_HOR_RES 320
  4. #define MY_DISP_VER_RES 480


b) 配置 void lv_port_disp_init(void)函数
  1. void lv_port_disp_init(void)
  2. {
  3. /*-------------------------
  4. * Initialize your display
  5. * -----------------------*/
  6. disp_init();
  7. /*------------------------------------
  8. * Create a display and set a flush_cb
  9. * -----------------------------------*/
  10. disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
  11. lv_display_set_flush_cb(disp, disp_flush);
  12. /* Example 2
  13. * Two buffers for partial rendering
  14. * In flush_cb DMA or similar hardware should be used to update the display in the background.*/
  15. ALIGNED_HEAD static lv_color_t buf_2_1[MY_DISP_HOR_RES * 100] ALIGNED_TAIL;
  16. ALIGNED_HEAD static lv_color_t buf_2_2[MY_DISP_HOR_RES * 100] ALIGNED_TAIL;
  17. lv_display_set_buffers(disp, buf_2_1, buf_2_2, sizeof(buf_2_1),
  18. LV_DISPLAY_RENDER_MODE_PARTIAL);
  19. }


注意:在lv_port_disp_template.c 文件要先先定义static lv_display_t * disp = NULL;便于相关函数调用
配置static void disp_init(void)函数
  1. <blockquote>static void disp_init(void)

c) 配置 static void disp_flush(lv_display_t * …)函数
  1. static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
  2. {
  3. if(disp_flush_enabled)
  4. {
  5. u32 size = (area->x2 - area->x1+1)*(area->y2 - area->y1+1) ;
  6. lcd_windows_set(area->x1,area->y1,area->x2,area->y2);
  7. DMA1_CHANNEL3->ctrl &= ~(uint16_t)1;
  8. DMA1_CHANNEL3->paddr = (uint32_t)px_map;
  9. DMA1_CHANNEL3->dtcnt = size/2;
  10. DMA1_CHANNEL3->ctrl |= (uint16_t)1;
  11. }
  12. }


d) 增加void DMA1_Channel3_IRQHandler()函数
  1. void DMA1_Channel3_IRQHandler()
  2. {
  3. if(dma_flag_get(DMA1_FDT3_FLAG)== SET)
  4. {
  5. dma_flag_clear(DMA1_FDT3_FLAG);
  6. lv_disp_flush_ready(disp);
  7. }
  8. }


本案例试用了DMA 方式刷屏,因此需要在DMA 完成中断中调用lv_disp_flush_ready(disp)函数
e) 在lv_port_disp_template.h 文件中添加必要的头文件
  1. #if defined(LV_LVGL_H_INCLUDE_SIMPLE)
  2. #include "lvgl.h"
  3. #include "at_surf_f437_board_lcd.h"
  4. #include "at32f435_437.h"
  5. #else
  6. #include "lvgl/lvgl.h"
  7. #endif


步骤五 修改lv_port_indev_template.c 文件,添加触摸屏显示驱动
a) 配置void lv_port_indev_init(void)函数
  1. <blockquote>void lv_port_indev_init(void)

b) 配置void touchpad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)函数
  1. static void touchpad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
  2. {
  3. static int32_t last_x = 0;
  4. static int32_t last_y = 0;
  5. if(touch_dev_struct.touch_read_xy(&touch_dev_struct.x_p[1],&touch_dev_struct.y_p[1]))
  6. {
  7. data->point.x = touch_dev_struct.x_p[1];
  8. data->point.y = touch_dev_struct.y_p[1];
  9. data->state = LV_INDEV_STATE_PR;
  10. last_x = data->point.x;
  11. last_y = data->point.y;
  12. }
  13. else
  14. {
  15. data->point.x = last_x;
  16. data->point.y = last_y;
  17. data->state = LV_INDEV_STATE_REL;
  18. }
  19. }


c) 在lv_port_indev_template.h 文件中添加必要的头文件
  1. #if defined(LV_LVGL_H_INCLUDE_SIMPLE)
  2. #if defined(LV_LVGL_H_INCLUDE_SIMPLE)
  3. #include "lvgl.h"
  4. #include "lvgl.h"
  5. #include "at_surf_f437_board_touch.h"
  6. #include "at_surf_f437_board_joystick.h"
  7. #include "at_surf_f437_board_key.h"
  8. #include "at_surf_f437_board_joystick.h"
  9. #include <stdio.h>
  10. #else
  11. #include "lvgl/lvgl.h"
  12. #endif


步骤六 增加lv tick 驱动

图5. Iv tick 驱动添加
433556682604ae92ae.png
步骤七 main 函数调用lvgl 相关函数
  1. #include "at32f435_437_clock.h"
  2. #include "at_surf_f437_board_lcd.h"
  3. #include "at_surf_f437_board_usart.h"
  4. #include "lv_port_disp_template.h"
  5. #include "lv_port_indev_template.h"
  6. #include "at_surf_f437_board_delay.h"
  7. #include "at_surf_f437_board_touch.h"
  8. #include "at_surf_f437_board_joystick.h"
  9. #include "lv_tick_custom.h"
  10. #include <stdint.h>
  11. #include <string.h>
  12. #include "lvgl.h"
  13. #include "at_surf_f437_board_key.h"
  14. extern void lv_demo_benchmark(void);
  15. /** @addtogroup AT32F437_periph_template
  16. * @{
  17. */
  18. /** @addtogroup 437_LED_toggle LED_toggle
  19. * @{
  20. */
  21. /**
  22. * [url=home.php?mod=space&uid=247401]@brief[/url] main function.
  23. * @param none
  24. * @retval none
  25. */
  26. int main(void)
  27. {
  28. system_clock_config();
  29. delay_init();
  30. uart_print_init(115200);
  31. printf("init ok\r\n");
  32. pca9555_init(PCA_I2C_CLKCTRL_100K);
  33. lcd_init(LCD_DISPLAY_VERTICAL);
  34. touch_init(TOUCH_SCAN_VERTICAL);
  35. lv_init();
  36. lv_port_disp_init();
  37. lv_port_indev_init();
  38. lv_demo_benchmark();
  39. /* for littlevgl gui tick increase */
  40. tmr7_int_init(287, 999);
  41. lv_tick_set_cb(millis);
  42. while(1)
  43. {
  44. lv_task_handler();
  45. }
  46. }


步骤八 其他步骤
完成案例还需以下步骤
a) 删除at32f435_437_board.c 文件及其头文件路径
b) 添加i2c_application.c 和surf 板级支持文件及其头文件路径到keil 工程中
c) 修改at32f435_437_int.c 文件,参考案例代码

图6. 添加其余文件
426796682622550ddb.png
注意:若程序异常,进入Hardfault,可检查堆栈大小是否不足,如果是此原因,可在启动文件中修改。
案例使用
本章节介绍如何使用已建立LVGL 工程,在AT-SURF-F437 板子上快速体验LVGL BenchMark 案例
效果。
a) 打开Template.uvprojx 工程文件,路径如下
AN0221_SourceCode_V2.0.0\project\at_start_f437\templates\mdk_v5
为加快调试下载速度,建议选AT Link Winusb,如下图。
图7. 选择AT Link WinUSB

60912668260774ecec.png

b) 下载程序到AT-SURF-F437,观察LV BenchMark demo 的测试结果
图8. BenchMark 显示结果
80026668260f5a2b32.png










AN0221_Quickly_Creat_LVGL_V9_Project_By_LV_CMSIS_PACK_ZH_V2.0.1.pdf

1.32 MB, 下载次数: 30

WXX菜鸡 发表于 2024-11-20 19:07 | 显示全部楼层
大佬,有基于FreeRTOS移植LVGL9的例程吗?整个来参考一下
菜鸟的第一步 发表于 2024-11-24 19:03 | 显示全部楼层
雅特力连LVGL的界面开发软件都有了。开发环境太好了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

215

主题

2077

帖子

37

粉丝
快速回复 在线客服 返回列表 返回顶部