ucgui在嵌入式linux下的移植
前几天在研究minigui,照着官方的步骤编译,竟然一堆错,不是缺这库,就是缺那库。好不容易快到了最后一步,竟然再链接时告诉我用的64位系统不兼容32位的minigui。
早不说呀,真折腾,这是让我再重装个32位系统么。想出来个helloworld,竟在编译环境上浪费时间,太坑。也不喜欢minigui的为win32风格,应用都得在他的框架下写,必须得有入口函数。类似于win32的api编程,很原始,连个界面的长宽高都要自己去定义。也没有好用的可视化的窗口设计及仿真环境。其实,如果没有那么多的人机交互,比如车载pos,不需要这些吧。不如直接调用显示接口函数,比如想显示个内容,直接LCD_DisplayString()来的容易。
用 ucgui还有个好处是,只要应用做稳定了,界面根本不会卡死或down掉。因为界面就像一个画布,让显示什么,什么时候显示,都是受应用控制的,界面是被动的。但是,如果应用跑在miniGUI的框架下,如果界面消息循环阻塞,或者minigui挂掉,整个应用就完了。且minigui的让显示什么,就发个消息,然后在主线程对消息就行处理再显示,感觉像是平白无故兜了一圈。完全没有直接操作屏幕爽。让什么时候显示什么直接LCD_Display,安全稳定。当然,这只针对目前的应用而言,界面不那么重要。如果是靠界面取胜的应用,都这么来会很累。
无意间发现了一个好东西,ucgui,这在原来单片机stm32上跑过,以及ucosII。之前也用过。ucgui占用资源很少,在stm32等单片机上都能跑,在linux 上更是没一点儿问题。
而且超轻量级,代码很好移植。甚至因为小巧,可以用来学习研究GUI用,或者增加定制些功能。
同事说这么小巧的东西在linux上有点儿不搭吧,linux那么强大,应该首先考虑minigui和QT。但是我我举得对于目前正在做的新项目而言,不需要界面太花哨,功能稳定就行,先快速出来产品再说吧。先整出来个界面用用,毕竟也不占多少精力。越是简单小巧越容易掌控,不容易掉坑里。
对于一款智能pos来说,从功能上无非是 卡处理、记录存储、通信、显示、这几块功能。目前 通信库,和文件存储库都已封装好。把显示也搞定了,就剩封装读卡库了。最后再实现个多线程框架把这些轮子组装起来,就是一完整 pos 了,也不是什么难事。难在接口封装和风格尽量要做到和原来一致啊,要不那么多地方的应用,移植是件痛苦的事。
进一步查资料发现,用这个 ucgui,电脑上还有模拟器可以用,那么界面设计部分,完全可以在电脑上仿真啦。这样,想设计个漂亮的界面出来,也不难啊。别抱怨说界面原生丑陋,那是没经过设计。至于是否支持中文,以及字体有哪些,那就自己画呗,用工具生成各种需要的中文字库导进去。 想让界面漂亮些,那自己画呗,正好考验下有没艺术细胞。反正画着也挺简单的,最底层的画点画线基本函数都有了。甚至可以移植gif解码库,让支持更多类型的图片动画。后续准备加入常用的中文字库支持。以及gif动画支持。
官方的模拟器 emWin(UCGUI)模拟器。在电脑上有模拟器啊,这是不是很赞。
移植之后,使用也很简单 。就一个libucgui.a库文件和gui.h头文件包含进来即可。
使用类似这样:
#include <stdio.h>
#include "GUI.h"
int main(int argc, char* argv[])
{
char c;
printf("this is ucgui-linux test!n");
GUI_Init();
GUI_SetBkColor(GUI_BLUE);
GUI_Clear();
GUI_SetColor(GUI_WHITE);
GUI_SetTextAlign(GUI_TA_HCENTER);
GUI_SetFont(&GUI_Font16B_ASCII);
GUI_DispStringAt("hello world, ucgui-linux",240,100);
GUI_DrawCircle(100,100,50);//画圆
printf("system pausen");
while ((c = getchar()) != 'n');
system("pause");
return 0;
}
先来张运行成功的截图:
又发现ucGUI一个强大功能,竟可以windows上设计界面自动生成代码,带仿真执行功能。附图:是不是很赞,这是minigui远远不能及的....
连带电脑上的代码编写仿真环境都有,
进入正题,移植minigui,
很好移植,把底层调用的几个函数,用linux上的frambuffer实现就可以了。
具体文件是LCDDummy.c那么文件 里的LCD_L0_Init(void),LCD_L0_SetPixelIndex,LCD_L0_GetPixelIndex,这三个函数,实现这三个函数。
/*********************************************
*
* LCD_L0_Init
*
**********************************************
Purpose:
Initialises the LCD-controller.
*/
int LCD_L0_Init(void) {
return fb_init();
}
/*********************************************
*
* LCD_L0_SetPixelIndex
*
**********************************************
Purpose:
Sets the index of the given pixel. The upper layers of emWin
calling this routine make sure that the coordinates are in range, so
that no check on the parameters needs to be performed.
*/
void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {
/* Convert logical into physical coordinates (Dep. on LCDConf.h) */
#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
int xPhys = LOG2PHYS_X(x, y);
int yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
/* Write into hardware ... Adapt to your system */
{
/* ... */
fb_setpixel(480, 272, xPhys, yPhys, PixelIndex);
}
}
/*********************************************
*
* LCD_L0_GetPixelIndex
*
**********************************************
Purpose:
Returns the index of the given pixel. The upper layers of emWin
calling this routine make sure that the coordinates are in range, so
that no check on the parameters needs to be performed.
*/
unsigned int LCD_L0_GetPixelIndex(int x, int y) {
LCD_PIXELINDEX PixelIndex;
/* Convert logical into physical coordinates (Dep. on LCDConf.h) */
#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
int xPhys = LOG2PHYS_X(x, y);
int yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
/* Read from hardware ... Adapt to your system */
{
PixelIndex = 0;/* ... */
PixelIndex = fb_readpixel(480, 272, xPhys, yPhys);
}
return PixelIndex;
}
#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>
static unsigned char* npu8_fbmem;
static int ns32_fb;
static unsigned int nu32_screensize;
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 fb0n");
return -1;
}
if( _fb_stat(ns32_fb, &fbw, &fbh, &fbd) < 0 ) return -1;
printf("%d, %d, %dn", fbw, fbh, fbd);
nu32_screensize = fbw * fbh * fbd / 8;
npu8_fbmem = _fb_mmap(ns32_fb, nu32_screensize);
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);
*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);
return *dst;
}
最后,要在linux上编译,写个makefile吧,简单省事。写完后配置下工具链直接make即可。
########################################
##makefile
########################################
#****************************************************************************
# Cross complie path
#****************************************************************************
#CHAIN_ROOT=/home/yangyongzhen/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-
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
#****************************************************************************
CFLAGS= -I./GUI_X -I./GUI/Core -I./GUI/WM -I./GUI/Widget
LDSCRIPT=
LDFLAGS=
#****************************************************************************
# Targets of the build
#****************************************************************************
TARGET := libucgui
.PHONY: clean
all: prebuild $(TARGET).a
#****************************************************************************
# TARGET
#****************************************************************************
prebuild:
@echo Building lib...
$(TARGET).a : $(OBJS)
@echo Generating lib...
ar crv $(TARGET).a $(OBJS)
cp $(TARGET).a ../
@echo OK!
%.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
clean:
@echo The following files:
rm -f $(TARGET) *.a
find . -name "*.[od]" |xargs rm
@echo Removed!
- Lucene.Net 删除索引DeleteDocuments的注意事项
- 使用VS2010的Database 项目模板统一管理数据库对象
- 利用c#制作托盘程序,并禁止多个应用实例运行
- dotNET跨平台相关文档整理
- .NET Core 2.0 正式发布信息汇总
- iis7.0上发布mvc4.0网站
- 遍历文件夹所有文件(示例)
- Visual Studio 2017 : client version 1.22 is too old
- httphandler和httpmodule的区别
- 每周.NET前沿技术文章摘要(2017-06-21)
- Access数据库多表连接查询
- Lucene2.1 的官方示例代码
- 使用NUnit在.Net编程中进行单元测试
- 在CentOS上使用Jexus托管运行 ZKEACMS
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 利用Libra进行机器学习和深度学习
- I2C总线架构 之 总线驱动
- 一文讲透“布隆过滤器”
- 基于PySpark的流媒体用户流失预测
- 盘一盘 Python 特别篇 21 - 分箱之 qcut
- 挖洞经验 | 以SSRF获取Zimbra邮件服务的用户明文凭据
- Office文件追踪方案探索
- 如何全方位地给 SQL Server 做测试
- 下下下一代防火墙关键技术漫谈
- Mysql事务隔离级别
- ent orm笔记1---快速尝鲜
- UsoDllLoader:一款功能强大的武器化特权文件写入工具
- 宇智波程序笔记10-为什么你使用的 Spring Security OAuth 过期了
- 无线电侧信道攻击利用复现:监听显示器显示内容
- typeScript 配置文件该怎么写?