18.4.1 简介及型号选择LCD(Liquid Crystal Display)以其功耗低、冷光源、显示灵活等特点,正逐步取代LED数码管等显示器件。 LCM,英文全称为LCD Control Module,意为“液晶控制模块”。狭义上讲,LCD只是液晶显示面板而已,其控制线繁多,时序也较为复杂;而单片机、DSP等嵌入式系统若和LCD直接连接,硬件连接、软件编写都很麻烦。所以,我们采用一个控制器,介于液晶面板和嵌入式系统之间,对于嵌入式系统来说,这个控制器提供8位或16位的接口,嵌入式系统可像访问片外RAM一样去读/写该控制器;而对于LCD显示面板来讲,这个控制器收到嵌入式系统发来的命令后,驱动LCD显示内容。这种连接嵌入式系统和LCD显示面板的“桥梁”作用可参考下节对SED1335内部框图的分析。 这种LCD控制器,一般有如下型号:KS0066、ST7920、T6963、SED1335等。 常见的LCM按显示的内容可分为段型液晶、字符型液晶和图形型液晶;按颜色可分为单色液晶、灰度液晶和彩色液晶。 从显示的效果来讲,彩色液晶固然更加引人瞩目,但其价格高,而且控制复杂。另外,C6713内部没有彩色液晶控制器,没有专门的彩屏接口,因此C6713连接彩屏很费事,要外接彩屏控制器要用CPLD、FPGA或ASIC作为接口转换器。经过性能、成本等方面的考虑并结合实际需要,我们选择了单色LCM,控制器是SED1335,320×240分辨率,同样可以构建良好的显示界面。 18.4.2 控制芯片构架、寄存器以SED1335为控制芯片构成的LCM(液晶显示模块),分辨率大多为240×128和320×240。下面我们就来介绍分辨率为320×240的液晶显示模块。国内兼容的产品型号有AG320240、DV320240等。 SED1335是日本 SEIK EPSON 公司出品的液晶显示控制器,具有较强功能的I/O缓冲器,指令功能丰富,4位数据并行发送,最大驱动能力为640×256点阵,能显示文本和图形。 SED1335的特性如下: 显示模式:文本、图形、文本/图形混合; 在图形模式下,支持3个屏幕的交叠; 最高分辨率:640×256点; 可编程的光标控制; 支持6800和8080系列时序; 低功耗:3.5mA工作电流(工作电压为3.5V),0.05μA待机电流; 封装:QFP。 SED1335硬件结构可分为MPU接口、控制部分和驱动LCD面板等,结构如图18-18所示。正如上面对LCD控制器的作用所言:起着连接DSP等微处理器和LCD控制面板的“桥梁”作用。如图18-18中所示,图的下部分是单片机、DSP等微处理器的接口,用来接收微处理器发送的命令和数据,经过LCD控制器内部的处理之后,将要显示的内容发送给右上角的LCD面板,从而实现LCD显示。  图18-18 SED1335内部原理框图 SE1335接口部分具有功能较强的I/O缓冲器,慢速的微控制器访问SED1335可以不用判断SED1335的“忙”信号,SED1335可随时接受嵌入式系统的访问,并及时地把嵌入式系统发来的指令、数据传输就位。 控制部分由时钟、功能逻辑器、图像RAM管理电路、内部或外部字符库及LCD面板驱动时序电路的时序发生器组成。 SED1335的引脚图可以参考SED1335的数据手册。我们使用的是成品的LCD液晶显示模组(LCM),所以,只要把LCM当成一个黑盒子就是了,了解单片机或DSP访问LCM的时序图即可。 为了达到更大限度的兼容性,能用于更多的场合,能和更广泛的微处理器配合工作,SED1335兼容两种时序:8080时序和6800时序。 8080时序图如图18-19所示,由A0、 负责选通LCM的数据通道或命令通道。 、 表示读或写操作。DB0~ DB7是数据输入或输出总线。 
图18-19 SED1335的8080时序图 6800时序图如图18-20所示,由A0, 负责选通LCM的数据通道或命令通道。E表示使能,R/W表示读或写操作。DB0 ~DB7是数据输入或输出总线。 
图18-20 SED1335的6800时序图 8080系列、6800系列时序的切换通过SED1335的SEL1、SEL2引脚上的高低电平来确定,一般在液晶模块上有跳线帽或短路电阻来控制,详情请参考相应的液晶模块说明书。 320×240液晶显示模块引脚定义如表18-6。 表18-6 320×240液晶显示模块引脚定义 引 脚 序 号 | 名 称 | 用 途 说 明 | 1 |
| 重启。低电平有效 | 2 |
| 8080时序:读信号 | 6800时序:使能信号 | 3 |
| 8080时序:写信号 | 6800时序:R/W信号 | 4 |
| 片选信号 | 5 | A0 | 命令/数据选择 | 6~13 | DB0~DB7 | 数据输入(8位) | 14 | VDD | 逻辑电源正极(5.0V或3.3V) | 15 | VSS | 电压地(0V) | 16 | VEE | LCD面板驱动电压 | 17 | VO | 对比度调节 | 18~24 | NC | 悬空,不连接 |
18.4.3 硬件连接320×240液晶显示模块与C6713的连接示意图如图18-21所示,由于为了和C6713的时序兼容,我们把液晶显示模块的时序定为8080时序。LCM上的跳线选择或电阻选择详情请参考相应液晶显示模块的说明书。 <DIV> TMS320C6713 EA2 EA18 EA19 EA20 ED0~ED7 ARE AWE </DIV> |
<DIV> SE1335液晶显示模块 A0
D0~D7 RD WR </DIV> |
图18-21 320×240液晶显示模块和C6713的连接示意图 SED1335液晶显示模块和C6713的连接,其实不复杂,其时序就如同访问外部RAM一样。说到硬件设计,就不得不说LCM的背光方式了。 LCM的背光方式,一般分为LED、CCFL、EEFL等方式。 (1)CCFL(Cold Cathode Fluorescent Lamp,冷阴极荧光灯管),由于CCFL的技术工艺成熟、信赖性高、性能稳定,所以,CCFL作为LCD的背光有不少的市场占有率。 但CCFL驱动电路较为复杂,要用逆变器产生驱动电压,外部电路复杂,增加了电子系统的总成本。另外这些高频、大功率的交流电压必定会对其他电路产生影响,如对距离屏幕较近的触摸屏芯片AD7843。 (2)EEFL(External Electrode Fluorescent Lamp,外置电极荧光灯),也是用逆变器产生驱动电压来发光的。 (3)LED(Light Emitting Diode,发光二极管),特点是:寿命长、不含汞、环保性能更好、不需要变换器、功耗低等。LED的背光方式中电路很简单,只要正向驱动电压即可,无须像CCFL和EEFL那样需要逆变器,还可以采用PWM(Pulse Width Modulation,脉宽调制)的方法来控制亮度,从而更好、更方便、更简易地与数字电路连接。 如图18-22是所示的LED背光方式示意图,在这种形式下,接入5V直流电即可产生背光。LED是冷电源,功耗小、效率高且连接方便,无须逆变器等外接电源器件,产生的干扰也小。 如图18-23所示的是EEFL背光方式示意图,需要加入逆变器。 <DIV> LCM + LED背光电路 - </DIV> | 图18-22 LED背光方式示意图 图18-23 EEFL背光方式示意图 如图18-24所示的是CCFL背光方式示意图,也需要加入逆变器。
图18-24 CCFL背光方式示意图 18.4.4 SED1335指令解析了解了SED1335的内部原理、外部连接、背光方式之后,下面来讲解SED1335的指令,了解了这些指令,才能控制LCM,才能让其按照我们的想法来显示界面。 1.系统设置命令SED1335系统设置命令各字位如表18-7所示。 表18-7 SED1335系统设置命令各字位 A0 |
|
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 字节数 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 8 |
A0表示选中SED1335的命令输入通道, 、 分别为1、0,表示当前是写操作。 本命令用来进行SED1335的系统设置,包括重启液晶、单屏/双屏等设置参数。 2.显示开/关命令SED1335显示开/关命令各字位如表18-8所示。 表18-8 SED1335显示开/关命令各字位 A0 |
|
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 字节数 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | D | 1 |
D=0:显示关; D=1:显示开。 3.设置光标命令SED1335设置光标命令各字位如表18-9所示。 表18-9 SED1335设置光标命令各字位 A0 |
|
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 字节数 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 2 |
该命令用来设置光标的属性,发送该命令字之后,紧跟两个命令字,用来设置光标的位置、点阵数等。 4.设置光标地址命令SED1335设置光标地址命令各字位如表18-10所示。 表18-10 SED1335设置光标地址命令各字位 A0 |
|
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 字节数 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 2 |
该命令用来设置光标的地址,就是设置光标在显示屏上哪个坐标。 发送该命令后,紧跟着另外两个命令,用来表示坐标的具体位置。 5.写显存命令SED1335写显存命令各字位如表18-11所示。 表18-11 SED1335写显存命令各字位 A0 |
|
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 字节数 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | / |
该命令用来写LCM中的显存,将数据写入显存之后,SED1335就会将这些数据显示在液晶面板上。 6.读显存命令SED1335读显存命令各字位如表18-12所示。 表18-12 SED1335读显存命令各字位 A0 |
|
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 字节数 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | / |
该命令用来读取LCM中的显存,在一些应用中,往往需要将液晶面板上的某个区域反白、取反、与或等操作,此时就用到读取显存的命令,先读取SED1335的显存,在单片机或DSP等微处理器中对读出的数据进行处理之后,再写到显存中,从而实现操作。 18.4.5 SED1335底层驱动函数上一节介绍了SED1335的常用指令,下面讲解C6713如何驱动SED1335,从而让其显示。 首先,来讲解最底层的硬件驱动函数。 C6713对SED1335液晶控制器的底层驱动函数包括写命令、写数据、读数据、判读就绪等子函数。 在本实例中,SED1335液晶控制器映射在C6713的两个地址上,命令地址为0x0a00d0000,数据地址为0x0a0050000。 所以,就在程序开始的地方预定义: #define LCD_DAT (*((unsigned int *)0x0a0050000)) #define LCD_COM (*((unsigned int *)0x0a00d0000)) 下面是判断SED1335是否正在忙的子程序: void lcd_busy(void) { unsigned int temp; temp=0x40; while( (temp & 0x40)==0x40 ) { temp= LCD_COM; } } 下面是发送命令字给SED1335的子函数: void lcd_write_com(unsigned int com) { lcd_busy(); //判读LCM是否正忙,等到不忙为止 LCD_COM=com; } 下面是发送数据给SED1335的子函数: void lcd_write_dat(unsigned int dat) { lcd_busy(); //判读LCM是否正忙,等到不忙为止 LCD_DAT=dat; } 18.4.6 SED1335软件编写上一节讲解了C6713驱动SED1335最底层的硬件驱动子函数,本节就根据320×240液晶模块的特性,来说明320×240液晶模块上各种字符、图形、点、线的显示方法。 一个好的图形界面,不仅能显示字符,还能显示图形,并能根据实际需要画出直线、圆弧、矩形等几何图形。 320×240液晶模块以其高分辨率,可显示字符、数字、汉字、图形等特性,符合我们构建图形界面的需求,可以构建良好的人机交互平台。 1.SED1335初始化以下程序是SED1335显示模块的初始化子函数,其中涉及的命令字请参考前两节的命令字讲解或者参考SED1335的官方数据手册。 为方便起见,我们将系统设置的8个参数、显示区域设置的10个参数,写成一个数组的形式,便于代码维护和修改。 /*系统设置参数,8个参数*/ unsigned int system_para[]={0x30,0x87,0x07,0x27,0x2b,0xf0,0x28,0x00}; /*显示区域设置参数,10个参数*/ unsigned int scroll_para[]={0x00,0x00,0xf0,0x00,0x40,0xf0,0x00,0x80,0x00,0x00}; void LCD_Init(void) { unsigned int i; i=0; lcd_write_com (0x40); /*初始化,显示窗口设置命令*/ for(i=0;i<8;i++) /*写初始化参数*/ { lcd_write_dat(system_para[i]); } lcd_write_com (0x44); /*设置显示区域命令*/ for(i=0;i<10;i++) /*写显示区域设置参数*/ { lcd_write_dat(scroll_para[i]); } lcd_write_com (0x5a); /*设置点单元卷动位置命令*/ lcd_write_dat(0x00); lcd_write_com (0x5b); /*设置合成显示方式命令*/ lcd_write_dat(0x00); /*设置参数:一三区为文本属性*/ lcd_write_com (0x5d) /*设置光标形状*/ lcd_write_dat(0x07); lcd_write_dat(0x83); Clear_Screen(); /*清屏*/ lcd_write_com (0x59); /*DISP ON/OFF 命令*/ lcd_write_dat(0x54); /*设置参数:显示一~四区开显示,光标闪 */ } 2.画水平或垂直方向的直线以下代码是画水平或垂直方向直线的子函数。由于非水平或非垂直的直线,涉及坐标计算的问题,所以,我们将会在下一节讲解。 #define uint unsigned int void Line(uint row1, uint col1, uint row2, uint col2, uint style) { uint i,n; Set_Grap_Addr(row1,col1); //设置图形区域地址 if(row1==row2) { Cursor_Move('R'); n=col2-col1; lcd_write_com(0x42); for(i=0;i<n;i++) { if(style==1) { lcd_write_dat(0xff); } else if(style==2) { lcd_write_dat(0xa6); } else if(style==3) { lcd_write_dat(0xaa); } } } else if(col1==col2) { Cursor_Move('D'); n=row2-row1; lcd_write_com(0x42); for(i=0;i<n;i++) { lcd_write_dat(0x01); } } } 3.画非垂直或非水平方向的直线 以下代码是绘制非垂直或非水平直线的子函数。 #define uint unsigned int void disp_Linexy(uint x_start, uint y_start, uint x_end, uint y_end, uint screen) { uint t; int xerr=0,yerr=0,delta_x,delta_y,distance; uint incx,incy; //计算横、纵方向上的两个距离 delta_x = x_end - x_start; delta_y = y_end - y_start; if(delta_x>0) incx=1; else if( delta_x==0 ) incx=0; else incx=-1; if(delta_y>0) incy=1; else if( delta_y==0 ) incy=0; else incy=-1; /* 比较X、Y方向上距离的大小*/ delta_x = cabs( delta_x ); delta_y = cabs( delta_y ); if( delta_x > delta_y ) distance=delta_x; else distance=delta_y; /* 绘制直线 */ for( t=0;t <= distance+1; t++ ) { disp_Point(x_start,y_start,screen); xerr += delta_x ; yerr += delta_y ; if( xerr > distance ) { xerr-=distance; x_start+=incx; } if( yerr > distance ) { yerr-=distance; y_start+=incy; } delay_ms(300); } } 4.画圆弧以下代码是画圆弧的子函数。根据数学方程:
式中,x0、y0分别为圆心的坐标值,R为圆的半径。 void disp_circle(uint x0,uint y0,uint R,uchar screen) { uint xx,rr,xt,yt,rs,col,row; yt=Rx; rr=Rx*Rx; rs=Rx*71/100; //分开1/8圆弧来画 for (xt=0;xt<=rs;xt++) { xx=xt*xt; while ((yt*yt)>(rr-xx))yt--; col=x0+xt; //第一象限 row=y0-yt; disp_Point(col,row,screen); col=x0-xt; //第二象限 row=y0-yt; disp_Point(col,row,screen); col=x0-xt; //第三象限 row=y0+yt; disp_Point(col,row,screen); col=x0+xt; //第四象限 row=y0+yt; disp_Point(col,row,screen); /***************45°镜像变换,画另一半***************/ col=x0+yt; //第一象限 row=y0-xt; disp_Point(col,row,screen); col=x0-yt; //第二象限 row=y0-xt; disp_Point(col,row,screen); col=x0-yt; //第三象限 row=y0+xt; disp_Point(col,row,screen); col=x0+yt; //第四象限 row=y0+xt; disp_Point(col,row,screen); } } 5.显示数字显示8×16大小的阿拉伯数字,采用图形点阵的方式,所建立的数组如下所示。 unsigned int ASC2_num[] = { 0x00,0x00,0x00,0x1E,0x33,0x37,0x37,0x33, /*-- 0 --*/ 0x3B,0x3B,0x33,0x1E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0C,0x1C,0x7C,0x0C,0x0C, /*-- 1 --*/ 0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x06,0x0C, /*-- 2 --*/ 0x18,0x30,0x60,0x7E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x06,0x1C, /*-- 3 --*/ 0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x30,0x30,0x36,0x36,0x36, /*-- 4 --*/ 0x66,0x7F,0x06,0x06,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7C, /*-- 5 --*/ 0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x1C,0x18,0x30,0x7C,0x66, /*-- 6 --*/ 0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7E,0x06,0x0C,0x0C,0x18, /*-- 7 --*/ 0x18,0x30,0x30,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x76,0x3C, /*-- 8 --*/ 0x6E,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66, /*-- 9 --*/ 0x3E,0x0C,0x18,0x38,0x00,0x00,0x00,0x00, } 显示的子函数请参考下一节“显示英文字母”,因为在这个应用中,英文字母和阿拉伯数字同为8×16点阵,都是图形显示方式,所以,它们的显示子函数是通用的。 6.显示英文字母液晶显示模块LCM上显示英文字母,有两种方式:一种是内置字库;另一种是没有内置字库。 有内置字库的LCM,使用方便,节省CPU的ROM资源,显示字母时,发送该英文字母的ASCII码就可以了,但这种LCM成本相对高一些。 而没有内置字库的LCM,要显示字母时,其工作原理可以理解为显示图片,即把字母当成一个图片,在LCM上面显示而已。 字母变成“图片”,一般称之为字母点阵,所建立的大、小写字母的点阵如下所示。 unsigned int ASC2_char [] = { 0x00,0x00,0x00,0x18,0x3C,0x66,0x66,0x66, /*-- A --*/ 0x7E,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C, /*-- B --*/ 0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x60,0x60, /*-- C --*/ 0x60,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x78,0x6C,0x66,0x66,0x66, /*-- D --*/ 0x66,0x66,0x6C,0x78,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7C, /*-- E --*/ 0x60,0x60,0x60,0x7E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7C, /*-- F --*/ 0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x60,0x60, /*-- G --*/ 0x6E,0x66,0x66,0x3E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x7E, /*-- H --*/ 0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x18,0x18,0x18,0x18, /*-- I --*/ 0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06, /*-- J --*/ 0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x66,0x66,0x6C,0x6C,0x78, /*-- K --*/ 0x6C,0x6C,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60, /*-- L --*/ 0x60,0x60,0x60,0x7E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x63,0x63,0x77,0x6B,0x6B, /*-- M --*/ 0x6B,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x63,0x63,0x73,0x7B,0x6F, /*-- N --*/ 0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66, /*-- O --*/ 0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C, /*-- P --*/ 0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66, /*-- Q --*/ 0x66,0x66,0x66,0x3C,0x0C,0x06,0x00,0x00, 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C, /*-- R --*/ 0x6C,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x66,0x60,0x30,0x18, /*-- S --*/ 0x0C,0x06,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18, /*-- T --*/ 0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66, /*-- U --*/ 0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66, /*-- V --*/ 0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B, /*-- W --*/ 0x6B,0x36,0x36,0x36,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x66,0x66,0x34,0x18,0x18, /*-- X --*/ 0x2C,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3C, /*-- Y --*/ 0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7E,0x06,0x06,0x0C,0x18, /*-- Z --*/ 0x30,0x60,0x60,0x7E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x30,0x30,0x30,0x30, /*-- [ --*/ 0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x3C, 0x00,0x00,0x00,0x60,0x60,0x30,0x30,0x18, /*-- \ --*/ 0x18,0x0C,0x0C,0x06,0x06,0x00,0x00,0x00, 0x00,0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C, /*-- ] --*/ 0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x3C, 0x00,0x18,0x3C,0x66,0x00,0x00,0x00,0x00, /*-- ^ --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*-- _ --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, 0x00,0x38,0x18,0x0C,0x00,0x00,0x00,0x00, /*-- ` --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x06, /*-- a --*/ 0x3E,0x66,0x66,0x3E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x60,0x60,0x7C,0x66,0x66, /*-- b --*/ 0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x60, /*-- c --*/ 0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x06,0x3E,0x66,0x66, /*-- d --*/ 0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66, /*-- e --*/ 0x7E,0x60,0x60,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x1E,0x30,0x30,0x30,0x7E, /*-- f --*/ 0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66, /*-- g --*/ 0x66,0x66,0x66,0x3E,0x06,0x06,0x7C,0x7C, 0x00,0x00,0x00,0x60,0x60,0x7C,0x66,0x66, /*-- h --*/ 0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x18,0x18,0x00,0x78,0x18,0x18, /*-- i --*/ 0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, 0x00,0x00,0x0C,0x0C,0x00,0x3C,0x0C,0x0C, /*-- j --*/ 0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x78,0x78, 0x00,0x00,0x00,0x60,0x60,0x66,0x66,0x6C, /*-- k --*/ 0x78,0x6C,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18, /*-- l --*/ 0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x7E,0x6B,0x6B, /*-- m --*/ 0x6B,0x6B,0x6B,0x63,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66, /*-- n --*/ 0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66, /*-- o --*/ 0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66, /*-- p --*/ 0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60, 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66, /*-- q --*/ 0x66,0x66,0x66,0x3E,0x06,0x06,0x06,0x06, 0x00,0x00,0x00,0x00,0x00,0x66,0x6E,0x70, /*-- r --*/ 0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x3E,0x60,0x60, /*-- s --*/ 0x3C,0x06,0x06,0x7C,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x30,0x30,0x7E,0x30,0x30, /*-- t --*/ 0x30,0x30,0x30,0x1E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66, /*-- u --*/ 0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66, /*-- v --*/ 0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x63,0x6B,0x6B, /*-- w --*/ 0x6B,0x6B,0x36,0x36,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C, /*-- x --*/ 0x18,0x3C,0x66,0x66,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66, /*-- y --*/ 0x66,0x66,0x66,0x3C,0x0C,0x18,0xF0,0xF0, 0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C, /*-- z --*/ 0x18,0x30,0x60,0x7E,0x00,0x00,0x00,0x00, } 下面是显示8×16点阵的子函数,可以显示8×16的阿拉伯数字或英文字母。 void Display_8_16(uint row, uint col, uint *string) { uint strlen; /*字符串长度变量*/ uint temp_char; /*临时显示字符变量*/ uint i,j; /*显示字符循环变量*/ i=0; strlen=0; Set_Grap_Addr(row,col); /*设置图形显示区域显示地址*/ Cursor_Move('D'); /*得到*string的长度*/ while(string[strlen]!=0x00) { strlen++; } /*显示*string*/ for(i=0;i<strlen;i++) { Set_Grap_Addr(row,col); temp_char=string[i]; if( (temp_char>=0x20) && (temp_char<=0x7f) ) /*判断是否为可显示字符*/ { lcd_write_com(0x42); /*数据写入显示缓冲区命令*/ for(j=0;j<16;j++) /*显示一个字符*/ { lcd_write_dat(ASC_MSK[(temp_char-0x20)*16+j]); } } else {break;} col++; } } 7.显示汉字液晶显示模块LCM上显示汉字,有两种方式:一种是内置汉字库,另一种是没有内置汉字库。 有内置汉字库的LCM,使用方便,节省CPU的ROM资源,显示汉字时,发送该汉字的ASCII码就可以了。这种LCM成本相对高一些。 而没有内置汉字库的LCM,要显示汉字时,其工作原理可以理解为显示图片,即把汉字当成一个图片,在LCM上面显示而已。 汉字变成“图片”,一般称之为汉字点阵,而汉字点阵一般分为横向取模和纵向取模。下面就以汉字“电”为例(宋体、9号字,高:12点,宽:12点),来讲解这两种取模方式。 “电”的汉字点阵图如图18-25所示。
图18-25 “电”的汉字点阵图 横向取模的顺序是: 第1字节(8位) 第2字节(4位在高位) 第3字节(8位) 第4字节(4位在高位) ............ ............ 第23字节(8位) 第24字节(4位在高位) 横向取模方式取出的汉字点阵数据如下面大括号中所示。 unsigned char dian_h[]= { 0x04,0x00,0x04,0x40,0x7F,0xE0,0x44,0x40,0x7F,0xC0,0x44,0x40,0x44,0x40, 0x7F,0xC0,0x44,0x00,0x04,0x20,0x03,0xE0,0x00,0x00, }; 而纵向取模的顺序是: 第1字节(8位) 第13字节(4位在高位)
第2字节(8位) 第4字节(4位在高位)
............ ............ 第12字节(8位) 第24字节(4位在高位) 纵向取模方式取出的汉字点阵数据如下面大括号中所示。 unsigned char dian_z[]= { 0x00,0x3F,0x29,0x29,0x29,0xFF,0x29,0x29,0x29,0x7F,0x20,0x00,0x00,0x80,0x00, 0x00,0x00,0xC0,0x20,0x20,0x20,0x20,0x60,0x00, }; 讲解了汉字点阵的取模方式后,下面就来看看以SED1335为控制器的320×240液晶显示器中,汉字是如何被显示的。 下面的代码是显示12×12汉字点阵的代码。 void Display_12_12(uint row, uint col, uint *string) { uint i,j; Cursor_Move('R'); /*光标移动方向向右*/ for(i=0;i<12;i++) { Set_Grap_Addr(row,col); lcd_write_com(0x42); for(j=0;j<2;j++) { lcd_write_dat(string[i*2+j]); } row++; } } 8.显示图片以下代码是显示一个点阵图的子函数。图形显示作为人机交互界面中一个很重要的组成部分,对于改善界面、提供可操作性具有重要作用。 在下面代码中,假定要显示一幅100×46的点阵图。 void Display_pic(uint row, uint col, uint k) { uint i,j; Cursor_Move('R'); /*光标移动方向向右*/ for(i=0;i<46;i++) /*46行数据*/ { Set_Grap_Addr(row,col); lcd_write_com(0x42); for(j=0;j<13;j++) /*每行数据为13个字节*/ { lcd_write_dat(face[k*104+i*13+j]); } row++; } } 9.清除屏幕清屏就是将显示内存的内容全部置0或全部置1,LCM在全部置0时底色为蓝色,全部置1时底色为白色。 清屏的方法是:设置光标从地址0x0000开始,向显存连续写入0x00(或0xff)。 void Clear_Screen(void) { uint idata i; lcd_write_com(0x4c); /*设置光标移动方向,->*/ /*------------------------------------------------*/ lcd_write_com(0x46); /*设置光标地址命令*/ lcd_write_dat(0x00); /*设置光标地址指针低8位*/ lcd_write_dat(0x00); /*设置光标地址指针高8位*/ /*------------------------------------------------*/ lcd_write_com(0x42); /*数据写入显示缓冲区命令*/ for(i=0;i<0x6fff;i++) { lcd_write_dat(0x00); } } 10.显示进度条可以将进度条理解为一幅一幅静态画面,连续地显示在LCM的同一个位置上,组成进度条移动的景象,如图18-26所示。
图18-26 进度条静态图像对比 所以,进度条的显示就可以简化为以上静态画面的显示。 这些静态画面,外框4条边是固定的,可由下面的画线代码实现。该子函数中的x1、y1、x2、y2分别是左上角和右下角的坐标值。 void outline(uint x1,uint y1,uint x2,uint y2) { Line(x1,y1,x2,y1); Line(x1,y1,x1,y2); Line(x1,y2,x2,y2); Line(x2,y1,x2,y2); } 外框中的进度条,就是4个实心的矩形,而绘制矩形可通过以下代码实现。 void display_ rectangle (row,col) { Cursor_Move('R'); Set_Text_Addr(row,col); lcd_write_com(0x42); lcd_write_dat(0xff); } 18.4.7 SED1335应用示例<DIV>
图18-27 320×240液晶显示模块显示示例 </DIV> | 如图18-27所示,这是基于SED1335的320×240液晶显示模块构建的人机界面的实例图,上面显示了进度条、数字、汉字、英文字母、位图等。
若加上触摸屏,则这个人机交互界面将更加完美,易于操作。 读者也可以发挥自己的想象力和创造力,构建出更美好、更人性化的人机交互界面。
|