打印
[技术相关]

SWM32SRET6--LVGL移植

[复制链接]
7603|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
SynwitMCU|  楼主 | 2022-12-27 11:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 SynwitMCU 于 2022-12-27 11:40 编辑

SWM32SRET6硬件资源介绍:    SWM320是一款基于ARM Cortex-M4的32位微控制器,片上包含精度为1%以内的 20MHz/40MHz时钟,可通过PLL倍频到120MHz 时钟,提供多种内置FLASH/SRAM大小可供选择,支持ISP(在系统编程)操作及IAP(在应用编程)。
外设串行总线包括:
-1个CAN接口
-内部叠封8MB SDRAM
-多个UART接口
-SPI 通信接口(支持主/从选择)
-及I2C接口(支持主/从选择)
-此外还包括1个32位看门狗定时器
-6组32位通用定时器
-1组32位专用脉冲宽度测量定时器
-12通道16位的PWM发生器
-2个8通道12位,1MSPS的逐次逼近型ADC模块
-1个SDIO接口模块
-TFT-LCD液晶驱动模块以及RTC实时时钟、-SRAMC、NORFLC接口控制模块
-同时提供欠压检测及低电压复位功能。

LittlevGL移植
LittlevGL是一个免费的开放源代码图形库,它提供创建嵌入式GUI所需的一切,它具有易于使用的图形元素,精美的视觉效果和低内存占用。强大的构建块按钮,图表,列表,滑块,图像等,带有动画,抗锯齿,不透明度,平滑滚动的高级图形,各种输入设备的触摸板,鼠标,键盘,编码器等,多显示器支持,即同时使用更多的TFT和单色显示器,支持UTF-8编码的多语言,完全可定制的图形元素。独立于任何微控制器或显示器使用的硬件,可扩展以使用较少的内存(80kB闪存,12 kB RAM),支持操作系统,外部存储器和GPU,但不是必需的,即使使用单帧缓冲区操作,也具有高级图形效果。用C语言编写,以实现最大的兼容性(与C++兼容),模拟器可在没有嵌入式硬件的PC 上启动嵌入式GUI设计,快速GUI设计的教程,示例,主题,在线和离线文档,在 MIT 许可下免费和开源。
LittlevGL 官网:https://lvgl.io

LittlevGL硬件要求
-16、32或64位微控制器或处理器
-建议时钟频率大于16MHz
-闪存/ ROM:对于非常重要的组件,其大小大于64 kB(建议大于180 kB)
-内存:
-静态RAM使用量:大约8至16 kB,具体取决于所使用的功能和对象类型
-堆栈:大于2kB(建议大于4kB)
-动态数据(堆):大于4 KB(如果使用多个对象,则建议大于16 kB)。LV_MEM_SIZE 在lv_conf.h中设置
-显示缓冲区:大于“水平分辨率”像素(建议大于10× “水平分辨率”)
-C99或更高版本的编译器
-基本的C(或C ++)知识:指针,结构,回调

LittlevGL移植

LittlevGL 的移植过程也非常简单,
总结了以下几个步骤
1. 添加库文件到工程
2. 配置屏幕大小以及颜色深度等跟显示相关的参数
3. 分配一个显示缓冲区并实现屏幕填充的接口
4. 实现输入设备接口,读取触摸屏坐标
5. 实现文件系统接口,实现文件的读取写入
6. 提供一个滴答时钟的接口 lv_tick_inc();
7. 完成库的初始化以及接口的初始化 lv_init();lv_port_disp_init();lv_port_indev_init(); lv_port_fs_init;
8. 定期调用任务处理函数,可设置为 5-10ms lv_task_handler();

第一步,复制库文件
复制lvgl文件夹到工程文件夹APP下面。
将lvgl\lv_conf_template.h文件复制一份并改名为lv_conf.h。这个文件是lvgl的配置文件,后面再介绍如何修改。
将lv_examples文件夹复制到工程文件夹下面,这里面包含了各种应用和基础示例,我们后面需要使用。
第二步,添加库文件到工程
打开MDK工程,添加源码,在lvgl\src文件夹下面有如下文件,我们在MDK里面添加全部文件即可。
然后在MDK里面再新建一个lvgl_porting文件夹和一个lvgl_demo文件夹,前者用于添加接口文件,后者用于我们后面添加示例文件,将 lvgl\porting\lv_port_disp_template.c和lvgl\porting\lv_port_indev_template.c,lvgl\porting\lv_port_fs_template.c各复制一份,分别改名为lv_port_disp,c和lv_port_indev.c,lv_port_fs.c添加到MDK的lv_porting文件夹下面,后面再针对开发板的硬件进行对应的修改。

lvgl的源码中包含头文件有完整路径和简单路径两种方式,在MDK里面我们直接使用简单的头文件包含形式。
/*********************
*      INCLUDES
*********************/
#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lv_conf.h"
#else
#include "../../../lv_conf.h"
#endif

我们使用简单的头文件包含,在MDK的宏定义里面添加LV_CONF_INCLUDE_SIMPLE 定义,如果后面还有lvgl的头文件路径是MDK不能识别的,读者根据实际情况修改为编译器能识别的格式,后面不再对此修改做介绍。

修改lv_conf文件,在我们之前复制过来的配置示例文件默认是被注释掉了。我们需要打开他。只需要将开头的#if 0修改为#if 1即可,如果后续的文件中再出现这种开关,读者自行打开即可。
/*********************
*      INCLUDES
*********************/
#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lv_conf.h"
#else
#include "../../../lv_conf.h"
#endif

配置屏幕的大小,我们的液晶屏是480*272
/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX          (480)
#define LV_VER_RES_MAX          (272)

配置颜色位数,我们使用RGB565模式,16位色
/* Color depth:
* - 1:  1 byte per pixel
* - 8:  RGB233
* - 16: RGB565
* - 32: ARGB8888
*/
#define LV_COLOR_DEPTH     16

/* Swap the 2 bytes of RGB565 color.
* Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP   0

LVGL内存配置,这里区别与绘图缓冲区,这里配置的是lvgl的控件等使用的内存,需大于2KB,这里可以使用默认的32K配置,也可以将内存定义100K,从而分配更多的内存。
/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */
#define LV_MEM_CUSTOM      0
#if LV_MEM_CUSTOM == 0
/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
#  define LV_MEM_SIZE    (100 * 1024U)

GPU配置,这里关闭,我们使用LCD中断进行buffer的填充
/* 1: Enable GPU interface*/
#define LV_USE_GPU              0

LOG接口配置,这里暂未使用,读者在使用是可以将其配置为串口等
/*1: Enable the log module*/
#define LV_USE_LOG      0
#if LV_USE_LOG
/* How important log should be added:
* LV_LOG_LEVEL_TRACE       A lot of logs to give detailed information
* LV_LOG_LEVEL_INFO        Log important events
* LV_LOG_LEVEL_WARN        Log if something unwanted happened but didn't cause a problem
* LV_LOG_LEVEL_ERROR       Only critical issue, when the system may fail
* LV_LOG_LEVEL_NONE        Do not log anything
*/
#  define LV_LOG_LEVEL    LV_LOG_LEVEL_WARN

/* 1: Print the log with 'printf';
* 0: user need to register a callback with `lv_log_register_print_cb`*/
#  define LV_LOG_PRINTF   1
#endif  /*LV_USE_LOG*/

LittlevGL绘制的过程需要有一个缓冲区disp_buf,lvgl内部将位图绘制到这个缓冲区,缓冲区满了以后调用flush_cb接口函数进行屏幕的填充,我们将这部分缓冲区的内容通过LCD中断搬运到液晶屏,当填充完成后,调用lv_disp_flush_ready函数通知库绘制已经完成,可以开始其他绘制过程。
LittlevGL已经提供了一个示例文件,我们上面提到的复制文件也是使用他提供的文件,只需要我们修改几个接口函数即可。
定义lvgl绘制的缓冲区,这里需定义在外部SDRAM定义两个全屏的缓冲区。
static lv_disp_buf_t disp_buf;
#ifdef SWM_USING_SRAM
static lv_color_t lcdbuf_1[LV_HOR_RES_MAX * LV_VER_RES_MAX] __attribute__((at(SRAMM_BASE)))           = {0x00000000};
static lv_color_t lcdbuf_2[LV_HOR_RES_MAX * LV_VER_RES_MAX] __attribute__((at(SRAMM_BASE + 0x3FC00))) = {0x00000000};
#endif
#ifdef SWM_USING_SDRAM
static uint32_t lcdbuf_1[LV_HOR_RES_MAX * LV_VER_RES_MAX / 2] __attribute__((at(SDRAMM_BASE)))           = {0x00000000};
static uint32_t lcdbuf_2[LV_HOR_RES_MAX * LV_VER_RES_MAX / 2] __attribute__((at(SDRAMM_BASE + 0x3FC00))) = {0x00000000};
#endif
    lv_disp_buf_init(&disp_buf, lcdbuf_1, lcdbuf_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/

定义一个lv_disp_drv_t的变量并初始化。
lv_disp_drv_t disp_drv;      /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/

设置缓冲区。
/*Set a display buffer*/
    disp_drv.buffer = &disp_buf;

设置屏幕填充接口,这里的 disp_fluash 是一个函数,在示例中已经定义,我们直接对其修改就行了。
/*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;

注册驱动程序。
/*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);

修改disp_flush函数以适应我们自己的硬件和屏幕。
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    LCD->SRCADDR = (uint32_t)disp_drv->buffer->buf_act;
    LCD_Start(LCD);

    /* IMPORTANT!!!
     * Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

lvgl支持键盘、鼠标、按键、触摸屏作为输入设备,我们这里仅仅使用触摸屏进行输入。
在lv_port_indev_template.c中,注册一个触摸屏设备需要以下步骤,我们只需要对触摸屏读取的回调函数进行修改即可。

/*Register a touchpad input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = touchpad_read;
    indev_touchpad = lv_indev_drv_register(&indev_drv);

打开触摸屏读取的回调函数touchpad_read函数
* Will be called by the library to read the touchpad */
static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    static lv_coord_t last_x = 0;
    static lv_coord_t last_y = 0;

    /*Save the pressed coordinates and the state*/
    if (touchpad_is_pressed())
    {
        touchpad_get_xy(&last_x, &last_y);
        data->state = LV_INDEV_STATE_PR;
    }
    else
    {
        data->state = LV_INDEV_STATE_REL;
    }

    /*Set the last pressed coordinates*/
    data->point.x = last_x;
    data->point.y = last_y;

    /*Return `false` because we are not buffering and no more data to read*/
    return false;
}

从touchpad_read函数可以看出,用户只需要完成两个接口函数即可。这两个函数的实现如下:
/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{
    /*Your code comes here*/
    if(tp_dev.sta & 0x80)
    {
        return true;
    }
    return false;
}

/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
    /*Your code comes here*/

    (*x) = tp_dev.x[0];
    (*y) = tp_dev.y[0];
}

配置文件系统接口
文件系统使用FATFS,对接前需要完成文件系统的挂载。文件系统注册。
void lv_port_fs_init(void)
{
    /*----------------------------------------------------
     * Initialize your storage device and File System
     * -------------------------------------------------*/
    fs_init();

    /*---------------------------------------------------
     * Register the file system interface  in LittlevGL
     *--------------------------------------------------*/

    /* Add a simple drive to open images */
    lv_fs_drv_t fs_drv;
    lv_fs_drv_init(&fs_drv);

    /*Set up fields...*/
    fs_drv.file_size     = sizeof(file_t);
    fs_drv.letter        = 'P';
    fs_drv.open_cb       = fs_open;
    fs_drv.close_cb      = fs_close;
    fs_drv.read_cb       = fs_read;
    fs_drv.write_cb      = fs_write;
    fs_drv.seek_cb       = fs_seek;
    fs_drv.tell_cb       = fs_tell;
    fs_drv.free_space_cb = fs_free;
    fs_drv.size_cb       = fs_size;
    fs_drv.remove_cb     = fs_remove;
    fs_drv.rename_cb     = fs_rename;
    fs_drv.trunc_cb      = fs_trunc;

    fs_drv.rddir_size   = sizeof(dir_t);
    fs_drv.dir_close_cb = fs_dir_close;
    fs_drv.dir_open_cb  = fs_dir_open;
    fs_drv.dir_read_cb  = fs_dir_read;

    lv_fs_drv_register(&fs_drv);
}

配置LittlevGL的
嘀嗒心跳时钟接口
LittlevGL的使用需要需要周期性的时钟支持,用户需要定期调用 lv_tick_inc(uint32_t tick_period)函数,我们这里利用滴答定时器的1KHz去调用这个函数。在滴答定时器的中断服务函数中添加lvgl时基函数。
uint8_t tick_indev = 0;
void SysTick_Handler_cb(void)
{
    lv_tick_inc(1);
    tick_indev++;
    if (tick_indev > 100)
    {
        tick_indev = 0;
        GT911_Scan();
    }
}

初始化
包含lvgl的初始化以及显示和触摸,文件系统接口的初始化。
lv_init();
lv_port_disp_init();
    lv_port_indev_init();
    lv_port_fs_init();

我们需要在主循环中周期性调用LittelvGL的任务处理函数。
while (1 == 1)
{
        lv_task_handler();
}

然后就可以进行应用的开发了。





使用特权

评论回复

相关帖子

沙发
caigang13| | 2023-1-5 07:50 | 只看该作者
内部叠封8MB的SDRAM,不错啊。

使用特权

评论回复
板凳
SynwitMCU|  楼主 | 2023-1-5 09:23 | 只看该作者
目前我司已有内置16MB SDRAM产品,有需求欢迎咨询。

使用特权

评论回复
地板
sjnh| | 2023-1-5 13:25 | 只看该作者
SynwitMCU 发表于 2023-1-5 09:23
目前我司已有内置16MB SDRAM产品,有需求欢迎咨询。

有没有买芯片的连接网址

使用特权

评论回复
5
lcr12| | 2023-1-5 14:46 | 只看该作者
功能非常强

使用特权

评论回复
6
SynwitMCU|  楼主 | 2023-1-5 16:57 | 只看该作者
sjnh 发表于 2023-1-5 13:25
有没有买芯片的连接网址

可以上官方网站申请样品

使用特权

评论回复
7
zbx1981| | 2023-1-22 13:02 | 只看该作者
lvgl 9.0版本的运行怎么样啊,之前跑过8.x版本的,性能发挥一般,原厂建议我们跑7.x的版本,不知这个9.x版本的运行如何

使用特权

评论回复
8
软核硬核| | 2023-2-20 14:09 | 只看该作者
要是能做视频教程就好了,LVGL移植还是比较简单的。

使用特权

评论回复
9
LLGTR| | 2023-2-20 14:10 | 只看该作者
LVGL做动态效果挺不错的。

使用特权

评论回复
10
天天向善| | 2023-2-20 14:11 | 只看该作者
LVGL主要是开源,不收费,这点还是很给力的。

使用特权

评论回复
11
chenjun89| | 2023-4-10 07:46 | 只看该作者
内部8MB SDRAM不错啊。

使用特权

评论回复
12
lzbf| | 2023-6-5 10:18 | 只看该作者
提升 LVGL 帧率的方法有哪些

使用特权

评论回复
13
mikewalpole| | 2023-6-8 13:28 | 只看该作者
lvgl按键支持双击吗               

使用特权

评论回复
14
qiufengsd| | 2023-6-8 13:36 | 只看该作者
LVGlL8.2触摸不行?               

使用特权

评论回复
15
louliana| | 2023-6-8 13:41 | 只看该作者
在进行LVGL移植时,还需要考虑到不同操作系统和平台的差异

使用特权

评论回复
16
mattlincoln| | 2023-6-8 13:50 | 只看该作者
选择合适的LVGL版本,并下载相应的代码。

使用特权

评论回复
17
loutin| | 2023-6-8 13:59 | 只看该作者
lvgl如何做到控件闪烁               

使用特权

评论回复
18
beacherblack| | 2023-6-8 14:11 | 只看该作者
qt和lvgl谁用的多              

使用特权

评论回复
19
pentruman| | 2023-6-8 14:16 | 只看该作者
lvgl怎么画矩形不要圆角              

使用特权

评论回复
20
modesty3jonah| | 2023-6-8 14:54 | 只看该作者
lvgl的显示缓冲区为什么要乘2

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:广东华芯微特集成电路有限公司
简介:华芯微特是一家由留美归国资深技术团队创立的中国芯片设计公司,是国家高新技术企业。2014年进军MCU产业,专注于32位MCU研发设计,并针对细分市场提供参考解决方案。

30

主题

54

帖子

1

粉丝