原创 基于MiniStm32的uCGUI移植

2012-12-22 15:23 3381 26 28 分类: MCU/ 嵌入式

 

一直都想能够学会使用一种嵌入式图形用户软件,前阵子开始听说uCGUI,于是花大力气在网上查资料,然后试着移植到自己的miniSTM32板子上,昨天终于移植成功,今天特地写这篇文章记录一下自己的学习成果,方便以后查阅,同是希望能给像我一样的初学者一点帮助。非常感谢www.openedv.com论坛网友提供的资料和网友开水提供的视频教程。

 

其实移植uCGUI非常简单,简单到你无需对uCGUI内核源码有过多了解,就我现在的状况,可以说是对uCGUI内核一无所知,但照样可以进行移植。我们唯一需要准备的就是一个硬件平台(我手上是正点原子的mini开发板)和已经写好了的可以裸跑的LCD驱动程序(同样我的驱动程序都是随光盘附带),因此我做的移植工作几乎就是整理一下文件而已,一点都没有技术含量。因此实现的功能就很简单了,就是:

stm32官方固件库3.5版+裸奔uCGUI3.9版,不带操作系统也不带触摸屏。

实现的功能就是板子上一个led灯的闪烁,还有TFT液晶屏上不断输出“Hello  world!”

简陋得不能再简陋了!

不过我自认我的工程项目设置比较适合初学者,目录设置比较清楚明了。呵呵~

 

我的工程文件夹名字为uCGUI_Demo,与工程的名字一致。下面是我的工程文件夹在windows管理器下的文件目录:

20121220123537359001.jpg

其中,项目文件就全部放在工程的根目录下,list和obj文件夹的作用相信熟练keil建立工程的人一看便知。STM32F10Xxxxxxxx那个文件夹就是ST的官方固件库,我从网上下载,没有做任何改动,所以里面的文件藏得比较深,反正我是已经习惯了不更改任何东西,不习惯的人可以自己整理整理,呵呵。

SYSTEM文件夹里的东西如下:

20121220123541433002.jpg

这个文件夹包含了与我的硬件平台紧密相关的文件,比如采用systick写的延时函数delay.c和液晶屏的驱动程序ILI93XX..c,那个font.h文件也属于液晶屏驱动的一部分,被ILI93XX.c文件包含。这里需要说明的是,由于我是直接用正点原子的驱动代码,而代码是采用寄存器操作方式,所以SYSTEM文件夹里的文件都没有用到固件库,但这依然不影响我们再main函数里或者是其他地方使用固件库。

最后那个USER文件夹里的文件如下:

20121220123545338003.jpg

这个无需任何说明了,都是基于库建立工程约定俗成的方式。

 

好了,接下来是我们所要关注的重点文件夹GUI,GUI文件夹包含了uCGUI的源码,其目录如下:

20121220123550897004.jpg

其实,uCGUI的官方推荐目录是把Config文件夹独立出来,但是我觉得这样放对于我们移植到stm32下更方便,更清楚。

 

好了,说完了windows管理器下的目录,接下来看keil工程下的目录:

20121220123557572005.jpg

仔细看那些展开了的目录每项都包含了哪些文件。

其实uCGUI有很多可选择包含文件,由于我是最简单化移植,不带触摸屏也不带操作系统,因此所需包含的文件就很少了。

另外,在设置keil的包含路径include paths的时候,有些人习惯将uCGUI所有文件夹都包含进来,当然这样是不会有问题,但这恰恰是对c语言的细节不太关注的表现。事实上,用标准C开发程序,添加到工程中的只需要.c源文件就行,.h头文件是没有必要添加到工程目录的,当然有时候为了方便修改就例外,比如上面我就把GUIConfig.h和LCDConfig.h添加到了我的工程里,实际上整个Gonfig目录都可以去掉。既然不用添加.h文件,编译软件是怎么找到头文件的呢?那就是设置编译器的包含路径了。Keil就是设置include paths找到需要的头文件的。这同样说明,如果某个文件夹里没有任何项目所需头文件,那就根本不需要将该文件夹设置成包含路径!

uCGUI官方文档上也说明了,只需要且必须包含如下路径:

20121220123603363006.jpg

 

下面就说明怎样来移植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!”

 

 

文章评论2条评论)

登录后参与讨论

用户377235 2013-7-22 12:24

用户1004684 2013-1-16 08:44

感谢楼主分享,学习啦!
相关推荐阅读
用户423038 2012-12-26 09:35
利用序列的DTFT来分析被采样模拟信号的频谱----我的一点理解
       假设被采样的模拟信号为x(t)=sin(Ω0t+∅),其周期为T0,频率 为f0;        采样周期为Ts,  则采样后得到的序列为x(n)=sin(w0n+∅), ...
用户423038 2012-12-26 09:34
时域抽取基2FFT算法C程序注解
/*********************************************************************    简介:此程序包是通用的快速傅里叶变换C语...
用户423038 2012-12-26 09:33
由DFT来分析模拟信号频谱的过程之我的理解
   所谓信号的频谱,就是信号的傅里叶变换,就是信号的频域特性。           我们知道,连续时间信号的傅里叶变换所得信号的频谱函数是模 拟角频率Ω的连续函数;而对连续时间信号...
用户423038 2012-12-26 09:33
因果实序列可以完全由其奇分量或偶分量恢复
        首先,任意实序列都可以分解成奇序列和偶序列之和。 即x[n]=xe[n]+xo[n],其中,xe[n]=(x[n]+x[-n])/2,xo[n]=(x[n]-x[-n])/2。...
用户423038 2012-12-26 09:31
(*(volatile unsigned long *)用法
           对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语...
用户423038 2012-12-26 09:29
傅里叶变换的物理意义
        傅里叶变换的实质是将一个信号分离为无穷多多正弦/复指数信号的加成,也就是说,把信号变成正弦信号相加的形式——既然是无穷多个信号相加,那对于非周期信号来说,每个信号的加权应该都是零—...
我要评论
2
26
关闭 站长推荐上一条 /2 下一条