Date: 23-Nov-2011
1.LCD简介
LCD 液晶显示器是 Liquid Crystal Display 的简称,LCD 的构造是在两片平行的玻璃当中放置液态的晶体,两片玻璃中间有许多垂直和水平的细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面。TFT-LCD主要由背光模组及TFT模组组成。
◆ 背光模组(Back Light):提供电源
◆ 上下偏光片(Polarizer),TFT玻璃基板(Glass substrate),液晶(Liqurd crystal):形成偏振光,控制光线通过与否
◆ 彩色滤光片(Color Filter):提供TFT-LCD R/G/B(三原色)
◆ ITO透明导电层:提供透明的导电电路
和TN技术不同的是,TFT的显示采用“背透式”照射方式——假想的光源路径不是像TN液晶那样从上至下,而是从下向上。这样的作法是在液晶的背部设置特殊光管,光源照射时通过下偏光板向上透出。由于上下夹层的电极改成FET电极和共通电极,在FET电极导通时,液晶分子的表现也会发生改变,可以通过遮光和透光来达到显示的目的,响应时间大大提高到80ms左右。因其具有比TN-LCD更高的对比度和更丰富的色彩,荧屏更新频率也更快,故TFT俗称“真彩”。
TFT-LCD中导电玻璃上有网状的细小线路,电极则是由薄膜式晶体管所排列而所的矩阵开关,在每个线路相交的地方配有半导体开关器件,各显示点半导体开关器件配合驱动讯号开启或关闭液晶分子的电压,使液晶分子轴转向而成亮或暗的对比。相对于DSTN而言,TFT-LCD的主要特点是为每个像素配置一个半导体开关器件。由于每个像素都可以通过点脉冲直接控制。因而每个节点都相对独立,并可以进行连续控制。这样的设计方法不仅提高了显示屏的反应速度,同时也可以精确控制显示灰度,这就是TFT色彩较DSTN更为逼真的原因。
2.LCD屏相关术语
◆ 像素(Pixel): 是LCD上的一个点,是显示屏上所能控制的最小单位;
◆ 分辨率(Reselution): LCD上像素的数目,用横向(列)点数X纵向(行)点数表示,如:320X240、640X480等;
◆ 色深(Bit Per Pixel): 指在某一分辨率下,每一像素可以用多少种色彩来描述,单位是bit,也称为位深。色深和分辨率之积决定了显存的大小;
◆ 灰度(Grey level): 指纯白、纯黑以及两者中的一系列从黑到白的过渡色;
◆ 刷新频率(Refresh rate): 图像在屏幕上更新的速度,也即屏幕上的图像每秒钟出现的次数,单位是Hz;
◆ 行(Line): 每一行图像数据;
◆ 帧(Frame): 每一幅图像数据;
◆ 虚拟屏(Virtual screen): 显示的图像尺寸大于LCD物理尺寸时,用虚拟屏可完整显示该图像;
◆ 物理尺寸(Screen size): LCD的对角线长度,单位为英寸。一般为1.8、3.5英寸等。
3.LCD控制框图及控制信号说明
要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S 3C2410/2440等。通过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/TFT屏了。
◇ REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的;
◇ LCDCDMA是一专用DMA,它能自动地把在帧内存中的视频数据传送到LCD驱动器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上;
◇ VIDPRCS接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;
◇ TIMEGEN和LPC3600负责生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等等,而这些控制信号又与REGBANK寄存器组中的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同形态,从而支持不同的LCD驱动器(即不同的STN/TFT屏)。
◇ VFRAME/VSYNC/STV:帧同步信号(STN)/垂直同步信号(TFT),该信号每发出一个脉冲,意味着新的1幅图像数据开始传送;
◇ VLINE/HSYNC/CPV:行同步信号(STN)/水平同步信号(TFT),每个HSYNC脉冲表明新的1行图像数据开始传送;
◇ VDEN/VM/TP:数据使能信号(TFT),用来标明图像数据有效;
◇ VCLK:像素时钟信号;
4.TFT-LCD工作时序分析
◇ VSPW:垂直同步信号脉冲宽度,用行数计算;
◇ VBPD:垂直同步信号后肩,表一帧图像开始时,垂直同步信号以后的无效的行数;
◇ VFPD:垂直同步信号前肩,表一帧图像结束后,垂直同步信号以后的无效的行数;
◇ HSPW:水平同步信号脉冲宽度,用VCLK计算;
◇ HBPD:水平同步信号后肩,表水平同步信号开始到一行的有效数据开始之间的VCLK的个数;
◇ HFPD:水平同步信号前肩,表一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数;
◇ LINEVAL:垂直显示尺寸,即屏行宽;
◇ HOZVAL:水平显示尺寸,即屏列宽。
由该图可知:
1)扫描一帧图像所需要时间为:
((VSPW+1)+(VBPD+1)+( LINEVAL+1)+(VFPD+1))个行时间。
2)扫描一行所所需的时间:
((HSPW+1)+(HSPD+1)+(HFPD+1)+ (HOZVAL+1))个VCLK时间。
3)而一个VCLK时间由LCD寄存器LCDCON1内的CLKVAL决定:
HCLK/[2*(CLKVAL+1)]
4)因此扫描一帧所需的时间:
T=[(VSPW+1)+(VBPD+1)+( LINEVAL+1)+(VFPD+1)]* [(HSPW+1)+(HSPD+1)+(HFPD+1)+ (HOZVAL+1)]* HCLK/[2*(CLKVAL+1)]
5)帧刷新频率为:1/T
在帧同步及行同步的头尾必须留有回扫时间(VBPD/VFPD/HBPD/HFPD),这种时序要求是当初CRT显示器由于电子枪偏转需要时间,后来成了实际上的工业标准,以至后来出现的TFT-LCD为了在时序上与CRT兼容,也采用这样的控制时序。FL2440开发板所用东华TFT-LCD WXCAT35的时序以及相关参数如下图:
5.16BPP 5:6:5模式显存数据格式
6.TFT-LCD寄存器设置
//TFT 320240
#define LCD_XSIZE_TFT_320240 (320)
#define LCD_YSIZE_TFT_320240 (240)
//虚拟屏
#define SCR_XSIZE_TFT_320240 (320)
#define SCR_YSIZE_TFT_320240 (240)
#define HOZVAL_TFT_320240 (LCD_XSIZE_TFT_320240-1)
#define LINEVAL_TFT_320240 (LCD_YSIZE_TFT_320240-1)
//Timing parameter for LCD WXCAT35
//HCLK=100Mhz,VCLK=6.25MHz,VCLK=HCLK/[2*(CLKVAL+1)]
#define CLKVAL_TFT_320240 (8-1)
#define VBPD_320240 (15-1) //垂直同步信号的后肩
#define VFPD_320240 (12-1) //垂直同步信号的前肩
#define VSPW_320240 (3-1) //垂直同步信号的脉宽
#define HBPD_320240 (38-1) //水平同步信号的后肩
#define HFPD_320240 (20-1) //水平同步信号的前肩
#define HSPW_320240 (30-1) //水平同步信号的脉宽
#define M5D(n) ((n) & 0x1fffff) // To get lower 21bits
//320×240 16Bpp TFT-LCD初始化
static void LCD_Port_Init(void){
rGPCUP=0xffffffff; // Disable Pull-up register
rGPCCON=0xaaaa56a9; //VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
rGPDUP=0xffffffff; // Disable Pull-up register
rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]
rGPGUP=rGPGUP&(~(1<<4))|(1<<4); // Pull-up disable
rGPGCON=rGPGCON&(~(3<<8))|(3<<8); //GPG4=LCD_PWREN
// TFT LCD panel,16bpp TFT,ENVID=off
rLCDCON1=(CLKVAL_TFT_320240<<8)|(3<<5)|(12<<1);
rLCDCON2=(VBPD_320240<<24)|(LINEVAL_TFT_320240<<14)|(VFPD_320240<<6)|(VSPW_320240);
rLCDCON3=(HBPD_320240<<19)|(HOZVAL_TFT_320240<<8)|(HFPD_320240);
rLCDCON4=(13<<8)|(HSPW_320240);
rLCDCON5=(1<<11)|(1<<9)|(1<<8)|(1);
//设置显存Frame buffer起始地址
rLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|M5D((U32)LCD_BUFFER>>1);
//设置显存Frame buffer结束地址
rLCDSADDR2=M5D(((U32)LCD_BUFFER+(SCR_XSIZE_TFT_320240*LCD_YSIZE_TFT_320240*2))>>1 );
rLCDSADDR3=(((SCR_XSIZE_TFT_320240-LCD_XSIZE_TFT_320240)/1)<<11)|(LCD_XSIZE_TFT_320240/1);
//禁止LCD中断
rLCDINTMSK|=(3); // MASK LCD Sub Interrupt
//禁用调色板
rTPAL=0; // Disable Temp Palette
}
7.代码分析 TFTLCD_WXCAT35.c
#include "def.h"
#include "Option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "UART.h"
#include "Mitsubishi.h" //用Bmp2RGB.exe软件生成RGR565图像数据的C数组
//TFT 320240
#define LCD_XSIZE_TFT_320240 (320)
#define LCD_YSIZE_TFT_320240 (240)
//虚拟屏
#define SCR_XSIZE_TFT_320240 (320)
#define SCR_YSIZE_TFT_320240 (240)
#define HOZVAL_TFT_320240 (LCD_XSIZE_TFT_320240-1)
#define LINEVAL_TFT_320240 (LCD_YSIZE_TFT_320240-1)
//HCLK=100Mhz,VCLK=6.25MHz
#define CLKVAL_TFT_320240 (8-1)
//Timing parameter for LCD WXCAT35
#define VBPD_320240 (15-1) //垂直同步信号的后肩
#define VFPD_320240 (12-1) //垂直同步信号的前肩
#define VSPW_320240 (3-1) //垂直同步信号的脉宽
#define HBPD_320240 (38-1) //水平同步信号的后肩
#define HFPD_320240 (20-1) //水平同步信号的前肩
#define HSPW_320240 (30-1) //水平同步信号的脉宽
#define M5D(n) ((n) & 0x1fffff) // To get lower 21bits
static volatile unsigned short LCD_BUFFER[SCR_YSIZE_TFT_320240][SCR_XSIZE_TFT_320240];
//320×240 16Bpp TFT-LCD初始化
static void LCD_Port_Init(void){
rGPCUP=0xffffffff; // Disable Pull-up register
rGPCCON=0xaaaa56a9; //VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
rGPDUP=0xffffffff; // Disable Pull-up register
rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]
rGPGUP=rGPGUP&(~(1<<4))|(1<<4); // Pull-up disable
rGPGCON=rGPGCON&(~(3<<8))|(3<<8); //GPG4=LCD_PWREN
// TFT LCD panel,16bpp TFT,ENVID=off
rLCDCON1=(CLKVAL_TFT_320240<<8)|(3<<5)|(12<<1);
rLCDCON2=(VBPD_320240<<24)|(LINEVAL_TFT_320240<<14)|(VFPD_320240<<6)|(VSPW_320240);
rLCDCON3=(HBPD_320240<<19)|(HOZVAL_TFT_320240<<8)|(HFPD_320240);
rLCDCON4=(13<<8)|(HSPW_320240);
rLCDCON5=(1<<11)|(1<<9)|(1<<8)|(1);
//设置显存Frame buffer起始地址
rLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|M5D((U32)LCD_BUFFER>>1);
//设置显存Frame buffer结束地址
rLCDSADDR2=M5D(((U32)LCD_BUFFER+(SCR_XSIZE_TFT_320240*LCD_YSIZE_TFT_320240*2))>>1 );
rLCDSADDR3=(((SCR_XSIZE_TFT_320240-LCD_XSIZE_TFT_320240)/1)<<11)|(LCD_XSIZE_TFT_320240/1);
rLCDINTMSK|=(3); // MASK LCD Sub Interrupt
//禁用调色板
rTPAL=0; // Disable Temp Palette
}
//LCD 电源控制
static void LCD_Power_Enable(BYTE pwren){
rLCDCON5=rLCDCON5&(~(1<<3))|(pwren<<3); // PWREN
}
//LCD 视频和控制信号输出控制
static void LCD_Envid_OnOff(BYTE onoff){
rLCDCON1 =rLCDCON1&(~(1<<0))|(onoff<<0); //Envid
}
//LCD全屏填充特定颜色单元或清屏
static void LCD_Clear_Scr( U32 color){
U16 x,y ;
for( y = 0 ; y < SCR_YSIZE_TFT_320240 ; y++ )
{
for( x = 0 ; x < SCR_XSIZE_TFT_320240 ; x++ )
{
LCD_BUFFER[y][x] = color ;
}
}
}
//LCD单个象素的显示数据输出
static void LCD_PutPixel(U32 x,U32 y, U32 color ){
if ( (x < SCR_XSIZE_TFT_320240) && (y < SCR_YSIZE_TFT_320240) )
LCD_BUFFER[(y)][(x)] = color;
}
//在LCD屏幕上用颜色填充一个矩形
static void LCD_Glib_FilledRectangle(U16 x1,U16 y1,U16 x2,U16 y2,U16 color){
U16 i,j;
for(i=y1;i<=y2;i++)
{
for(j=x1;j<=x2;j++)
{
LCD_BUFFER[i][j] = color;
}
}
}
//在LCD屏幕上指定坐标点画一个指定大小的图片
static void LCD_Paint_Bmp(U16 x0,U16 y0,U16 h,U16 l,unsigned int bmp[]){
int x,y;
int p = 0;
for( y = y0 ; y < l ; y++ )
{
for( x = x0 ; x < h ; x++ )
{
LCD_BUFFER[y0+y][x0+x] = bmp[p++];
}
}
}
void TFTLCD_WXCAT35_Test( void ) {
LCD_Port_Init();
LCD_Power_Enable(EN); //Power Enable
LCD_Envid_OnOff(ON); //Turn on vedio
LCD_Clear_Scr((0xff<<11)|(0xff<<5)|(0xff)); //Clear screen
LCD_PutPixel(50,50,(0x0<<11)|(0x0<<5)|(0xff));
LCD_Glib_FilledRectangle(100,100,200,200,(0xff<<11)|(0x0<<5)|(0x0));
LCD_Paint_Bmp( 0, 0, 320, 240, Mitsubishi );
}
8. 测试程序及结果
#include "TFTLCD_WXCAT35.h"
int Main(void)
{
TFTLCD_WXCAT35_Test();
while(1){
;
}
return 0;
}
9.Bmp2RGB.exe使用介绍
1)用图形处理软件制作320X240的bmp图形文件Mitsubishi.bmp
2)在Bmp2RGB.exe中加载图形文件并按要求格式转换
3)生成C数组Mitsubishi.h
4)软件下载地址:http://space.ednchina.com/Upload/2009/7/22/0002eaa2-bb78-421a-8985-cd118df51d6f.rar
10.TFTLCD显示汉字
1)16X16中文字模表示原理
2)用取模软件ZIMO21.exe生产所需要文字C数组
3)代码分析
//"武" 64*64
unsigned char char5[]={
0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,
0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,
0x00,0x00,0x00,0x7F,0xF8,0xFE,0x00,0x00,0x00,0x00,0x01,0xFF,0xF8,0x7F,0x80,0x00,
0x00,0x00,0xFF,0xFF,0xFC,0x3F,0xC0,0x00,0x00,0x00,0xFF,0xFF,0xFC,0x1F,0xC0,0x00,
0x00,0x00,0xFF,0xFF,0xF8,0x1F,0xC0,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x1F,0xC0,0x00,
0x00,0x00,0x3F,0xFF,0xF0,0x7F,0xC0,0x00,0x00,0x00,0x1F,0xFF,0xF0,0x7F,0xC0,0x00,
0x00,0x00,0x0F,0xFF,0xF0,0x3F,0x00,0x00,0x00,0x00,0x07,0xFC,0xFF,0x00,0x00,0x00,
0x00,0x00,0x07,0xF8,0x7F,0x80,0x00,0x00,0x00,0x00,0x0F,0xF1,0xFF,0xC0,0x00,0x00,
0x00,0x00,0x1F,0xEF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x3F,0xBF,0xFF,0xC0,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,0x00,
0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0x3E,0x00,0x00,0x00,
0x00,0x07,0xFF,0xFC,0x3F,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x7F,0x00,0x00,0x00,
0x00,0x1F,0xFF,0xC0,0x7F,0x80,0x00,0x00,0x00,0x3F,0xFF,0x80,0xFF,0x80,0x00,0x00,
0x00,0xFF,0xFE,0x03,0xE7,0x80,0x00,0x00,0x01,0xFF,0xFC,0x77,0xE7,0xC0,0x00,0x00,
0x01,0xFF,0xF8,0xFF,0xC3,0xC0,0xC0,0x00,0x01,0xFF,0x71,0xFF,0x83,0xE0,0xC0,0x00,
0x00,0xFE,0xF3,0xFF,0xE1,0xE0,0xC0,0x00,0x00,0xFE,0xFB,0xFE,0xF1,0xF0,0x60,0x00,
0x00,0x7D,0xFB,0xF8,0x79,0xF0,0x60,0x00,0x00,0x01,0xF9,0xF0,0xFC,0xF8,0x60,0x00,
0x00,0x01,0xF8,0xE3,0xFC,0xF8,0x60,0x00,0x00,0x01,0xF0,0x0F,0xF0,0x7C,0x60,0x00,
0x00,0x01,0xF0,0x3F,0xE0,0x7C,0x70,0x00,0x00,0x01,0xF1,0xFF,0x80,0x3E,0x70,0x00,
0x00,0x01,0xF7,0xFE,0x00,0x3F,0x70,0x00,0x00,0x01,0xFF,0xFC,0x00,0x1F,0x78,0x00,
0x00,0x01,0xFF,0xF0,0x00,0x0F,0xB8,0x00,0x00,0x00,0xFF,0xE0,0x00,0x0F,0xF8,0x00,
0x00,0x00,0xFF,0xC0,0x00,0x07,0xFC,0x00,0x00,0x00,0x7F,0x80,0x00,0x03,0xFC,0x00,
0x00,0x00,0x1F,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
//显示64*64字符,输入参数:显示座标值,字体颜色,背景颜色以及字符数组指针
void LCD_Put_64X64Char(U16 x0, U16 y0, U32 color_font, U32 color_bg, unsigned char cha[])
{
U16 row,c,c1,p=0,p1=0,data;
for(row=0;row<64;row++){ //行
for(c1=0;c1<4;c1++){ //列4*16
for(c=0;c<16;c++){
data = (cha[p]<<8 | cha[p+1]); //LCD显示格式为16BPP
if (data & (1<<(15-c))){ //判断字模某行中的某列是否为1
LCD_PutPixel(p1+x0,row+y0,color_font); //为1,该点显示字体色
}
else{
LCD_PutPixel(p1+x0,row+y0,color_bg); //为0,该点显示背景色
}
p1++; //指向下一点
}
p = p+2; //指向下一16Bit数据
}
p1 = 0; //指向下一行
}
}
4)测试结果