玲珑GUI介绍

玲珑GUI(LLGUI)是一套使用简单、低价的单片机GUI解决方案。可以用来代替串口屏、组态,降低产品成本,产品软硬件自主可控。 配套界面开发软件,图形化编辑界面,生成C代码。

如其名字玲珑小巧,代码量不大,纯c语言写的,适用各类资源受限的单片机mcu,且开源免费。(协议使用Apache License, Version 2.0,可以二次开发类GPL,非二次开发类使用Apache,多许可协议的方式。

资料地址

教程地址:玲珑GUI教程 · 语雀

Gitee地址:LingLongGUI: 玲珑GUI是高效的界面开发解决方案。 代替串口屏、组态,降低产品成本,产品软硬件自主可控。 配套界面开发软件,图形化编辑界面,生成C代码。

交流QQ群:QQ群1:1004783094 QQ群2:473465075

简单体验

简单体验了一把,感觉挺不错的,在这里推荐下。

尤其是它还提供了类似QT的可视化的GUI界面编辑器GUIBulider,可以可视化的编辑UI。同时还提供了类似于QT的信号和曹机制真心不错。虽然基础控件还不够多,比如常见的label控件没找到(作者说可以使用Text替代,我觉得label挺常用的,还是能有个单独的label组件比较好)。但是对于嵌入式应用差不多够用了,就像官方的介绍一样,可作为替代串口屏的一种低价的单片机GUI解决方案。

期待后续有更多好用的组件出来,期望llgui作为国产开源中的一员不断发展壮大。至少截止目前,配合这么好用的GUIBulider,可以和LittlevGL比个高下了。虽然组件丰富度不如LittlevGL,但是使用的易用性上还是这个小巧易用啊,类QT但比QT小巧太多,很有特色。

也希望作者开源出来一些自定义组件的方法和文档或教程,这样更利于生态扩建,丰富更多好用的组件。如一些仪表、曲线、table、chart等。

关于中文字库的支持方面(文档,示例等)期待再完善些。可能目前主要是瞄准嵌入式mcu上,在嵌入式linux上其实可以完善些常用字库。

GUIBulider长这样,有一种QT设计师的风格:

可以直接拖动编辑界面UI,最右侧可以更改属性。下方可以编辑发送者,信号和接收者。

点击工具栏上的绿色三角图标,自动生成对应的ui代码和对应的逻辑层处理代码文件。

嵌入式linux上的移植

在嵌入式linux上的移植(底层基于framebuffer的fb0):

新建一文件夹test,在里面新建llgui,ui和port文件夹。

其中llgui放置从gitee上下载到的最新llgui的源码。port文件夹放置跟移植相关的内容。ui文件夹里放置ui和ui的响应逻辑实现文件。

移植还是很简单的,实现LL_Config.c中的几个函数即可。主要的三个函数:画点和读点,填充矩形的函数。十分钟完整移植,此言不虚。

头文件LL_Config.h里做些配置:

...
颜色位数
#define CONFIG_COLOR_DEPTH                    16 // 1 8 16 24 32
//屏幕宽度像素
#define LL_MONITOR_WIDTH                      480
//屏幕高度像素
#define LL_MONITOR_HEIGHT                     272

LL_Config.c文件

#include "LL_Config.h"
#include "string.h"
#include "freeRtosHeap4.h"
#include "io_fb.h"uint8_t cfgColorDepth = CONFIG_COLOR_DEPTH;
uint16_t cfgMonitorWidth = 0;
uint16_t cfgMonitorHeight = 0;#if USE_DOUBLE_BUFFERING == 1
uint32_t *lcdFrontBuf=LL_LCD_BUF1_POINTER;
uint32_t *lcdBackBuf=LL_LCD_BUF2_POINTER;
#endifvoid llCfgSetLcdBufAddr(uint32_t *addr)
{
#if USE_DOUBLE_BUFFERING == 1lcdSetBufferAddr(addr);
#endif
}void llCfgSetLcdSrcAddr(uint32_t *addr)
{
#if USE_DOUBLE_BUFFERING == 1lcdSetSrcAddr(addr);
#endif
}void llCfgLcdCopyFront2Back(void)
{
#if USE_DOUBLE_BUFFERING == 1
//    memcpy(lcdBackBuf,lcdFrontBuf,SDRAM_LCD_SIZE);uint64_t i;for(i=0;i<SDRAM_LCD_SIZE;i++){lcdBackBuf[i]=lcdFrontBuf[i];}
#endif
}bool llCfgClickGetPoint(int16_t *x,int16_t *y)
{bool ret;return ret;
}void llCfgSetPoint(int16_t x,int16_t y,llColor color)
{fb_setpixel(LL_MONITOR_WIDTH,LL_MONITOR_HEIGHT,x,y,color);
}llColor llCfgGetPoint(int16_t x,int16_t y)
{llColor retColor;retColor = fb_readpixel(LL_MONITOR_WIDTH,LL_MONITOR_HEIGHT,x,y);return retColor;
}void LCD_L0_SetPixelIndex(int x, int y, llColor color) {fb_setpixel(LL_MONITOR_WIDTH, LL_MONITOR_HEIGHT, x, y, color);
}
void LCD_L0_DrawHLine (int x0, int y,  int x1,llColor color) {for (; x0 <= x1; x0++) {LCD_L0_SetPixelIndex(x0, y, color);}
}
void llCfgFillSingleColor(int16_t x0,int16_t y0,int16_t x1,int16_t y1,llColor color)
{for (; y0 <= y1; y0++) {LCD_L0_DrawHLine(x0, y0, x1,color);}
}void *llMalloc(uint32_t size)
{return malloc(size);
}void llFree(void *p)
{free(p);p=NULL;
}void *llRealloc(void *ptr,uint32_t newSize)
{return realloc(ptr,newSize);
}void llExFlashInit(void)
{
}void llReadExFlash(uint32_t addr,uint8_t* pBuffer,uint16_t length)
{
}void llBuzzerBeep(void)
{
}/***************************************************************************//*** @fn         void llGetRtc(uint8_t *readBuf)* @brief      读取年月日时分秒周* @param      *readBuf yy yy mm dd hh mm ss ww* @return     void* @version    V0.1* @date       * @details    数据用16进制储存,2021年 yyyy=0x07E5******************************************************************************/
void llGetRtc(uint8_t *readBuf)
{
}/***************************************************************************//*** @fn         void llSetRtc(uint8_t *writeBuf)* @brief      写入年月日时分秒* @param      *writeBuf yy yy mm dd hh mm ss* @return     void* @version    V0.1* @date       * @details    数据用16进制储存,2021年 yyyy=0x07E5******************************************************************************/
void llSetRtc(uint8_t *writeBuf)
{
}

  io_fb.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/fb.h>#define printV(v)                printf(#v"=%d\n", v);static unsigned char*  npu8_fbmem;
static int             ns32_fb;
static unsigned int    nu32_screensize;static unsigned char   displaybuffer[480*272*4];
static unsigned char*  pframebuffer;
static unsigned char   pfbStat = 0;        //0-framebuffer, 1-cache bufferunsigned char getGUIcache(void);int setGUIcache(unsigned char stat);void GUIcache2fb(void);static void* _fb_mmap(int fd, unsigned int screensize)
{caddr_t fbmem;if ((fbmem = mmap(0, screensize, PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0)) == MAP_FAILED) {perror(__func__);return (void *) (-1);}return fbmem;
}static int _fb_munmap(void *start, size_t length)
{return (munmap(start, length));
}static int _fb_stat(int fd, unsigned int *width, unsigned int *height, unsigned int *depth)
{//struct fb_fix_screeninfo fb_finfo;struct fb_var_screeninfo fb_vinfo;//if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) {//    perror(__func__);//    return -1;//}if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {perror(__func__);return -1;}*width  = fb_vinfo.xres;*height = fb_vinfo.yres;*depth  = fb_vinfo.bits_per_pixel;return 0;
}int fb_init(void)
{ unsigned int  fbw, fbh, fbd;ns32_fb = open("/dev/fb0", O_RDWR);if(ns32_fb<0){printf("can not open fb0\n");return -1;}if( _fb_stat(ns32_fb, &fbw, &fbh, &fbd) < 0 ) return -1;printf("%d, %d, %d\n", fbw, fbh, fbd);nu32_screensize = fbw * fbh * fbd / 8;npu8_fbmem = _fb_mmap(ns32_fb, nu32_screensize);setGUIcache(0);return 0;
}void fb_deinit(void)
{ close(ns32_fb);_fb_munmap(npu8_fbmem, nu32_screensize);
}int fb_setpixel(int width, int height, int x, int y, unsigned short color)
{if ((x > width) || (y > height))return -1;//unsigned short *dst = ((unsigned short *)npu8_fbmem + y * width + x);unsigned short *dst = ((unsigned short *)pframebuffer + y * width + x);*dst = color;return 0;
}unsigned short fb_readpixel(int width, int height, int x, int y)
{if ((x > width) || (y > height)) return -1;//unsigned short *dst = ((unsigned short *)npu8_fbmem + y * width + x);unsigned short *dst = ((unsigned short *)pframebuffer + y * width + x);return *dst;
}unsigned char getGUIcache(void)
{//printf("%s\n", __FUNCTION__);return pfbStat;
}int setGUIcache(unsigned char stat)
{//printf("%s\n", __FUNCTION__);if( stat ) {pframebuffer = displaybuffer;pfbStat      = 1;} else {pframebuffer = npu8_fbmem;pfbStat      = 0;}return 0;
}void GUIcache2fb(void)
{printf("%s\n", __FUNCTION__);memcpy( npu8_fbmem, displaybuffer, nu32_screensize);
}

最后是makefile文件,更改下交叉编译工具链,直接执行make即可。

附:makefile文件:

########################################
##makefile template by yangyongzhen
########################################
#****************************************************************************
# Cross complie path
#****************************************************************************
# CHAIN_ROOT=/home/yang/imax283/ctools/gcc-4.4.4-glibc-2.11.1-multilib-1.0/arm-fsl-linux-gnueabi/bin# CROSS_COMPILE=$(CHAIN_ROOT)/arm-none-linux-gnueabi-CHAIN_ROOT= /opt/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin
CROSS_COMPILE=$(CHAIN_ROOT)/arm-linux-gnueabihf-
#CROSS_COMPILE = CC     := $(CROSS_COMPILE)gcc
CXX    := $(CROSS_COMPILE)g++
AS     := $(CROSS_COMPILE)as
AR     := $(CROSS_COMPILE)ar
LD     := $(CROSS_COMPILE)ld
RANLIB := $(CROSS_COMPILE)ranlib
OBJDUMP:= $(CROSS_COMPILE)objdump
OBJCOPY:= $(CROSS_COMPILE)objcopy
STRIP  := $(CROSS_COMPILE)strip#****************************************************************************
# Source files
#****************************************************************************
SRC_C=$(shell find . -name "*.c")OBJ_C=$(patsubst %.c, %.o, $(SRC_C))SRCS := $(SRC_C) $(SRC_C)OBJS := $(OBJ_C) #****************************************************************************
# Flags
#****************************************************************************
LIBS := -LLIBS
INCS := -I./llgui/Gui -I./llgui/Misc -I./Fonts -I./port -I./ui -I./
CFLAGS= -std=gnu99  -fno-common  -fsanitize=address -fno-stack-protector -fno-omit-frame-pointer -fno-var-tracking -g1
LDSCRIPT=
LDFLAGS= -lasan
#****************************************************************************
# Targets of the build
#****************************************************************************
TARGET      := testllgui
TARGETLIB   := libllgui.PHONY: clean
all:  prebuild  $(TARGET)lib:  prebuild  $(TARGETLIB).so#****************************************************************************
# TARGET
#****************************************************************************
prebuild:@echo Building...$(TARGET): $(OBJS)@echo Generating exe...$(CC)   -o  $(TARGET) $(OBJS) $(LIBS) $(LDFLAGS)@echo OK!$(TARGETLIB).so : $(OBJS)@echo Generating shared lib...$(CC)  -shared -fPIC -o  $(TARGETLIB).so $(OBJS) @echo OK!%.o : %.c$(CC) -c -fPIC $(CFLAGS) $(INCS) $< -o  $@clean:@echo The following files:rm  -f  $(TARGET) *.sofind . -name "*.[od]" |xargs rm@echo Removed!

最后把编译生成的可执行文件,放在板子上,改下执行权限,直接运行即可。

推荐一款不错的嵌入式GUI(玲珑GUI)及在嵌入式linux上的移植相关推荐

  1. 全光谱护眼灯有哪些?推荐几款不错的全光谱灯

    全光谱护眼灯是近几年兴起的一个产品种类,主打的就是类太阳光的全光谱照明,使灯光下的物体色彩真实.自然,无限接近太阳光,从而达到使眼睛更舒适.保护眼睛的目的. 所谓全光谱,就是指灯光的色谱成分无限接近太 ...

  2. 市面上哪款蓝牙耳机音质比较好?推荐四款不错的蓝牙耳机

    蓝牙耳机经过长足发展,性能配置方面也越来越高,越来越先进.主打各种性能的蓝牙耳机应有尽有,其中,主打音质的蓝牙耳机也有不少,很多人购买耳机第一大因素就是音质,当然,随着耳机越来越多,大家都不知道该如何 ...

  3. python编辑器安装视频教程_Python安装教程(推荐一款不错的Python编辑器)

    网工2.0已来,网络工程师单单会路由交换已经不吃香了, 所以,这里提倡广大网络工程师抽空学习编程,至少掌握一门编程语言, 后续可以用于自动化运维. 因此,本期为大家分享了python安装教程,供大 家 ...

  4. 推荐8款不错的HTML5文本编辑器

    如果你是一名Web开发人员,当你需要开发一个独特的网站时,你就会知道文本编辑器的重要性.小编为大家整理了8款非常前沿的HTML5文本编辑器,简化开发流程,喜欢就转走吧! Mercury Editor ...

  5. 选择什么样的台灯灯光是好的?推荐几款不错的护眼台灯

    常生活中,灯光对于我们来说,重要性不言而喻,学习.办公等环境都需要合适的光线,所以一般来说,都会准备一款台灯,特别是对于长期使用电脑的设计师.影像绘图设计人员.学生这类长时间用眼.使用电脑的人员.更需 ...

  6. 测试拳击速度软件,有没有专门看拳击的app?推荐一款不错的拳击app

    现在很多人对于拳击这项运动的热情很高,人们会持续在线搜索各类拳击软件,大部分用户对于拳击比赛以及学习拳击的兴趣很大,但是这两种功能好多软件都是拆开观看或者直接是一个软件,今天小编发现了一款不错的拳击软 ...

  7. 开放耳机有什么优缺点,推荐几款不错的开放式耳机

    ​由于骨传导耳机可以保持耳朵的开放,长时间佩戴不会有闷热感,同时可以在运动中保持安全,因此被越来越多的人接受.在目前市面上骨传导耳机品牌众多,价格从几十元到上千元不等,为了让大家更好地挑选适合自己的骨 ...

  8. 推荐几款不错的写作利器

    建议阅读时长 3 分钟 Typora Typora 是一款免费的写作工具,支持所有的 Markdown 语法,所写即所现 整理文件:Typora 提供文件树面板和文章(文件列表)面板,使您可以轻松管理 ...

  9. 推荐几款不错的 Mac 文字处理器

    无论您是需要软件来创作最新史诗.小说的专业作家,还是只需要制作文档.报告.时事通讯和其他基于文本的任务的人,macOS 都是正确的选择.从极简的无干扰应用程序到功能齐全的办公套件,mac可供选择的优质 ...

最新文章

  1. [BTCC] 要“工程师”“工程师”“工程师”
  2. 轻量级数据库Sqlite的使用
  3. 自定义控件只允许输入Decimal和int类型字符串
  4. async js 返回值_图文讲解浏览器执行JS过程中的微任务和宏任务
  5. java 08_java 08 权限修饰符 编译运行
  6. 数据库乐观锁如何实现幂等性?
  7. Python -- post方式上传文件
  8. vue图片查看控件v-viewer使用
  9. Python 测试驱动开发(四)测试及重构的目的(上)
  10. 华为一季度每天入账20亿,首次披露云业务用户超100万
  11. hibernate反向工程
  12. 解决Ubuntu 14.04下CodeBlocks缩进异常问题
  13. 让电脑「读懂」你的思想——java工程师的职业规划
  14. ASIO Link Pro 声卡跳线(搭配福克斯特solo声卡)
  15. [渝粤教育] 中国地质大学 工业卫生技术 复习题
  16. Jeshoots - 类别齐全的高质量免费商业摄影图库
  17. 模型保存文件.npy
  18. C语言short转成int,short转换int的小例子
  19. Codeforces - Reachable Strings
  20. AUTODESK 卸载工具,完美彻底卸载清除干净autodesk各种软件残留注册表和文件

热门文章

  1. (附源码)node.js电商管理系统毕业设计251001
  2. Linux系统性能监测工具——CPU
  3. 【历史上的今天】2 月 18 日:电池的发明者出生;全美最大的电脑连锁店开业;Netsky 蠕虫问世
  4. MSP430F5529-定时器介绍
  5. 百度地图行政区优化卡顿问题
  6. nginx利用ngx_http_geoip2_module模块对国外ip限制
  7. 每日一分享C语言代码(The first day)
  8. cocos2dx+VS2019环境配置
  9. CUDA:CUDA out of memory. Tried to allocate 100.00 MiB (GPU 0; 15.78 GiB total capacity; 14.24 GiB al
  10. 计算机应用模块等级考试大纲,计算机等级考试大纲最新.doc