文字显示结果
组合搜索  计算机图书分类目录
 
所在位置: 图书 -> 在线试读 -> DSP嵌入式常用模块与综合系统设计实例精讲 
                 

第18章 多媒体人机交互系统

18.4 LCD液晶显示设计

18.4.1  简介及型号选择

LCDLiquid Crystal Display)以其功耗低、冷光源、显示灵活等特点,正逐步取代LED数码管等显示器件。

LCM,英文全称为LCD Control Module,意为“液晶控制模块”。狭义上讲,LCD只是液晶显示面板而已,其控制线繁多,时序也较为复杂;而单片机、DSP等嵌入式系统若和LCD直接连接,硬件连接、软件编写都很麻烦。所以,我们采用一个控制器,介于液晶面板和嵌入式系统之间,对于嵌入式系统来说,这个控制器提供8位或16位的接口,嵌入式系统可像访问片外RAM一样去读/写该控制器;而对于LCD显示面板来讲,这个控制器收到嵌入式系统发来的命令后,驱动LCD显示内容。这种连接嵌入式系统和LCD显示面板的“桥梁”作用可参考下节对SED1335内部框图的分析。

这种LCD控制器,一般有如下型号:KS0066ST7920T6963SED1335等。

常见的LCM按显示的内容可分为段型液晶、字符型液晶和图形型液晶;按颜色可分为单色液晶、灰度液晶和彩色液晶。

从显示的效果来讲,彩色液晶固然更加引人瞩目,但其价格高,而且控制复杂。另外,C6713内部没有彩色液晶控制器,没有专门的彩屏接口,因此C6713连接彩屏很费事,要外接彩屏控制器要用CPLDFPGAASIC作为接口转换器。经过性能、成本等方面的考虑并结合实际需要,我们选择了单色LCM,控制器是SED1335320×240分辨率,同样可以构建良好的显示界面。

18.4.2  控制芯片构架、寄存器

SED1335为控制芯片构成的LCM(液晶显示模块),分辨率大多为240×128320×240。下面我们就来介绍分辨率为320×240的液晶显示模块。国内兼容的产品型号有AG320240DV320240等。

SED1335是日本 SEIK EPSON 公司出品的液晶显示控制器,具有较强功能的I/O缓冲器,指令功能丰富,4位数据并行发送,最大驱动能力为640×256点阵,能显示文本和图形。

SED1335的特性如下:

显示模式:文本、图形、文本/图形混合;

在图形模式下,支持3个屏幕的交叠;

最高分辨率:640×256点;

可编程的光标控制;

支持68008080系列时序;

低功耗: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  SED13358080时序图

6800时序图如图18-20所示,由A0负责选通LCM的数据通道或命令通道。E表示使能,R/W表示读或写操作。DB0 ~DB7是数据输入或输出总线。

18-20  SED13356800时序图

8080系列、6800系列时序的切换通过SED1335SEL1SEL2引脚上的高低电平来确定,一般在液晶模块上有跳线帽或短路电阻来控制,详情请参考相应的液晶模块说明书。

320×240液晶显示模块引脚定义如表18-6

18-6  320×240液晶显示模块引脚定义

   

1

重启。低电平有效

2

8080时序:读信号

6800时序:使能信号

3

8080时序:写信号

6800时序:R/W信号

4

片选信号

5

A0

命令/数据选择

613

DB0DB7

数据输入(8位)

14

VDD

逻辑电源正极(5.0V3.3V

15

VSS

电压地(0V

16

VEE

LCD面板驱动电压

17

VO

对比度调节

1824

NC

悬空,不连接

18.4.3  硬件连接

320×240液晶显示模块与C6713的连接示意图如图18-21所示,由于为了和C6713的时序兼容,我们把液晶显示模块的时序定为8080时序。LCM上的跳线选择或电阻选择详情请参考相应液晶显示模块的说明书。

<DIV>

TMS320C6713

 

EA2

 

EA18

EA19

EA20

 

ED0ED7

 

ARE

AWE

</DIV>
<DIV>

SE1335液晶显示模块

 

A0

 

 

 

 

D0D7

RD

WR

</DIV>
<DIV>

74LS138

译码

</DIV>

18-21  320×240液晶显示模块和C6713的连接示意图

SED1335液晶显示模块和C6713的连接,其实不复杂,其时序就如同访问外部RAM一样。说到硬件设计,就不得不说LCM的背光方式了。

LCM的背光方式,一般分为LEDCCFLEEFL等方式。

1CCFLCold Cathode Fluorescent Lamp,冷阴极荧光灯管),由于CCFL的技术工艺成熟、信赖性高、性能稳定,所以,CCFL作为LCD的背光有不少的市场占有率。

CCFL驱动电路较为复杂,要用逆变器产生驱动电压,外部电路复杂,增加了电子系统的总成本。另外这些高频、大功率的交流电压必定会对其他电路产生影响,如对距离屏幕较近的触摸屏芯片AD7843

2EEFLExternal Electrode Fluorescent Lamp,外置电极荧光灯),也是用逆变器产生驱动电压来发光的。

3LEDLight Emitting Diode,发光二极管),特点是:寿命长、不含汞、环保性能更好、不需要变换器、功耗低等。LED的背光方式中电路很简单,只要正向驱动电压即可,无须像CCFLEEFL那样需要逆变器,还可以采用PWMPulse Width Modulation,脉宽调制)的方法来控制亮度,从而更好、更方便、更简易地与数字电路连接。

如图18-22是所示的LED背光方式示意图,在这种形式下,接入5V直流电即可产生背光。LED是冷电源,功耗小、效率高且连接方便,无须逆变器等外接电源器件,产生的干扰也小。

如图18-23所示的是EEFL背光方式示意图,需要加入逆变器。

       
<DIV>

LCM

 

 

+

 

LED背光电路

           -

</DIV>
<DIV>

5V

</DIV>
   
<DIV>

交流100V400Hz

</DIV>
<DIV>

LCM

 

 

             

 

EEFL背光电路

 

            

</DIV>
<DIV>

逆变器

</DIV>
<DIV>

直流输入

</DIV>

18-22  LED背光方式示意图                     18-23  EEFL背光方式示意图

如图18-24所示的是CCFL背光方式示意图,也需要加入逆变器。

<DIV>

交流390V55kHz

</DIV>
<DIV>

LCM

 

 

 

 

 

 

CCFL背光电路

 

 

</DIV>
<DIV>

逆变器

</DIV>
<DIV>

直流输入

</DIV>

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的命令输入通道, 分别为10,表示当前是写操作。

本命令用来进行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,从而让其显示。

首先,来讲解最底层的硬件驱动函数。

C6713SED1335液晶控制器的底层驱动函数包括写命令、写数据、读数据、判读就绪等子函数。

在本实例中,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液晶模块以其高分辨率,可显示字符、数字、汉字、图形等特性,符合我们构建图形界面的需求,可以构建良好的人机交互平台。

1SED1335初始化

以下程序是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;

    /*  比较XY方向上距离的大小*/

    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.画圆弧

以下代码是画圆弧的子函数。根据数学方程:

式中,x0y0分别为圆心的坐标值,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,使用方便,节省CPUROM资源,显示字母时,发送该英文字母的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,使用方便,节省CPUROM资源,显示汉字时,发送该汉字的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或全部置1LCM在全部置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_com0x42);          /*数据写入显示缓冲区命令*/

    for(i=0;i<0x6fff;i++)

    {

        lcd_write_dat(0x00);

    }

}

10.显示进度条

可以将进度条理解为一幅一幅静态画面,连续地显示在LCM的同一个位置上,组成进度条移动的景象,如图18-26所示。

18-26  进度条静态图像对比

所以,进度条的显示就可以简化为以上静态画面的显示。

这些静态画面,外框4条边是固定的,可由下面的画线代码实现。该子函数中的x1y1x2y2分别是左上角和右下角的坐标值。

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所示,这是基于SED1335320×240液晶显示模块构建的人机界面的实例图,上面显示了进度条、数字、汉字、英文字母、位图等。

若加上触摸屏,则这个人机交互界面将更加完美,易于操作。

读者也可以发挥自己的想象力和创造力,构建出更美好、更人性化的人机交互界面。

 
 
  上一页 返回 下一页  
 
Copyright © 2010 TianMei Technology All rights reserved. To comment on this site
  辽B-2-4-20100065