一直都想能够学会使用一种嵌入式图形用户软件,前阵子开始听说uCGUI,于是花大力气在网上查资料,然后试着移植到自己的miniSTM32板子上,昨天终于移植成功,今天特地写这篇文章记录一下自己的学习成果,方便以后查阅,同是希望能给像我一样的初学者一点帮助。非常感谢www.openedv.com论坛网友提供的资料和网友开水提供的视频教程。
其实移植uCGUI非常简单,简单到你无需对uCGUI内核源码有过多了解,就我现在的状况,可以说是对uCGUI内核一无所知,但照样可以进行移植。我们唯一需要准备的就是一个硬件平台(我手上是正点原子的mini开发板)和已经写好了的可以裸跑的LCD驱动程序(同样我的驱动程序都是随光盘附带),因此我做的移植工作几乎就是整理一下文件而已,一点都没有技术含量。因此实现的功能就很简单了,就是:
stm32官方固件库3.5版+裸奔uCGUI3.9版,不带操作系统也不带触摸屏。
实现的功能就是板子上一个led灯的闪烁,还有TFT液晶屏上不断输出“Hello world!”
简陋得不能再简陋了!
不过我自认我的工程项目设置比较适合初学者,目录设置比较清楚明了。呵呵~
我的工程文件夹名字为uCGUI_Demo,与工程的名字一致。下面是我的工程文件夹在windows管理器下的文件目录:
其中,项目文件就全部放在工程的根目录下,list和obj文件夹的作用相信熟练keil建立工程的人一看便知。STM32F10Xxxxxxxx那个文件夹就是ST的官方固件库,我从网上下载,没有做任何改动,所以里面的文件藏得比较深,反正我是已经习惯了不更改任何东西,不习惯的人可以自己整理整理,呵呵。
SYSTEM文件夹里的东西如下:
这个文件夹包含了与我的硬件平台紧密相关的文件,比如采用systick写的延时函数delay.c和液晶屏的驱动程序ILI93XX..c,那个font.h文件也属于液晶屏驱动的一部分,被ILI93XX.c文件包含。这里需要说明的是,由于我是直接用正点原子的驱动代码,而代码是采用寄存器操作方式,所以SYSTEM文件夹里的文件都没有用到固件库,但这依然不影响我们再main函数里或者是其他地方使用固件库。
最后那个USER文件夹里的文件如下:
这个无需任何说明了,都是基于库建立工程约定俗成的方式。
好了,接下来是我们所要关注的重点文件夹GUI,GUI文件夹包含了uCGUI的源码,其目录如下:
其实,uCGUI的官方推荐目录是把Config文件夹独立出来,但是我觉得这样放对于我们移植到stm32下更方便,更清楚。
好了,说完了windows管理器下的目录,接下来看keil工程下的目录:
仔细看那些展开了的目录每项都包含了哪些文件。
其实uCGUI有很多可选择包含文件,由于我是最简单化移植,不带触摸屏也不带操作系统,因此所需包含的文件就很少了。
另外,在设置keil的包含路径include paths的时候,有些人习惯将uCGUI所有文件夹都包含进来,当然这样是不会有问题,但这恰恰是对c语言的细节不太关注的表现。事实上,用标准C开发程序,添加到工程中的只需要.c源文件就行,.h头文件是没有必要添加到工程目录的,当然有时候为了方便修改就例外,比如上面我就把GUIConfig.h和LCDConfig.h添加到了我的工程里,实际上整个Gonfig目录都可以去掉。既然不用添加.h文件,编译软件是怎么找到头文件的呢?那就是设置编译器的包含路径了。Keil就是设置include paths找到需要的头文件的。这同样说明,如果某个文件夹里没有任何项目所需头文件,那就根本不需要将该文件夹设置成包含路径!
uCGUI官方文档上也说明了,只需要且必须包含如下路径:
下面就说明怎样来移植uCGUI到自己的硬件平台。
uCGUI说白了就是一个软件包,方便用户调用,使得用户在不同的LCD硬件平台下实现类似的操作可以采样完全相同的软件代码,它就是要屏蔽掉底层的硬件细节。那么说来,必须有一个途径来使得uCGUI和用户的硬件平台通信握手。对于我的项目来说,硬件平台就相当于工程里的ILI93XX.c,就是已经写好了的LCD驱动程序。而这个通信握手的途径就是LCDDriver文件夹里的LCDDummy.c文件和Congfig文件夹下的LCDConfig.h文件(有网友说LCDDiver文件夹下任何一个.c文件都可以作为握手文件,我没有验证,就使用了LCDDummy.c)。因此,移植的工作就是要修改这两个文件!使得uCGUI内核能够通过这两个文件(握手途径)找到我们的硬件平台(即ILI93XX.c文件)。这里需要注意的就是,我们的LCD驱动程序函数名称和文件名称一定不能和uCGUI内核使用的名称相同。
由于我的移植例程非常简单,需要uCGUI的功能很少,那么uCGUI所需要的握手途径也只要很少,需要准备好正常运行的LCD驱动程序只有以下三个驱动函数:
TFT_Init( );//LCD的初始化函数
TFT_ReadPoint( ); //LCD读取定点颜色函数,读取一个像素点的16位RGB颜色值
TFT_DrawPoint( ); //LCD画点函数, 用指定颜色填充一个像素
通过点的操作,uCGUI就可以调用进行线和面的操作了。
好了下面是我的LCDConf.h文件代码
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef LCDCONF_H
#define LCDCONF_H
#define LCD_XSIZE (320) /* X-resolution of LCD, Logical coor. */
#define LCD_YSIZE (240) /* Y-resolution of LCD, Logical coor. */
//#define LCD_BITSPERPIXEL (8)
#define LCD_BITSPERPIXEL (16)
#define LCD_FIXEDPALETTE (565)
#define LCD_SWAP_RB (1)
//#define LCD_SWAP_XY (1)
#define LCD_INIT_CONTROLLER() TFT_Init();
#define LCD_CONTROLLER 4531
#endif /* LCDCONF_H */
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
上面红色表示的部分非常重要,uCGUI就是通过LCD_INIT_CONTROLLER()这个宏来对应我们的LCD初始化函数,也就是说TFT_Init()函数是LCD驱动程序里的初始化函数,它的位置处在硬件平台ILI93XX.c文件里。
下面是LCDDummy.C文件的部分代码
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "LCD_Private.h" /* private modul definitions & config */
#include "LCD_Private.h"
#include "GUI_Private.h"
#include "GUIDebug.h"
#include "ILI93xx.h"
#if (LCD_CONTROLLER == 4531)
#ifndef LCD_INIT_CONTROLLER
#define LCD_INIT_CONTROLLER()
#endif
//根据坐标画点函数
void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {
TFT_DrawPoint(x, y, PixelIndex);
}
//获得坐标像素信息函数
unsigned int LCD_L0_GetPixelIndex(int x, int y) {
return TFT_ReadPoint(x, y);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
该文件一定要包含include "ILI93xx.h",这样uCGUI才能找到驱动程序,可以看到,uCGUI正是通过这个文件成功找到了驱动程序。
到目前为止,我们已经完成了移植uCGUI百分之九十九的工作,但是uCGUI本身也是有很多可裁剪项的,最后我们需要设置GUIConf.h文件。
下面是GUIConf.h文件的内容:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef GUICONF_H
#define GUICONF_H
#define GUI_OS (0) /* Compile with multitasking support */
#define GUI_SUPPORT_TOUCH (0) /* Support a touch screen (req. win-manager) */
#define GUI_SUPPORT_UNICODE (1) /* Support mixed ASCII/UNICODE strings */
#define GUI_DEFAULT_FONT &GUI_Font6x8
//#define GUI_ALLOC_SIZE 12500 /* Size of dynamic memory ... For WM and memory devices*/
#define GUI_ALLOC_SIZE 5000 /* Size of dynamic memory ... For WM and memory devices*/
/*********************************************************************
*
* Configuration of available packages
*/
#define GUI_WINSUPPORT 0 /* Window manager package available */
#define GUI_SUPPORT_MEMDEV 0 /* Memory devices available */
#define GUI_SUPPORT_AA 0 /* Anti aliasing available */
#endif /* Avoid multiple inclusion */
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
可以看到,我们有很多可选项,比如可以选择是否需要操作系统,是否需要触摸屏,等等。
注意的是,如果要移植操作系统uC/OS,就需要添加GUI_X_uCOS.c文件,需要使用触摸屏就需要添加GUI_X_Touch.c文件,这两个文件都在uCGUI_Demo\GUI\GUI_X文件夹中。
到目前为止,已经完成了移植uCGUI的全部工作。
下面就是直接在main函数里调用API了。
下面是我的main.c文件部分代码:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
u8 i=0;
rcc_cfg();
gpio_cfg();
delay_init(72);//切记要调用次函数,否则程序将无法运行
GUI_Init();
/* Infinite loop */
while (1)
{
/* Set PA8 */
if(i<10)
{
i++;
GUI_DispString("Hello world!\n\n");
}
else
{
i=0;
GUI_Clear();
GUI_GotoXY(0,0);
}
GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
M_delay();
/* Reset PA8 */
GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
M_delay();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
可以看到,mini板上连接到PA8上的led不停的闪烁,且TFT液晶屏上不断输出”Hello world!”
用户377235 2013-7-22 12:24
用户1004684 2013-1-16 08:44