当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > 裸奔之LCD
裸奔之LCD
时间:2016-12-12作者:华清远见

一、LCD的介绍

LCD 液晶显示器是 Liquid Crystal Display 的简称,LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置TFT(薄膜晶体管),上基板玻璃上设置彩色滤光片,通过TFT上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。现在LCD已经替代CRT成为主流,价格也已经下降了很多,并已充分的普及。

上面的这种定义方式说的是LCD众多类型中的TFT-LCD,LCD按其控制方式不同,有多种类型。比如:STN、TFT、LTPS,OLED等,各有优缺点.这里简单介绍一下STN-LCD(Super Twisted Nematic-Liquid Crystal Display)和TFT-LCD(Thin Film Transistor-Liquid Crystal Display)两类显示器的工作原理,其他的读者自行了解.

二、TFT和LCD

STN-LCD和TFT-LCD都使用一种被称为"向列型"的丝状液晶物质,利用电场来控制"丝状"液晶的方向。通常液态晶体包在两片玻璃中间,在玻璃的表面上先镀有一层透明而且导电的薄膜以作电极之用,然后在有薄膜的玻璃上镀一层称为配向剂的物质,以使液晶随着一个特定且平行于玻璃表面的方向扭转。

STN-LCD显示屏中的液晶,其自然状态具有90度的扭转,利用电场可使液晶再进行旋转,液晶的折射系数随液晶的方向改变而改变,光经过STN型液晶后,偏极性发生变化,只要选择适当,使光的偏极性旋转到180度到270度,就可以利用两个平行偏光片使光完全不能通过。若使液晶方向和电场方向平行,这样光的偏极性就不会改变,光就可以通过第二个偏光片。于是,就可以控制光的明暗了。而STN液晶之所以可以显示彩色,那是因为它在STN液晶显示屏上加了一个彩色的滤光片,并将单色显示矩阵中的每一个像素分成三个子像素,分别通过彩色滤光片显示红,绿,蓝三原色,就可以显示出彩色。STN型液晶属于放射式LCD器件,它的好处是功耗小,但在比较暗的环境中清晰度很差,所以不得不配置外部照明光源。 而TFT液晶显示技术采用了"主动式矩阵"的方式来驱动。方法是利用薄膜技术所做成的电晶体电极,利用扫描的方法"主动的"控制任意一个显示点的开和关。电极通过时,液晶分子就像STN液晶的排列状态一样会发生改变,也通过折光和透光来达到显示的目的。看起来和STN原理差不多。但不同的是,由于 TFT 晶体管具有电容效应,能够保持电位状态,已经透光的液晶分子会一直保持这种状态,知道TFT电极下一次再加电改变其排列方式为止,而STN型液晶就没有找个特性,液晶分子一旦没有电场,立刻就返回了原来的状态,这是TFT液晶和STN液晶显示原理的大不同之处。

三、FrameBuffer机制

FrameBuffer也叫帧缓存,它的意思是在我们的内存中开辟出以块内存,当作显存用。我们只需要将我们要显示的一副图片像素数据存放到这一块内存中,就能在LCD上显示我们的图片了。

这里以S3C2410为例,LCD控制器内部有一个专用的DMA。在这里我们只需要配置好LCD控制器就可以了,将显存的地址告诉LCD控制器。当LCD内部DMA的FIFO为空时,LCD控制器会自动发起DMA传输从内存中获取图像数据。

四、TFT-LCD的时序

要想很好的操作TFT-LCD显示屏,首先得搞清楚其时序:
        每个VSYNC信号表示一帧数据的开始,每个HSYNC信号表示一行数据的开始,每个VCLK表示正在传输一个像素的数据。LCD根据VSYNC、HSYNC、VCLK不停地读取总线数据、显示。

下面我们简单来说一下时序图:

(1)VSYNC信号有效时,表示一帧数据的开始
        (2)VSPW表示VSYNC信号的脉冲宽度为(VSPW+1)个HSYNC信号周期,即(VSPW+1)行,这(VSPW+1)行数据无效
        (3)VSYNC信号脉冲之后,还要经过(VBPD+1)个HSYNC信号周期,有效的行数据才出现。所以,在VSYNC信号有效之后,总共还要经过(VSPW+1+VBPD+1)个无效的行,第一个有效的数据才会出现。
        (4)随后即连续发出(LINEVAL+1)行的有效数据。
        (5)后是(VFPD+1)个无效的行,完整的一帧结束,紧接着就是下一个帧的数据了(即下一个VSYNC信号)

现在深入一行中像素数据传输的过程:

(1)HSYNC信号有效时,表示一行数据的开始
        (2)HSPW表示HSYNC信号的脉冲宽度为(HSPW+1)个VCLK信号周期,即(HSPW+1)个像素,这(HSPW+1)个像素的数据无效。
        (3)HSYNC信号脉冲之后,还要经过(HBPD+1)个VCLK信号周期,有效的像素数据才出现。所以,在HSYNC信号有效之后,总共还要经过(HSPW+1+HBPD+1)个无效的像素,第一个有效的像素才出现。
        (4)随后即连续发出(HOZVAL+1)个像素的有效数据
        (5)后是(HFPD+1)个无效的像素,完整的一行结束,紧接着下一行的数据了(即下一个HSYNC信号)

这里需要注意的是上图给出的时序是S3C2410数据手册给出的一个范例,具体的LCD屏时序需要根据屏的数据手册获得。我使用的是东华WXHAT35-TG2 320X240的TFT屏,时序如下:

可以看到和标准的时序很像,我们只需要配置LCD控制器,让其发出上图的时序,我们的屏就可以很好的工作了。

五、核心实验代码

如何配置其控制器,这里我就不再赘述了,网上的资料很多,说的都很详细。这里简单的说一下实验代码:

//初始化LCD控制器
        int tft_lcd_init()
        {
        unsigned int addr = (unsigned int )LCD_BUFER;
        /*
        *LCDCON1:
        *设置VCLK的频率:VCLK(HZ) = HCLK/[(CLKVAL + 1) x 2]
        *选择LCD类型:TFT LCD
        *设置显示模式:16 BPP
        *先禁止LCD信号输出
        */
        LCDCON1 = (CLKVAL << 8) | (PNRMODE << 5) | (BPPMODE << 1) | VID_DIS;
        /*
        *LCDCON2:设置LCD的垂直同步信号时序参数
        *VBPD:垂直同步信号的后肩
        *LINEVAL:LCD屏上有效的行数
        *VFPD:垂直同步信号的前肩
        *VSPW:垂直同步信号的脉宽
        */
        LCDCON2 = S3C2410_LCDCON2_LINEVAL(LCD_Y_SIZE - 1) |\
        S3C2410_LCDCON2_VBPD(UPPER_MARGIN - 1) |\
        S3C2410_LCDCON2_VFPD(LOWER_MARGIN - 1) |\
        S3C2410_LCDCON2_VSPW(VSYNC_LEN - 1);
        /*
        *LCDCON3:设置LCD的水平同步信号时序参数
        *HBPD:水平同步信号的后肩
        *HOZAL:LCD屏图像显示的宽度
        nbsp;*HFPD:水平同步信号的前肩
        */
        LCDCON3 = S3C2410_LCDCON3_HBPD(RIGHT_MARGIN - 1) |\
        S3C2410_LCDCON3_HFPD(LEFT_MARGIN - 1) |\
        S3C2410_LCDCON3_HOZVAL(LCD_X_SIZE - 1);
        /*
        *LCDCON4:水平同步信号的脉宽
        */
        LCDCON4 = S3C2410_LCDCON4_HSPW(HSYNC_LEN - 1);
        /*
        *LCDCON5:
        *设置显示模式为16BPP时的数据格式: 5:6:5
        *设置HSYNC,VSYN脉冲的极性(这需要参考具体LCD的接口信号)
        */
        LCDCON5 = (FORMAT_565 << 11) | (GET_DATA << 10) | (HSYNC_INV << 9)\
        | (VSYNC_INV << 8) | (HWSWP << 1);
        /*
        *设置LCD控制器的地址寄存器LCDSADDR1~3
        *帧内存与视口(view point)完全吻合
        *1.LCDSADDR1:
        *设置LCDBANK,LCDBASEU
        *
        *2.LCDSADDR2:
        *设置LCDBASEL:帧缓冲的结束地址A[21:1]
        *
        *3.LCDSADDR3:
        *OFFSIZE等于0,PAGEWIDTH等于(320/2)[注意:以半字为单位]
        */
        LCDSADDR1 = ((addr >> 22) << 21) | ((addr >> 1) & 0x1fffff);
        LCDSADDR2 = ((addr + LCD_X_SIZE * LCD_Y_SIZE * 2) >> 1) & 0x1fffff;
        LCDSADDR3 = (0 << 11) | (LCD_X_SIZE / 2);
        //禁用条色板
        TPAL = 0;
        //MASK LCD sub Interrupt
        LCDINTMSK = 3;
        //Disable LPC3480
        LPCSEL &= ~7;
        return 0;
        }

/*在LCD屏幕的指定坐标点绘制一幅图像*/
        static void paint_bmp(int x0,int y0,int x1,int y1,unsigned char bmp[])
        {
                int x,y;
                unsigned short c;
                int p = 0;
                for(y = 0;y < y1;y ++)
                {
                        for(x = 0;x < x1; x ++)
                        {
        &nnbsp;                       c = bmp[p+1] | ( bmp[p] << 8);
                                if((x0 + x) < LCD_X_SIZE && (y0 + y) < LCD_Y_SIZE)
                                {
                                        LCD_BUFER[y0 + y][x0 + x] = c;
                                }
                        p = p + 2;
                        }
                }
                return;
        }

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)