请选择 进入手机版 | 继续访问电脑版
搜索
查看: 33532|回复: 37

[原创] 开源GUI LittlevGL 移植

  [复制链接]

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2023-6-21
发表于 2017-9-7 22:39:54 | 显示全部楼层 |阅读模式
本帖最后由 creep 于 2018-1-13 19:14 编辑

    推荐阅读最新的Littlevgl移植(更新时间:2018-1-13):
  
    开源GUI  LittlevGL  V5.0版本移植      


LittlevGL 是一个开源免费的GUI,支持触摸屏操作,移植简单方便,开发者一直在不断完善更新。LittlevGL 自带了丰富的控件:窗口、按键、标签、list、图表等,还可以自定义控件;支持很多特效:透明、阴影、自动显示隐藏滚动条、界面切换动画、图标打开关闭动画、平滑的拖拽控件、分层显示、反锯齿等等。


下面是我在STM32F769-DISCO上移植的演示模式的效果图片.




TIM图片20170907220239.jpg TIM图片20170907220247.jpg

主要控件可以通过下面的图片有个基本的了解:


2017-09-06_115730.png
1、移植

LittlevGL 的移植非常简单,用户只需要提供systick、触摸屏、LCD显示接口即可。源码里面有3个文件用于分别添加这3个接口,具体如下:

0895ef3e-bcca-43d2-9e1d-7a9a21b4723e.png

也就是下面几个函数:


  • hal/disp disp_fill(x1, y1, x2, y2, color) to fill area with a color
  • hal/disp disp_map(x1, y1, x2, y2, &color_array) copy a color map to an area
  • hal/disp disp_color_cpy(dest, src, length, opa) copy pixel, optional for GPU
  • hal/indev indev_get(id, &x, &y) get the x and y coordinates from an input device (e.g. touch pad)
  • hal/systick systick_get() get a system tick with 1 ms resolution
  • hal/systick systick_elapse(prev_time) get the elapsed milliseconds sience prev_time

a)systick的移植直接使用的是HAL库里面提供的

  1. /**
  2. * Get the elapsed milliseconds since start up
  3. * @return the elapsed milliseconds
  4. */
  5. uint32_t systick_get(void)
  6. {
  7.         return HAL_GetTick();
  8. }
  9. /**
  10. * Get the elapsed milliseconds science a previous time stamp
  11. * @param prev_tick a previous time stamp from 'systick_get'
  12. * @return the elapsed milliseconds since 'prev_tick'
  13. */
  14. uint32_t systick_elaps(uint32_t prev_tick)
  15. {
  16.         volatile uint32_t act_time = systick_get();

  17.         /*If there is no overflow in sys_time
  18.          simple subtract*/
  19.         if(act_time >= prev_tick) {
  20.                 prev_tick = act_time - prev_tick;
  21.         } else {
  22.                 prev_tick = UINT32_MAX - prev_tick + 1;
  23.                 prev_tick += act_time;
  24.         }
  25.         return prev_tick;
  26. }
复制代码
b)提供触摸屏的函数,用于初始化触摸屏和返回触摸屏扫描结果
  1. /**
  2. * Initialize your input devices here
  3. */
  4. void indev_init(void)
  5. {
  6.   BSP_TS_Init(DISP_HOR_RES, DISP_VER_RES);
  7. }

  8. /**
  9. * Read an input device
  10. * @param indev_id id of the input device to read
  11. * @param x put the x coordinate here
  12. * @param y put the y coordinate here
  13. * @return true: the device is pressed, false: released
  14. */
  15. bool indev_get(uint8_t indev_id, int16_t * x, int16_t * y)
  16. {
  17.         if(indev_id != 0) {
  18.                 *x = 0;
  19.                 *y = 0;
  20.                 return false;
  21.         }
  22.         static int16_t last_x = 0;
  23.         static int16_t last_y = 0;
  24.         bool press;
  25.         BSP_TS_GetState(&TS_State);
  26.         if(TS_State.touchDetected != 0) {
  27.                 *x = TS_State.touchX[0];
  28.                 *y = TS_State.touchY[0];
  29.                 press = true;
  30.         } else {
  31.                 *x = last_x;
  32.                 *y = last_y;
  33.                 press = false;
  34.         }

  35.         return press;
  36. }
复制代码
c)LCD的移植分为几个函数,

1)一个是用单一色填充矩形区域,这个实际调用的次数较小


  1. /**
  2. * Fill a rectangular area with a color
  3. * @param x1 left coordinate of the rectangle
  4. * @param x2 right coordinate of the rectangle
  5. * @param y1 top coordinate of the rectangle
  6. * @param y2 bottom coordinate of the rectangle
  7. * @param color fill color
  8. */
  9. void disp_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, color_t color)
  10. {
  11.     /*Return if the area is out the screen*/
  12.     if(x2 < 0) return;

  13.     if(y2 < 0) return;

  14.     if(x1 > DISP_HOR_RES - 1) return;

  15.     if(y1 > DISP_VER_RES - 1) return;

  16.     /*Truncate the area to the screen*/
  17.     int32_t act_x1 = x1 < 0 ? 0 : x1;
  18.     int32_t act_y1 = y1 < 0 ? 0 : y1;
  19.     int32_t act_x2 = x2 > DISP_HOR_RES - 1 ? DISP_HOR_RES - 1 : x2;
  20.     int32_t act_y2 = y2 > DISP_VER_RES - 1 ? DISP_VER_RES - 1 : y2;

  21.     LCD_FillRectPart(act_x1, act_y1, act_x2 - act_x1 + 1, act_y2 - act_y1 + 1, ((color.full)));
  22. }
复制代码
2)这个是用一个颜色map填充一个矩形区域,这个主要用显示时局部刷新使用,是LCD显示调用的底层接口,使用非常频繁,如果需要优先显示速度,可以从这个函数入手,使用块内存复制或者DMA2D来实现。
  1. /**
  2. * Put a color map to a rectangular area
  3. * @param x1 left coordinate of the rectangle
  4. * @param x2 right coordinate of the rectangle
  5. * @param y1 top coordinate of the rectangle
  6. * @param y2 bottom coordinate of the rectangle
  7. * @param color_p pointer to an array of colors
  8. */
  9. void disp_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const color_t * color_p)
  10. {
  11.     /*Return if the area is out the screen*/
  12.     if(x2 < 0) return;

  13.     if(y2 < 0) return;

  14.     if(x1 > DISP_HOR_RES - 1) return;

  15.     if(y1 > DISP_VER_RES - 1) return;

  16.     /*Truncate the area to the screen*/
  17.     int32_t act_x1 = x1 < 0 ? 0 : x1;
  18.     int32_t act_y1 = y1 < 0 ? 0 : y1;
  19.     int32_t act_x2 = x2 > DISP_HOR_RES - 1 ? DISP_HOR_RES - 1 : x2;
  20.     int32_t act_y2 = y2 > DISP_VER_RES - 1 ? DISP_VER_RES - 1 : y2;


  21.     uint32_t y;

  22.     for(y = act_y1; y <= act_y2; y++)
  23.     {
  24.         memcpy(&my_fb[y * DISP_HOR_RES + act_x1],
  25.                color_p,
  26.                (act_x2 - act_x1 + 1) * sizeof(my_fb[0]));
  27.         color_p += x2 - x1 + 1;    /*Skip the parts out of the screen*/
  28.     }

  29. }
复制代码
3)硬件加速可选项打开后可以使用下面的函数复制加速填充复制内存
  1. /**
  2. * Copy pixels to destination memory using opacity
  3. * @param dest a memory address. Copy 'src' here.
  4. * @param src pointer to pixel map. Copy it to 'dest'.
  5. * @param length number of pixels in 'src'
  6. * @param opa opacity (0, OPA_TRANSP: transparent ... 255, OPA_COVER, fully cover)
  7. */
  8. void disp_color_cpy(color_t * dest, const color_t * src, uint32_t length, opa_t opa)
  9. {
  10.     /*Wait for the previous operation*/
  11.     HAL_DMA2D_PollForTransfer(&Dma2dHandle, 100);

  12.     Dma2dHandle.LayerCfg[1].InputAlpha = opa;
  13.     HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1);
  14.     HAL_DMA2D_BlendingStart(&Dma2dHandle, (uint32_t) src, (uint32_t) dest, (uint32_t)dest, length, 1);
  15. }
复制代码
移植了上面接口之后基本问题就不大了,littlevgl 目前的代码结构有点乱,分为core、hal、misc 几个部分,我是分别建立一个文件夹然后把相应的文件全部添加到里面了,官网也没有详细的移植说明文档。所有的源码如下:
830d99b5-4b7a-45d6-bdbc-e56085de3ef1.png
添加到工程中后如下整体如下:



3446ef89-270c-4dd3-8658-84f3ba39c9c6.png

将所有的文件添加到工程中后用keil编译可能会有一些错误和警告出现,但都很好解决。


2、运行效果

LittlevGL内置一个类似桌面系统的演示例子,通过打开相应的宏定义即可



6b77cfc1-d927-422c-9a91-f5f6b01ed4d7.png

LittlevGL有个桌面上模拟的工程,下面是论坛网友 @QianFan  在linux下运行官方例子的运行效果:


X$SK81@USA577AHK@1B@E_C.gif

除此之外官网还有一个在STM32F429-DISOC上移植的例子,在youtube上可以观看,因为转换为了gif可能看起来不是很流畅,实际演示效果很不错。


test1.gif

下面是我在STM32F769-DISOC上面的移植,和linux下模拟运行的差不多。因为769-disco的分辨率很高,移植后我没有使用优化,所以可以看到画面切换有些闪烁。
IMG_0253.GIF

3、关于LittlevGL

    LittlevGL里面有个简单的时间片调度系统,刷新显示和触摸处理等任务会周期的被调用处理。LCD刷新采用了局部缓存刷新,这样能避免闪烁出现。LittlevGL目前只有一个开发者在业余时间维护更新,但是开发者热情很高,可以在github上看到更新很频繁,我测试的使用的V4.2版本,开发者正在开发4.3版本并加入了不少新的功能,有建议可以在github和作者讨论互动。
目前代码结构看上去有点乱,有人在也提到了这个问题,计划好像是在5.0版本引入新的代码组织结构,感兴趣的可以去github提意见,开发者很乐意沟通讨论。官网也有不少控件的使用介绍和例子参考。



9360da2f-c19f-499f-950b-613fb29b2857.png


官网和github地址如下:

LittlevGL官网:http://www.gl.littlev.hu/
LittlevGLgithub :http://github.com/littlevgl   和  http://github.com/littlevgl/lvgl

下面2个视频是在PC Simulator (Linux)和F4-DICO上的移植演示可能需要科学的方式才能打开。
How to Run Littlev Graphics Library in PC Simulator (Linux):http://youtu.be/ZzLdct2ymvg
Embedded GUI on STM32 Discovery with Littlev Free Graphics Library:http://youtu.be/DcJdK137WKM

  和众多开源的RTOS不一样,目前GUI开源的不是很多,虽然很多商用的GUI也很炫酷,但是我们没法知道具体效果的实现细节,也没法学习到这种能力,LittlevGL目前实现的一些特性和控件我认为是开源的GUI里面水平非常高的了。但是目前LittlevGL资料不是很多,只能通过阅读源码去学习和研究。


测试代码:

LittlevGL-STM32F769-DISCO.rar (4.72 MB, 下载次数: 865)

评分

参与人数 2ST金币 +21 收起 理由
mcbot + 1 little VGL群,526465246 大家一起来学习.
zero99 + 20 大佬玩的好溜

查看全部评分

回复

使用道具 举报

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2023-6-21
 楼主| 发表于 2018-12-2 17:03:42 | 显示全部楼层
ioremap 发表于 2018-11-30 17:25
我遇到个大问题,求回复,空间没颜色的

看到一个别人分享的开源中文教程。
开源GUI-littevGL应用教程 V0.1.pdf (3.14 MB, 下载次数: 485)
回复 支持 1 反对 0

使用道具 举报

该用户从未签到

47

主题

3456

帖子

30

蝴蝶豆

版主

最后登录
2022-12-25
发表于 2017-9-7 23:33:35 | 显示全部楼层
跟着大佬学习。。。
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

6

帖子

0

蝴蝶豆

中级会员

最后登录
2017-12-29
发表于 2017-9-8 07:34:07 | 显示全部楼层
wow。感觉真不错
谢谢楼主分享
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

180

帖子

0

蝴蝶豆

金牌会员

最后登录
2020-10-7
发表于 2017-9-8 08:02:24 | 显示全部楼层
厉害厉害
回复

使用道具 举报

该用户从未签到

77

主题

2004

帖子

5

蝴蝶豆

论坛元老

最后登录
2021-1-6
发表于 2017-9-8 08:48:53 | 显示全部楼层
现在的代码有点乱,图形界面依赖其他的misc,HAL等库。在github中提意见,将gui部分确实需要的部分集成到gui中,其余没用的部分剥离出去。
回复 支持 反对

使用道具 举报

该用户从未签到

20

主题

1130

帖子

125

蝴蝶豆

论坛元老

最后登录
2019-5-4
发表于 2017-9-8 08:53:59 | 显示全部楼层
这个不错,赞一个
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

1002

帖子

363

蝴蝶豆

版主

最后登录
2021-4-15
发表于 2017-9-8 09:22:45 | 显示全部楼层
已经关注了一波。。。可以看看!!!!
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

253

帖子

0

蝴蝶豆

金牌会员

最后登录
2020-10-28
发表于 2017-9-8 09:23:21 | 显示全部楼层
学习新知识,快乐
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

16

帖子

0

蝴蝶豆

初级会员

最后登录
2018-12-6
发表于 2017-9-8 13:47:08 | 显示全部楼层
LittlevGL有个桌面上模拟的工程,下面是论坛网友 @QianFan  在linux下运行官方例子的运行效果:


如何模拟?  如何在linux中运行?

回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

16

帖子

0

蝴蝶豆

初级会员

最后登录
2018-12-6
发表于 2017-9-8 14:30:15 | 显示全部楼层
LittlevGL 相比 ucgui 的优势?

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-3-29 09:35 , Processed in 1.235142 second(s), 51 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表