原创 ucGUI分析,仿真,移植

2011-1-3 15:53 3326 7 9 分类: 工程师职场
ucGUI 分析
嵌入式用户图形接口uC/GUI在uC/OSII上的嵌入
   uC/GUI是Micrium公司开发的通用的嵌入式用户图形界面软件。它给任何使用图形LCD的应用程序提供独立于处理器和LCD控制器之外的有效的图形用户接口。可以应用于单一任务环境,也可以应用于多任务环境中。uC/GUI能够应用于任何LCD控制器和CPU的任何尺寸的物理显示或者模拟显示中。
   uC/GUI的特点如下:
 ◆ 适用于任何8位/16位/32位CPU,可允许于支持ANSI C的任何编译器
 ◆ 适用于任何控制器驱动任何LCD(单色,灰度,或者彩色)
 ◆ 通过配置宏,可支持任何接口
 ◆ 可配置显示尺寸
◆ 可在LCD的任何一点上显示字符和画位图
◆ 对于显示尺寸和速度提供优化进程,编译时间依赖于采用的优化进程
◆  支持虚拟显示,虚拟显示的尺寸比实际显示大。
 4.2 uC/GUI文件组织
uC/GUI目录下的文件有配置文件目录Config,GUI库函数目录,以及为GUI编写的应用程序目录。下面分别简要介绍相应目录下的函数,更为详细的文件介绍请参考我的uC/GUI移植的源代码。
GUICONF.h:     配置GUI移植到不同操作系统的选项。在本论文中配置移植到uC/OSII中,允许多任务调用uC/GUI函数。
GUITouchConf.h:配置触摸屏的选项以及编写触摸屏的驱动。本文移植uC/GUI所使用的LCD屏不支持触摸屏,所以此文件为空。

LCD_Init.C:     LCD控制器的初始化文件。
LCD_Conf.h:    LCD显示屏的选项文件,包括bpp,调试板模式,水平、竖直方向的分辨率等等。
 这个目录中包含9个文件,处理显示的边缘模糊效果,也就是抗锯齿和优化LCD锯齿。液晶屏上画斜线往往都有锯齿,所以通过优化算法进行美化。
   这个目录中包含14个.C文件,涉及调色板模式。uC\GUI的调色板模式支持111模式,222模式,223,323,332,444,555,565,8666等相关模式。我在论文中使用的LCD屏,为单色16级灰度屏,因而不涉及到这些模式。但为了保持UC\GUI文件的完整性,该目录以及目录下14个文件,仍然保存在移植文件中。
  此目录下的文件描述单色显示的不同模式,包含4个文件。
  此目录下包含129个文件,是uC/GUI的核心部分。包括GUI头文件,GUI显示各种文本,二进制,十进制,十六进制,字符型文本,字符串,在不同的位置显示二进制,十进制,十六进制,字符型文本,字符串等;GUI设置各种字体;GUI的2-D图形库,GUI绘图函数,在各种位置绘各种点,线,位图,多边形,长方形,圆等等;GUI获取函数,获取当前点,线,位图,多边形,长方形,圆,当前字体,当前二进制,十进制,十六进制,字符型文本,字符串等函数;设置GUI画笔函数;GUI支持的鼠标函数;GUI支持的键盘函数,GUI支持的触摸屏函数;GUI设置LCD函数等等。这些函数,在uC/GUI系统中都是必须的函数。正是这些函数的组合,使得uC/GUI具有复杂而且完备的图形用户接口。而且,这些函数的组合,使得uC/GUI可以单独的使用,也可以通过配置文件,移植到各种操作系统中使用。
此目录下包含的是uC/GUI支持的字体。
LCD API目录。该目录下包含很多已经完备的LCD控制器的驱动程序以及API函数。
MemDev目录。
MemDev主要用于防止在画交迭图时产生的抖动。uC/GUI函数绘图不使用MemDev时,画图操作直接写到终端上显示,交迭绘图执行时刷新屏幕,多次刷新时就会出现抖动。例如,要在背景色中画图,且在前景中写一些透明的文字,实现的步骤就是先画图,然后写文字,那么结果就会出现文字的抖动。如果在程序中使用MemDev,则所有的执行操作都在MemDev中执行,当所有的操作都执行完毕之后,最后的结果才会送到屏幕上显示,因而可以避免多次刷新,从而避免抖动。
此目录下包含这MemDev的所有函数,包括创建MemDev函数,激活MemDev,执行画图操作,显示到终端,删除MemDev函数等等。
触摸屏驱动函数所在目录。uC/GUI只支持模拟的触摸屏。因而此目录下只包含模拟触摸屏。
  此目录包含窗口控件函数,总共46个函数。UC/GUI中窗口控件机制时uC/GUI的实现难点,也是应用难点。运用窗口管理和回调机制,运用窗口控件函数,可以任意在LCD屏幕上实现类似于windows的界面,这样完备的功能在工业自动化控制和触摸屏应用上有着深远而积极的意义。
  此目录下的函数主要包括uC/GUI的窗口控件,如按钮BUTTON,校验窗CHECKBOX,编辑区EDIT,窗口框FRAMEWIN,列表LISTBOX,进度条PROGBAR,音频按钮RADIOBUTTON,滚动条SCROLLERBAR,改变值的灰度条SLIDER,以及文本框TEXT相关的各种函数。
此目录包括窗口管理函数,总共52个函数。UC/GUI中,窗口管理中的消息传递机制和回调机制,也是uC/GUI的实现难点和应用难点。4.3节中将详细介绍这两点。
此目录下的函数主要包括设置、返回、建立背景窗口、父窗口、各种子窗口以及相应的尺寸、窗口句柄,起点x,y坐标,窗口宽度,高度,位置等等,还包括改变窗口的大小,以及最关键的窗口的回调函数,窗口重绘函数等等。
4.3 uC/GUI的窗口管理
4.3.1简介
uC/GUI的窗口管理是一个单独的软件,不是uC/GUI的基本组成部分。详细代码见\uCGUI\GUI\WM。
当使用uC/GUI窗口管理时,任何能显示在显示终端上的内容都包含在一个窗口里面,这个窗口是LCD屏幕上的一个给用户画图或者显示目标的区域。窗口可以是任何尺寸的,可以一次在屏幕上显示多个窗口,也可以在其它窗口当中或之前显示窗口。
窗口管理的几个名词:
◆ 活动窗口:
 当前正在用来画图或是显示操作的窗口。
◆ 回调函数
回调函数是由用户定义的,当特定事件发生时,指示图形系统调用特定函数的函数。通常当窗口的内容发生改变时,它们用来自动重绘窗口。例如,窗口内显示一幅位图,当窗口移动时,位图并不会自动移动,此时,就需要调用回调函数对窗口进行重绘,即,从观众的角度来看,移动窗口和窗口内容。
◆ 子/父窗口
子窗口是相对于父窗口定义的窗口。无论何时,只要父窗口移动,则子窗口们都要相应移动。子窗口被父窗口完全包含。拥有同一个父窗口的子窗口们互相间称为兄弟。
◆ 客户区
窗口的客户区就是窗口的可用区。如果窗口包含方框或标题栏,则客户区就是方框或标题栏的内部区域。
◆ 句柄
当一个新的窗口被创建时,WM分配一个唯一的标识符,称为句柄。句柄用在后续对该窗口操作的所有函数中,而且可以利用该句柄唯一标识该窗口。
◆ 有效窗口/无效窗口
有效窗口是一个已经完全更新,不需要重绘的窗口。不管是完全重绘还是局部重绘。当窗口内容发生改变时,WM则标识窗口无效。下一次重绘之后(调用回调函数),窗口又变为有效。
4.3.2回调机制
uC/GUI提供给窗口和窗口控件的回调机制的背后,是一个事件驱动标志。在大多数的窗口系统中,流控不仅仅时从用户程序到图形系统,而且还要能够从用户程序到图形系统,并且能够通过用户程序提供的回调函数,返回到用户程序。这个机制,就称为回调机制。在uC/GUI中,回到机制用来在窗口管理中出控制窗口的重绘操作,这使得窗口管理的有效性成为可能。
4.3.3 回调函数的使用
使用回调函数建立一个窗口时,必须有一个回调函数。所用的回调函数必须有如下原型:
void callback (WM_MESSAGE *pMsg)。 其中pMsg为指向消息的指针。
回调函数执行的功能依赖于所接收到的消息。以上原型后一般跟着switch表达式,表达式定义不同的case表达式下不同的信息对应的不同行为,至少要有一个重绘函数:WM_PAINT()。如程序清单4.1,建立一个自动更新窗口的回调函数
程序清单 4.1 建立一个自动更新窗口的回调函数
void WinHandler (WM_MESSAGE * pMsg)
{
     switch (pMsg->MsgId)
     {
case: WM_PAINT   GUI_SetBkColor(0xff00);
                 GUI_Clear();
                 GUI_DispStringAt(“hello world”,0,0);
                 Break;
}
}
使用回调函数,更为详细的示例如程序清单4.2所示:
程序清单4.2  回调函数
#include GUI.H
 
/* 背景窗的回调函数 */
static void cbBackgroundWin(WM_MESSAGE* pMsg)
{
switch (pMsg->MsgId)
{
case WM_PAINT:    GUI_Clear();
default:          WM_DefaultProc(pMsg);
}
}
/* 前景窗的回调函数 */
static void cbForegroundWin(WM_MESSAGE* pMsg)
{
switch (pMsg->MsgId)
{
case WM_PAINT:    GUI_SetBkColor(GUI_GREEN);
GUI_Clear();
GUI_DispString(Foreground window);
default:          WM_DefaultProc(pMsg);
}
}
/*  回调机制 */
static void DemoRedraw(void)
{
GUI_HWIN hWnd;
while(1)
{
/*创建一个前景窗 */
hWnd = WM_CreateWindow(10, 10, 100, 100, WM_CF_SHOW, cbForegroundWin, 0);
/*显示前景窗*/
GUI_Delay(1000);
/* 删除前景窗 */
WM_DeleteWindow(hWnd);
GUI_DispStringAt(Background of window has not been redrawn, 10, 10);
/* 等待,显示并不重绘 */
GUI_Delay(1000);
GUI_Clear();
/* 设置背景窗的回调功能 */
WM_SetCallback(WM_HBKWIN, cbBackgroundWin);
/*创建一个前景窗 */
hWnd = WM_CreateWindow(10, 10, 100, 100,WM_CF_SHOW, cbForegroundWin, 0);
/* 显示前景窗*/
GUI_Delay(1000);
/*删除前景窗 */
WM_DeleteWindow(hWnd);
/* 等待,显示将重绘*/
GUI_Delay(1000);
/* 删除回调函数 */
WM_SetCallback(WM_HBKWIN, 0);
}
}
 
void main(void)
{
GUI_Init();
DemoRedraw();
}
4.3.4 消息传递机制
程序清单4.2中,回调函数执行的功能依赖于所接收到的消息。Switch语句中根据消息的类型,分别执行不同的功能。
WM_MESSAGE的成员如下:
MsgId:消息类型
HWin:  目的窗口
HWinSrc: 源窗口
Data.p : 数据指针
Data.v: 数据值
其中MsgId的类型如下:
    WM_PAINT: 窗口重绘
    WM_CREATE: 窗口一建立就发送
    WM_DELETE: 窗口一删除就发送
    WM_SIZE :  窗口尺寸发生改变就发送
    WM_MOVE :  窗口移动就发送
    WM_SHOW :  接收到show命令就发送
    WM_HIDE :  接收到hide命令就发送
    WM_TOUCH:  触摸屏信息
应用程序还可以为自己定义额外的消息。为保证它们不用到uC/GUI的消息ID,用户定义的消息从WM_USER后面开始,如:
#define MY_MESSAGE_AAA   WM_USER +0
#define MY_MESSAGE_BBB   WM_USER +1
 
VC++仿真

ucgui开源模拟器

如果你下载最新版的ucgui3.90a的话, 它的模拟器本身就是开源的.你可以看到你的UCGUI应用程序是如何跑起来的. 它是WIN下面的一个线程,模拟器程序是主线程.

还有, 在我的网站下面, 我先前就已经以写出了3.24版的UCGUI的模拟器程序, 到www.ucgui.com下就可以下载到.

模拟器的原理是很简单的,就是把内存中的数据弄成位图显示出来而已.

 

移植

转载http://blog.csdn.net/lyx_wq/archive/2009/09/21/4576203.aspx

mini2440上无操作系统移植ucGUI

由于不要把过多时间浪费在底层驱动上,这次我直接用mini2440开发板附带的 非操作系统示例代码的2440板上资源测试程序为基础,移植ucGUI。

       UcGUI的移植主要修改三个头文件和两个C文件。三个头文件都在\Config下,分别是GUICon.h ,GUITouchConf.h,LCDConf.h ;两个C文件一个是GUI_X.C(Sample\GUI_X.C) ,.另外一个在GUI\LCDDriver目录下(我是选择LCDWin.c来修改的)。

 1.修改头文件LCConf.h

主要修改的地方:

#define LCD_XSIZE (240)

#define LCD_YSIZE (320)

//#define LCD_BITSPERPIXEL (8)

#define LCD_BITSPERPIXEL (16) //16Bpp

#define LCD_CONTROLLER 1375

LCD_XSIZE ,LCD_YSIZE 是对应你的LCD的尺寸大小

LCD_BISPERPIXEL 指定每象素的位的数量

LCD_CONTROLLER控制器部分我没改,按原来定义的1375。uC/GUI的技术文档上没有Sharp FTFP屏的控制器,就用LCD13XX中的一个来代替。

2 修改头文件GUI_Conf.h

#ifndef GUICONF_H

#define GUICONF_H

#define GUI_OS (0)

#define GUI_SUPPORT_TOUCH (0)

#define GUI_SUPPORT_UNICODE (1)

#define GUI_DEFAULT_FONT &GUI_Font6x8

//#define GUI_ALLOC_SIZE 12500

#define GUI_ALLOC_SIZE 1024*1024

#define GUI_WINSUPPORT 0

#define GUI_SUPPORT_MEMDEV 0

#define GUI_SUPPORT_AA 0

#endif

GUI_0S 位1时支持OS,否则就是裸跑吧

GUI_SUPPORT_TOUCH 是否支持触摸屏

GUI_SUPPORT_UNICODE 是否支持ASCII/UNICODE

GUI_DEFAULT_FONT 选择一个默认的字体

GUI_ALLOC_SIZE 动态内存的大小

GUI_WINSUPPORT 是否支持 WM(视窗管理器)

GUI_SUPPORT_MEMDEV 是否支持存储设备

GUI_SUPPORT_AA 是否支持反锯齿

3 修改 GUITouchConf.h

如果需要支持触摸屏的话,这个头文件也要作相应的修改。

下面是说明如何修改uC/GUI的两个接口文件。

在LCD的最基本操作就是在某一个坐标上画点,其他的操作都是画点操作延伸出来的。uC/GUI的所有对LCD的操作也是基于这个动作。Mimi2440的底层驱动代码上有这个函数PutPixel(x,y,c)。所以必须要把这个函数连接到uC/GUI的代码里面。连接的函数就在LCDDriver下,我选用LCDWin.c.

修改这个文件的时候要注意,首先要屏蔽掉第一行的条件编译语句 #if defined(WIN32) && !defined(LCD_SIMCONTROLLER) 和文件的最后一行的#endif 顺便把#endif头上的#else 也干掉。这个文件是针对PC仿真的,不注释掉这几个地方,整个文件都不会被编译的。

PutPixel(x,y,c)在LCD_240X320.C中,由于PutPixel(x,y,c)被定义成了 static ,那就在LCD_240X320.C的后面加一个外部函数调用PutPixel(x,y,c) 。当然去掉static也行。

void LCD2410_SetPixel(U32 x,U32 y,U32 c)

{PutPixel(x,y,c);

}

然后把LCDWin.c的LCDSIM_SetPixelIndex(x, y, c, LCD_DISPLAY_INDEX)全部替换成LCD2410_SetPixel(x,y,c)

你会发现里面还有一个LCDSIM_GetPixelIndex(x,y, LCD_DISPLAY_INDEX); 那就在LCD_240X320.C造一个函数出来吧。参照 PutPixel() 造一个出来

void GetPixel(U32 x,U32 y,U32 c)

{

if ( (x < SCR_XSIZE_TFT_240320) && (y < SCR_YSIZE_TFT_240320) )

c=LCD_BUFER[(y)][(x)]; //对调过来,呵呵,简单吧!

}

void LCD_Off (void)

void LCD_ON(void)

这两个函数连接到LCD_240X320.C中的Lcd_EnvidOnOff(int onoff)

int LCD_L0_Init(void) 连接到 LCD_240X320.C 中的Lcd_Init();再加上一个清屏的函数

void LCD_L0_ReInit() 连接到LCD_240X320.C 中的Lcd_Init();不加清屏函数。

最后修改GUI_X.C文件

由于没有OS,所以有关OS的语句都得修改,幸好不是很多,就两个地方而已。

GUI_X_GetTime(void) 返回当前的OS_TimeMS ,那就修改一下,把变量赋值一个数比如是10 然后让函数返回这个值就行了 。

GUI_X_Delay(int ms)

自己写个延时程序吧,

GUI_X_Init();完成硬件的初始化,由于用的是现成的代码,板子的初始化都已经完成,我把LCD的初始化放在了这里。

做完以上的工作基本上算是完成了移植的工作了。

最后在主函数的适当位置添加一下程序

int Main()

{

其他代码

**************

GUI_Init();

GUI_DispString("Hello world!");

 *************

其他无关代码

}
别忘记包含头文件 GUI.h

编译通过后 ,LCD上就会出现 “Hello World !”了。

以上这些我相信在网上很多地方都可以搜到。下面说下我在移植时遇到的undefined symbol的错误:

1、  Error: undefined symbol LCDSIM_SetLUTEntry (referred from LCDWin.o);

这种错误应该还是很常见的,意思也很明显就是在LCDWin.c中没有定义LCDSIM_SetLUTEntry,一般只要把相应头文件加入即可,但就上面这个特定的错误,我发现函数LCDSIM_SetLUTEntry在LCDSIM.h里定义,而且已经在LCDWin.c里包含进了这个头文件,还是有错误,没办法我只好在LCDWin.c里重新定义了一次(其实这个函数什么也没实现)

void  LCDSIM_SetLUTEntry(U8 Pos, LCD_COLOR color, int LayerIndex)

{

       return;

}

2、  Error: undefined symbol main (referred from kernel.o)

这个错误我解决了好久,一是源文件里找不到kernel.c这个文件,二是我确实定义了main函数,最后终于在一篇相关文章的评论里找到了这个问题的解决方法(不知道是否具有通用性)原来mini2440的main函数是Main开头的m是大写的,应该改成小写,相关的当然还有起始代码中用到Main的一律小写就可以了。

   3、Error:differing redefinition of #define macro U32

U32的定义不一致 为了不想改动太大,我直接把位于GUI\Core\LCD.h中的

#define U32 unsigned long 改为 #define U32 unsigned int

其他一些错误应该是很好改的,希望对大家有所帮助,下篇把触摸屏的功能移植上去。

参考文章:http://hi.baidu.com/mikenoodle/blog/item/e6b031d3519350063bf3cf54.html

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lyx_wq/archive/2009/09/21/4576203.aspx

 


PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户1653723 2012-4-26 17:20

同上!看不懂 只能支持了。。

用户1611555 2011-7-26 10:32

很深奥的技术文章,看不懂但是必须支持下

用户123084 2010-4-7 22:29

好像叫做本振馈通,应该是频谱仪本身振荡器产生的信号,把它做到零频就不会对信号测量造成影响了。
相关推荐阅读
mcuandme 2020-03-14 23:15
18位、线性、低噪声、精密双极性±10 V直流电压源
www.analog.com/zh/CN0200...
mcuandme 2020-03-14 21:51
C语言printf("")左对齐和右对齐 (转)
https://blog.csdn.net/abcdu1/article/details/74926375  原文地址1.左对齐方式1printf("%d\n",101010);默认打印格式...
mcuandme 2020-03-14 21:45
放大器电路设计中的常见问题经验总结
源地址:https://www.cnblogs.com/huanzxj/p/5667633.html与分立器件相比,现代集成运算放大器(op amp)和仪表放大器(in-amp)为设计工程师带来了许多...
mcuandme 2015-07-13 15:12
简单的固态继电器具有过零开关功能
本设计实例是一个固态继电器(SSR),它能利用双向晶闸管切换大电流的交流负载(图1)。市场上有大量简单的固态继电器电路,但这个电路可能是最简单的,它只在交流线路电压接近零时才导通和关断。 晶体管Q2...
mcuandme 2014-07-30 08:44
LIB和DLL的区别与使用
共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library。 ...
mcuandme 2013-12-19 22:16
Stellaris LM3S MCUs
今天买了个开发板 EKK LM3S3748 然后上网查资料是 Stellaris LM3S MCUs 系列的芯片 是CORTX M3 内核 但是TI官方网站已经推荐上级到  Upgrade...
EE直播间
更多
我要评论
2
7
关闭 站长推荐上一条 /1 下一条