最近一段时间以来,准备移植uCGUI。在网络上找了大量的移植资料和学习教程,但都没有什么突破性进展。不知道是自己水平有限,还是网络上的资料不够系统,总是不得入门之路。经过自己的不断努力,感觉移植并不是什么难事,关键是要知道移植的过程。现将学习中遇到的问题和已经记录下来,方面自己的翻阅,已可以为初学者提供一条捷径。
一、 uCGUI的了解: 在移植之前最好对uCGUI有一定的了解,这样会加快移植的速度,也可以减少不少弯路。 ①.最好通读一遍《uCGUI用户手册》,在网络上有很多。有中文版也有英文版的,里边详细的介绍了uCGUI的所有API函数及一些例程,并提供了配置说明。特别是从20章开始就跟移植有很大的关系,而前面的十几章主要是介绍应用。
②.对源代码要有所了解,当然这方面的介绍在《uCGUI用户手册》的第二章中也有。不过不同版本的文件夹有所不同,但内核基本是相同的就是加了些附加功能而已。
下表显示了GUI 所有子目录的内容:
(带“*”标志的为可选项,不同版本带的有所不同) 说明:移植是要特别注意配置文件Config和GUI/LCDDriver。 ①.GUI/LCDDriver文件夹中存放的是一些LCD驱动代码,如果你使用的LCD在这里可以找到代码,可以直接通过Config中的LCDConfig.h里边的: #define LCD_CONTROLLER -1 // -1:表示没有选择的LCD驱动,而是使用里边的样本程序进行修改。 uCGUI中具体支持哪些LCD?可以查询《uCGUI用户手册》的第22章 LCD驱动程序。里边详细的说明了,支持些什么控制器的LCD。 ②.在工程中只需加载需要的LCD驱动代码文件即可。如果设置为-1,则选择加载LCDDummy.C或LCDTemplate.C文件(不同的版本,此代码的文件名可能会不同)。
二、 代码移植: 1. 必须编写好LCD的驱动函数,当然如果uCGUI中已经包含了移植需要的LCD底层驱动,就不用再编写。如果没有就需要编写好LCD的底层驱动。底层驱动需要包含如下函数: ①.LCD_Init (): LCD初始化函数。 ②.LCD_SetPixel(): LCD画点函数。 ③.LCD_GetPixel(): LCD读点颜色函数。
2.编写好这三个函数后,可以直接在LCDDummy.C或LCDTemplate.C文件中添加相应的代码 ①.添加画点函数: void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) { /* Write into hardware ... Adapt to your system */ { /* ... */ 添加画点函数 } }
②.添加获取像素点颜色函数: unsigned int LCD_L0_GetPixelIndex(int x, int y) { /* Read from hardware ... Adapt to your system */ { PixelIndex = 0; /* ... */ 添加获取像素点颜色函数 } return PixelIndex; } ③.添加初始化函数: int LCD_L0_Init(void) { LCD_INIT_CONTROLLER(); // 把这句改成LCD_Init (); return 0; } 当然也可以直接在LCDConf.c文件中,把宏改成如下: #define LCD_INIT_CONTROLLER() TFTInit();
3. 以上方法是利用样本函数,当然也可以自己编写连接代码。如果是直接编写,则需要编写如下函数:
注意:红色为必须要实现的函数,其他函数可以为空,但必须保留函数体。
4. 在工程中添加uCGUI源代码和配置代码:
每个文件中只要添加相应的C文件即可,没有使用的部分可以不添加,LCDDriver中只要添加需要的LCD驱动代码即可。如果没有相应的LCD代码,而是使用样本代码,则只需要添加样本文件;如果是自己编写的代码,则添加自己的代码即可。
5. 设置包含路径,“Include”目录,确认你的Include 路径包括有以下目录(包括的先后顺序并不重要): Config GUI/Core GUI/Widget(如果使用视窗控件库) GUI/WM(如果使用视窗管理器) 警告:你必须确认你在每个文件中只使用了一个版本的μC/GUI
设置“include paths”
添加包含路径
6. 在例程中拷贝GUI_X文件夹中的文件: ①.GUI_X.C :无系统 ②.GUI_X_embOS.C :embOS系统 ③.GUI_X_uCOS.C :uCOS系统 根据不同条件添加不同文件,如果是无系统下添加文件①,否则根据系统添加文件,或编写文件。特别说明如下函数: a.int GUI_X_GetTime(void); 此函数调用系统时间如果你的系统有实时时钟之类的可以将实时时钟驱动程序放在这里面。没有也没关系只是调用系统时间相关的函数不能用而已,可能这个功能很多人也不会用。 b.void GUI_X_Delay(int Period); 此函数用于GUI的延时,如果没有跑系统,就自己手动的写个延时程序,如果跑了操作系统,就调用系统的延时函数。
在uCGUI中有很多地方都调用了以上函数,在其它的GUIDEMO_XXXX.C中也有这样一些循环,你要是调试是发现液晶屏上的显示一直停在一个画面上很久的话,应该就是以上函数的问题,需要根据需要修改。 三、应用说明: 1. 如果要根据自己的需要编写应用代码的话,需要认真阅读API函数,利用API函数必须自己的应用程序即可,如: void main(void) { int i=0; /* 要做的事:确认硬件首先初始化了! */ GUI_Init(); GUI_DispString("Hello world!"); while(1); }
2. 如果需要调用uCGUI例程,则需要添加GUIDemo文件夹及里边的全部文件,根据需要选择实例或调用GUIDEMO_main()函数。
四、注意事项: 1. 由于某些编译器(如:ADS1.2,MDK)不会初始化全局变量,部分内核必须修改,否则程序只工作一遍就不再工作。具体需要修改的地方如下,红色表示添加的代码: ①.修改如下函数为:(位于GUICore.c) static void _InitContext(GUI_CONTEXT* pContext) { …… pContext->PenSize = 1; pContext->DrawMode = GUI_DRAWMODE_NORMAL; pContext->TextMode = GUI_TEXTMODE_NORMAL; pContext->TextAlign = GUI_TA_LEFT|GUI_TA_TOP; pContext->AA_HiResEnable = 0; /* Variables in WM module */ } ②.修改如下函数为:(位于GUIAlloc.c) void GUI_ALLOC_Init(void) { ...... GUI_ALLOC.NumUsedBytes = 0; memset(&aBlock, 0, sizeof(aBlock[0])*GUI_MAXBLOCKS); aBlock[0].Size = (1<<GUI_BLOCK_ALIGN); /* occupy minimum for a block */ ...... }
③.修改如下函数为:(位于WM.c) void WM_Init(void) { if (!_IsInited) { ...... memset(&_ClipContext, 0, sizeof(WM_IVR_CONTEXT)); NextDrawWin = WM__FirstWin = WM_HWIN_NULL; ...... sInited = ; } }
2. 自己编写初始化变量函数,该函数应在GUI_Init()调用之前调用。 void MyInit() { IsInitialized = 0; // MemDev _IsInited = 0; // Win WM__CreateFlags = 0; GUI_CURSOR_pfTempHide = NULL; GUI_Context.hDevData = 0; WM__hCapture=0; WM__hWinFocus=0; WM_pfPollPID = 0; WM_pfHandlePID = 0; GUI_pfTimerExec = 0; _KeyMsgCnt = 0; }
总结: 经过多天的实验和多个版本的移植测试证明,以上移植方法实用与uCGUI的所有版本。本移植实验在我的《LPC2148开发板V2》验证通过;软件平台是MDK。 |
|