芯源半导体CW32
直播中

zealsoft

3年用户 688经验值
擅长:可编程逻辑,嵌入式技术
私信 关注

【CW32饭盒派开发板试用体验】移植GUILite

感谢电子发烧友论坛和武汉芯源所提供的CW32饭盒派开发板的测试机会。

CW32饭盒派有一块1.77寸的彩色液晶屏,160*128点阵大小,方便显示内容,但是CW32饭盒派只提供非常简单的图形相关API,显示效果有限,不能满足我们的日常需求。本文介绍将目前很热门的嵌入式图形库GUILite移植到CW32的方法。

1. GUILite简介

GUILite是个非常轻量级的图形库,只有4千行C++代码,基本上是零依赖,只需要将单一头文件库(GuiLite.h)加入到工程就可以使用。它支持各种操作系统,甚至于可以在裸机的单片机上运行。它的API和Qt/MFC这些API很接近,所以有图形界面开发经验的朋友很容易上手。

GUILite可以从https://gitee.com/idea4good/GuiLite或者https://github.com/idea4good/GuiLite下载。这个网站提供的分开的多个头文件和C++文件,然后利用CMake生成GuiLite.h文件。

2. 在CW32饭盒派上移植的基本步骤

移植工作一般并不是从前面提到的那个官方网站开始,而是从官方提供的一系列示例(https://gitee.com/idea4good/GuiLiteSamples)开始,这些示例一般都在百行左右,能够充分体现GUILite的特点。下面我们就以HelloStar示例开始我们的移植工作。

饭盒派在其“实验七 TFT彩屏实验”中提供了基本的驱动函数和示例程序。如果想在程序中使用其LCD显示功能,只需要把TFT目录中的内容加到工程中即可。我们可以从该工程出发来添加GUILite的文件。

我们只需要将HelloStar\UIcode目录下的GuiLite.h和UIcode.cpp两个文件加入到我们的工程中即可。

对主程序main.c的修改

在主程序中不要直接包含GuiLite.h文件,因为这个文件中包含大量C++的定义,在C语言文件中无法使用。

在C语言中加入以下定义:

struct DISPLAY_DRIVER
{
	void(*draw_pixel)(int x, int y, unsigned int rgb);
	void(*fill_rect)(int x0, int y0, int x1, int y1, unsigned int rgb);
} cw32driver;

#define GL_RGB_32_to_16(rgb) (((((unsigned int)(rgb)) & 0xFF) >> 3) | ((((unsigned int)(rgb)) & 0xFC00) >> 5) | ((((unsigned int)(rgb)) & 0xF80000) >> 8))

void DrawPoint(int x, int y, unsigned int rgb)
{
	Gui_DrawPoint(x, y, GL_RGB_32_to_16(rgb));
}


void delay_ms(unsigned short nms)
{
	delay1ms(nms);
}

结构体DISPLAY_DRIVER是移植的核心,它包括画点和画矩形两个函数指针。其中画点是必须提供的,而画矩形是可选的。CW32的LCD控制是通过I2C接口提供的,所以画矩形函数指针不提供对性能影响不是很大,不过对于内存映射的设备而言,用画点函数去填充整个区域会相当慢。在这里的画点函数DrawPoint就是直接调用了CW32官方驱动所提供的Gui_DrawPoint函数,只是做了颜色转换,从RGB888转换为RGB565。

在GUILite官方提供的示例中都有一个startHelloXXX的函数启动其示例。对于HelloStar而言,startHelloStar的定义是这样的:

extern void startHelloStar(void* phy_fb, int width, int height, int color_bytes, struct DISPLAY_DRIVER* driver);

在main函数中,添加以下代码以启动程序:

struct DISPLAY_DRIVER cw32driver;
cw32driver.draw_pixel = DrawPoint;
cw32driver.fill_rect = NULL;
startHelloStar(NULL, 128, 160, 2, &cw32driver);

对UIcode.cpp的修改

虽然我们在调用startHelloStar指定了宽度和高度,但是UIcode.cpp通常还有另外一组参数表示宽度和高度,就是

#define UI_WIDTH 240
#define UI_HEIGHT 320

这两个参数也需要根据我们的屏幕大小进行修改:

#define UI_WIDTH 128
#define UI_HEIGHT 160

修改后编译、链接、下载,就可以看到运行效果了。

VID2023052117221200-00-04[20230521-175446280].jpg

3. 其他几个示例的移植效果

Hello3D示例

Hello3D示例是一个能够充分展示GUILite魅力的例子。对main.c的修改和HelloStar基本相同,除了把startHelloStar改成startHello3D。对UIcode.cpp的修改则要多一些,因为绝大多数示例中显示位置和大小都是固定的,不能根据屏幕大小自动适应,而官方用于测试的屏幕尺寸比CW32的大很多。

主要修改包括调整形状的大小:

#define UI_WIDTH	128
#define UI_HEIGHT	160
#define SHAPE_SIZE	25

create_ui函数也需要修改,以调整显示的位置:

while(1) {
		theCube.draw(60, 40, true);//erase footprint
		theCube.rotate();
		theCube.draw(60, 40, false);//refresh cube

		thePyramid.draw(60, 110, true);//erase footprint
		thePyramid.rotate();
		thePyramid.draw(60, 110, false);//refresh pyramid
		thread_sleep(50);
	}

VID2023052117211300-00-16[20230521-175655266].jpg

HelloPendulum示例

这是一个展示钟摆效应的例子。首先需要修改常数定义:

#define UI_WIDTH 128
#define UI_HEIGHT 160
#define SQUARE_SIZE_1 10
#define SQUARE_SIZE_2 14

然后需要修改摆动的范围:


	int r1 = 45;
	int r2 = 45;
	int x1 = 0;
	int x2 = 0;
	int y1 = 0;
	int y2 = 0;
	float m1 = 25;
	float m2 = 50;

同样需要修改create_ui函数以改变显示位置:

while (true)
	{
		s_mode ? pendulum::draw(60, 50, "Gui", "Lite") : pendulum::draw(60, 50);
		thread_sleep(30);
	}

从这段代码我们还可以看出,钟摆有两种显示效果,一个是显示文字Gui Lite,另一个是显示方框,这两种显示效果是利用s_mode变量实现的。改变这个变量的取值可以看到两种不同的效果。

在HelloPendulum中提供了sendKey2HelloPendulum函数,将这个函数和按键中断相关联,就可以得到不同的显示效果。

VID2023052117194200-00-19[20230521-175420246].jpg

VID2023052117194200-00-08[20230521-175409672].jpg

这几个示例的完整运行效果可以参见视频:https://www.bilibili.com/video/BV1Uk4y1s7RG/。在移植过程中,我们仅用了厂商提供的CW32的LCD驱动,有兴趣的朋友可以优化一下这个驱动以提升性能。

更多回帖

发帖
×
20
完善资料,
赚取积分