Graphical User Interface简称GUI,即图形用户界面,准确来说GUI就是屏幕产品的视觉体验和互动操作部分。在工业控制领域里,各种仪器仪表、智能工控设备中广泛采用了嵌入式技术,但由于资源有限,这些系统一般不希望建立在庞大累赘的、非常消耗系统资源的操作系统和GUI之上,如Windows或XWindows。这些系统对液晶显示的常用GUI需求更加突出。因此,在工业控制系统中实现一个简洁、快速、方便的常用GUI具有广阔的市场应用前景。
在工业控制领域点阵液晶显示(LCD)是应用最为广泛的,如果使用GUI,那么在显示设备(通常指的是LCD)上完成绘制图形、显示西文字符和汉字、显示和使用控件以及窗口等工作,就可以通过调用GUI提供的函数来实现,无须自己为LCD编写完成这些工作的程序,也无须选用自带汉字库的LCD了。“GUI”一词是“图形用户界面(Graphics User Interface)”的缩写,那么使用GUI的LCD,当然只能选择图形点阵LCD,1602之类的字符LCD不在考虑之列。
在进行液晶显示GUI开发的时候首先要考虑MCU和LCD的选型。
MCU选型
8位单片机——8051系列单片机系统要求64Kb ROM和1Kb RAM,可以选择单片增强型8051单片机,如宏晶科技增强型8051单片机STC89C516RD+,内部继承64Kb Flash和1280B RAM,其中包括1Kb扩展RAM(Keil C51中为xdata);也可以用普通8051单片机外界ROM和RAM。
为了保证GUI的运行速度,8051单片机系统的主频应尽量高一些,至少应在22MHz以上,如果单片机有内部倍频可以打开,使用告诉的C8051F系列单片机更好,如C8051F020等。
如果选用AVR系列8位单片机,可以选择内部Flash不小于32Kb,内部SRAM不小于2Kb的型号,如ATmega32、ATmega64、ATmega128等。
LCD选型
STN LCD——市面上销售的单色LCD绝大多数都是这种类型。STN LCD可选择自带LCD驱动器/控制器的STN LCD模块,如基于KS0107/KS0108的128×64单色图形点阵液晶模块,更大一些的同样可以使用,无须自带汉字库。
TFT LCD——即俗称的“真彩色”液晶。TFT LCD通常一定要选择总线型液晶显示器,或者外接单片机LCD驱动板也可以,总之要能够连接单片机或者MCU。
注意:无论选择何种LCD,LCD供电电压和I/O电平应与MCU供电电压和I/O电平相匹配,例如,都是5V或者都是3.3V,如果不匹配,可考虑使用LDO(低压差稳压器)和上拉电阻。
底层驱动函数
在选定MCU和LCD后,针对LCD控制器要编写一些底层驱动函数,这些函数主要实现MCU对LCD控制器的控制,进而实现对LCD的控制。其中最主要的两个驱动函数是控制器写命令函数和控制器写数据函数。值得注意的是不同的控制器的控制时序和控制特性有所不同,应针对所选用的MCU和LCD控制器选择合适的连接方式以最简捷的硬件连接来获得最佳的控制效果。
GUI基本功能的实现
液晶显示的常用GUI应实现最基本的画点、画圆、画线、矩形、正方形、填充等功能,还须要实现ASCII显示和汉字显示以及简单的图标显示和菜单显示。
在实现GUI的这些基本要素时一个最重要的问题是准确定位光标位置。由于各控制器的不同,光标的定位也不同,例如有的控制器是以字节(8个点)为基本单位,而有的控制器是以点为基本单位。在应用以字节为基本单位的控制器时应注意要实现任意位置的操作时需要经过适当的算法进行移位处理。
在选用不带汉字库的LCD时,在实现汉字显示功能时应用字模软件对汉字进行取模存储。根据实际要求ASCII字模可选用8×8和8×16,而汉字字模一般选用16×16和24×24。在实现单个ASCII和汉字的显示后,建议最好实现ASCII和汉字混合字符串的显示,因为实现此功能后将对后期开发菜单时带来极大的方便。
实例:AVR单片机ATmega128控制SED1335实现GUI
ATmgeal28是AVR单片机中功能最强的,它有128KB的Flash程序存储器、4Kb的SRAM和4Kb的EEPROM。在端口方面,它有边界扫描JATG口、I2C串行口、SPI同步串行口和通用异步串行口UART。通过适当的外围接口电路的设计,它能够满足工业控制器的要求。
SED1335是日本SEIKO EPSON公司出品的液晶显示控制器,在同类产品中功能最强,它具有如下几个特点:
①有较强功能的I/O缓冲器;
②指令功能丰富;
③四位数据可并行发送,最大驱动能力为640×256点阵;
④可混合显示图形和文本方式;
⑤具有垂直、水平和滚动功能;
⑥图形方式下具有三重屏幕显示;
⑦内含160个点阵字符的字符发生器。
SED1335在接口部设置了适配Intel 8080系列和M6800系列MPU的两种操作时序电路,通过引脚的电平设置,可选择二者之一。
本例采用的为Intel8080操作时序,如图1所示。
图1 SED1335与8080系列MPU接口时序
本例利用ATmega128丰富的管脚资源直接通过输入输出引脚控制SED1335。其中数据部分是8条数据线(DB0~DB8),控制部分包括RD(读)、WR(写)、CS(片选)、A0(数据类型选择)。ATmega128与SED1335的接线原理图如图2所示。
图2 ATmega128与SED1335连线原理图
实际上,在对SED1335进行控制的过程中,最重要的一点就是对A0的控制。由于A0是数据类型选择位,当A0为1时,ATmega128发出的数据会被SED1335认为是指令代码而将它自动放到它的指令输入缓存器内;当A0为0时,ATmega128发出的数据会被SED1335认为是数据代码自动放到它本身的数据输入缓存器内。
值得注意的是:ATmega128的输入输出端口必须自己设定,本文采用的编译器是WinAVR(GCC),所以对输入输出口的设定如下程序语句:
DDRA=0XFF; //将PA口设为输出
DDRD=0XF0; //将PC口PD4~PD7设为输出
为了控制SED1335在底层需要编写两个重要的驱动函数分别为SED1335写命令函数和SED1335写数据函数。本文使用WinAVR(GCC)编译器,具体实现如下:
void SED1335_write_command(unsigned char CommandByte)
{
PORTD|=BIT(1)|BIT(3)|BIT(4);
PORTD|=BIT(2); //A0置高 即A0=1
PORTD&=~BIT(1);
PORTD&=~BIT(3);
PORTA=CommandByte;
PORTD|=BIT(1);
PORTD|=BIT(3);
}
void SED1335_write_data(Uchar dataW)
{
PORTD|=BIT(1)|BIT(3)|BIT(4);
PORTD&=~BIT(2);//A0置低 即A0=0
PORTD&=~BIT(1);
PORTD&=~BIT(3);
PORTA=dataW;
PORTD|=BIT(1);
PORTD|=BIT(3);
}
SED1335具有一个13条指令的指令集,多数指令带有参数,参数由用户根据用户所控制的液晶显示模块的特性和实际应用的需要来设置。这个指令集可实现初始化、显示域、显示状态、光标(包括形状、位置和移动方向)、显示合成方式和数据读写设置等,可完成多种文本的显示、刷新等功能。
在编写菜单以前要对SED1335进行初始化设置,设置液晶屏显示的方式、显示的合成方式等各个方面。具体程序的初始化指令代码如下:
void GuiInit(void)
{
//SYSTEM SET COMMAND
SED1335_write_command(SystemSet); //系统设置命令
SED1335_write_data(0x30);
SED1335_write_data(0x87);
SED1335_write_data(0x07);
SED1335_write_data(0x27);
SED1335_write_data(0x42);
SED1335_write_data(0xef);
SED1335_write_data(0x28);
SED1335_write_data(0x00);
……
}
注意带有多参数的指令在写参数时,一定要按规定的顺序依次写入(参数可以不必全部写入),不然就会出错。另外,在初始化设置SED1335之前应先对ATmega128进行初始化,主要是对I/O口进行输入输出设定。
其他的工作就是具体实现画点、画圆、画线、矩形、正方形、填充、ASCII显示和汉字显示以及简单的图标显示等功能了。这里列出需要实现的函数,不再给出具体程序代码。
void LcdOn(void); //允许液晶显示
void LcdOff (void); //关闭液晶显示
void DispClear (void); //清除32K RAM显存
void GotoXY(Uint x,Uint y); //文本方式下将光标定位到指定位置
void GPix(Uint x,Uint y,char color); //任意位置的画点或消点
void lcd_rectangle(Uint x1,Uint y1,Uint x2,Uint y2,char color); //画方框图
void GuiLevelLine(Uint x0,Uint x1,Uint y,char color); //画水平线
void GuiUpdownLine(Uint x,Uint y0,Uint y1,char color); //画垂直线
void GuiLine(Uint x0,Uint y0,Uint x1,Uint y1,char color); //画直线
void GuiCirclePixel(Uint x0,Uint y0,Uint r,char color); //画圆
void GuiBoxReverse(Uint dot_start_x, //指定区域的取反显示
Uint dot_start_y,
Uint dot_end_x,
Uint dot_end_y);
void GuiBoxFill (Uint dot_start_x, //指定区域的填充(置0或写1)
Uint dot_start_y,
Uint dot_end_x,
Uint dot_end_y,
char color);
void write_string(char *ptr); //文本方式下写8*8的字符
void PutCdotInAlpha(Uint x,Uint y,Uint Cnumber);//汉字写入子程序(文本方式)
void PutCdotInGraph(Uint x,Uint y,Uint Cnumber,Uint DotWidth); //汉字写入子程序(图形方式)。每次调用输出一个汉字(可显示16*16或24*24的汉字)
void Locatexy(Uint x,Uint y); //图形方式的光标定位函数
void GuiString(Uint x,Uint y,char *ptr,char color,char colorBk); //图形方式的写8*16的字符和16*16的汉字混合函数
void bprintf (Uint x,Uint y,Uint a,char color,char colorBk); //图形方式的显示变量数值的函数(8*16)
void mprintf (Uint x,Uint y,int *p,char color,char colorBk); //图形方式的显示文件名的函数(8*16)
整个系统的软件流程图如图3所示。
图3 系统软件流程图
在本实例中,通过液晶显示屏和按键配合操作可完成各种功能选择和参数的设置。由于采用汉字显示菜单,接口直观、简便、美观、友好。
液晶显示常用GUI的通用性
通过上述实例可以看出:在应用本文设计的GUI时,只需要针对不同的MCU和LCD控制器进行很少的底层驱动函数的更改,使其满足LCD控制器的控制时序和控制特性即可,而GUI基本的画点、画圆、画线、矩形、正方形、填充、ASCII显示和汉字显示以及简单的图标显示等功能,几乎不用改动或只需针对光标定位进行改动。此外,对于AVR单片机而言由于具有丰富的管脚资源可以直接使用输入输出引脚,对LCD控制器进行控制,其实当该GUI作为嵌入式系统的显示部分时可以不用 I/O进行控制来满足时序。如本文所举的实例如果由FPGA完成时序配置,则只需对SED1335写命令函数和SED1335写数据函数稍加修改,而其余GUI函数都可以直接应用。修改的SED1335写命令函数和SED1335写数据函数代码如下:
void sed1335_write_command(Uchar CommandByte)
{
*(volatile unsigned char*)SED1335_WRITE_COMMAND_ADDR =CommandByte;
}
void sed1335_write_data(Uchar dataW)
{
*(volatile unsigned char*)SED1335_WRITE_DATA_ADDR=dataW;
}
结束语
工业测量控制仪器中,友好的人机对话窗口可使操作更加简单,本文提出的液晶显示的常用GUI不仅满足工控要求,而且具备很好的通用性,同时还有轻型、占用资源少、高性能、高可靠性、可配置等特点,可以方便地移植到各种工控嵌入式系统中。
评论