您的位置:首页 > 其它

S3C2410TFT LCD分析

2014-11-16 10:42 225 查看
S3C2410TFT LCD分析

TFT LCD的系统整体结构如下图所示,有LCD控制器,显示缓存SDRAM区以及LCD驱动器,电源;其中需要编程人员进行操作的是LCD控制器和对显示缓存的处理,即对这两者相关的寄存器编程。



图1 LCD系统结构框图



图2 LCD控制器的结构框图
LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器组成;

REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的;

LCDCDMA是一个专用的DMA,它能自动地把在侦内存中的视频数据传送到LCD驱动器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上;

VIDPRCS接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;

TIMEGEN由可编程的逻辑组成,他生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等,而这些控制信号又与REGBANK寄存器组中的LCDCON1/2/3/4/5的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同形态,从而支持不同的LCD驱动器(即不同的STN/TFT屏)。

1. 时序分析






在帧的领域里,我们所说的周期单位是一行,即1帧说的是一行数据,帧的时钟是HSYNC;而在行的时候,我们所说的周期单位是VCLK时钟周期。我们可以将图像看成一个矩形的点阵,由很多排列整齐的点一行一行组成,这些点称之为像素。以240*320的屏为例:

在1 Line内分析,以像素点为单位,一个VCLK周期传输一组VD信号,从而给一个像素着色。要点亮一行,那么要有240个VCLK周期将240个pixel的VD值输出,而且这240个周期内VDEN应该一直是有效的。现在我们的思路从点扩展到行。

在1Frame内分析,以行为单位,我们引入了行同步HSYNC信号,也就是说在传输完一行的数据后,先歇一会儿,等待若干个时钟(我们称之为后插入等待周期HFPD+1);然后我们送一个行同步信号,当然这个信号的有效周期数我们也能控制(我们称之为同步周期HSPW+1);之后呢,我们在等一会,让 LCD驱动电路准备好接收,我们在把一行的数据发下去(这个等待时间我们称之为前插入等待周期HBPD+1)。

在数据发送过程来分析,以帧为单位;在帧与帧切换之间也是需要一定的时间的,我们称之为帧切换,那么LCD整个显示的过程在时间线上看,就可表示为时序图上的VSYNC。

在行中考虑,HSPW+1、HBPD+1、HFPD+1就是我们分别定义了同步周期、前插入等待周期、后插入等待周期;而HOZVAL+1则是一行的有效象素数目。

以帧来考虑,也应该是类似于行的结构,同样包含了同步周期VSPW+1、前插入等待周期VBPD+1、后插入等待周期VFPD+1;而LINEVAL+1表示这一帧中的有效行数目。

经过上述的分析,我们可以把TFT LCD的接口归纳到8个参数上:HSPW、HBPD、HFPD、HOZVAL、VSPW、VBPD、VFPD、LINEVAL。另外,通过上述分析,我们可以看到,显示一帧图像总共需要的VCLK周期为:(HSPW+HBPD+HFPD+HOZVAL+4)*(VSPW+VBPD+VFPD+ LINEVAL+4)。

寄存器编程:由时序计算出下列数据,在相应寄存器中写入对应值即可。

所要显示的LCD屏大小为320×240,故有:

VSPW+1=2-> VSPW=1 HSPW+1=4 -> HSPW=3

VBPD+1=2-> VBPD=1 HBPD+1=7 -> HBPW=6

VFPD+1=3-> VFPD=2 HFPD+1=31 -> HFPD=30

LINVAL+1=320->LINVAL=319 HOZVAL+1=240->HOZVAL=239

HSF=VCLK÷[(HSPW+1)+(HSPD+1)+(HFPD+1)+(HOZVAL+1)]

VSF=HSF÷[(VSPW+1)+(VBPD+1)+(VFPD+1)+(LINEVAL+1)]

2. 显示缓存区

只要把所要显示的数据放入显示缓存区内,就可以在屏幕上呈现内容。该缓存区是我们自己编程时开辟的一段内存区。一般我们是通过定义一个与屏幕尺寸大小相同的二维数组来开辟该空间的,这样控制屏幕内容会方便一些,如当屏幕的尺寸为320×240时,可以定义该缓存区为LCD_BUFFER[240][320]。由于s3c2440支持16位和24位的非调色板真彩色的TFT型LCD模式,而24位颜色模式是用32位数据来表示的,所以前面定义的那个二维数据的数据类型应该是半字整型或全字整型的。例如,在24位颜色模式下,我们想要在尺寸大小为320×240屏幕的中心处设置为白色像素,则:LCD_BUFFER[120][160]=0xffffffff。

在s3c2440中,寄存器LCDSADDR1和LCDSADDR2用于设置显示缓存区,即把我们定义的那个二维数组告诉s3c2440。其中LCDBANK的9位数据指定LCD的BANK,即显示缓存区的第30位到第22位地址;LCDBASEU的21位数据指定了LCD的基址,即显示缓存区开始地址的第21位到第1位;LCDBASEL的21位数据指定了LCD的尾址,即显示缓存区结束地址的第21位到第1位。例如,我们想要在尺寸为320×240的屏幕上显示24位颜色,定义的显示缓存区数组为LCD_BUFFER[240][320],则LCDBANK等于LCD_BUFFER的第30位到第22位数据值(因为LCD_BUFFER表示的就是数组的首地址),LCDBASEU等于LCD_BUFFER的第21位到第1位数据值,由于是用32位数据表示24为颜色,因此每个像素值是4个字节,所以LCDBASEL等于(LCD_BUFFER+(240×320×4))结果的第21位到第1位的数据值。另外寄存器LCDSADDR3有两个内容:OFFSIZE和PAGEWIDTH。OFFSIZE用于虚拟屏幕的偏移长度,如果我们不使用虚拟屏幕,就把它置为0;PAGEWIDTH定义了视口的宽,单位是半字,如在上面的例子中,PAGEWIDTH应该为320×32÷16。

理论部分参考:

http://blog.csdn.net/jaylondon/article/details/6363741

主要对LCD初始化配置代码进行分析

#include<stdarg.h>

#include<stdio.h>

#include"inc/lcd320.h"

#include"inc/macro.h"

#include"inc/reg2410.h"

//对各个控制寄存器中的地址进行定义

#defineLCDCON1_CLKVAL (1<<8) //设置TFTLCD的VCLK时钟信号

#define LCDCON1_MMODE (0<<7) //是

#defineLCDCON1_PNRMODE (0x3<<5) //设置LCD类型,0x3表示TFTLCD

#defineLCDCON1_BPPMODE (0xc<<1) //设置像素模式 0xc对应16bpp

#defineLCDCON1_ENVID (1) //LCD信号输出使能位,0:禁止;1:使能



//显示尺寸640*480

#defineLCDCON3_HOZVAL 639

#defineLCDCON2_LINEVAL 479

/垂直同步信号的脉宽、后肩和前肩

#defineLCDCON2_VBPD 32 //32 //TFT LCD 信号的垂直信号

#defineLCDCON2_VFPD 9//9

#defineLCDCON2_VSPW 1//

//水平同步信号的脉宽、后肩和前肩

#defineLCDCON3_HBPD 47//49

#defineLCDCON3_HFPD 15//14

#defineLCDCON4_HSPW 95//95



#defineLCDCON5_FRM565 1//

#defineLCDCON5_INVVCLK 0 //像素值在VCLK下降沿有效

#defineLCDCON5_INVVLINE 1 //翻转HSYNC信号

#define LCDCON5_INVVFRAME 1 //翻转VSYNC信号

#defineLCDCON5_INVVD 0 //正常VD信号极性

#defineLCDCON5_INVVDEN 0 //正常VDEN信号极性

#defineLCDCON5_INVPWREN 0

#defineLCDCON5_INVLEND 0

#defineLCDCON5_PWREN 1 //使能PWREN信号

#defineLCDCON5_ENLEND 0

#defineLCDCON5_BSWP 0 //颜色数据字节不交换

#defineLCDCON5_HWSWP 1 //颜色数据半字交换

#defineBPP24BL 0 //32位数据表示24位颜色值时,低位数据有效,高8位无效

#defineTPALEN 1

#defineLPC_EN 1

#defineFIWSEL 0

#defineINT_FrSyn 1

#defineINT_FiCnt 1

#defineMVAL 13

U16*pLCDBuffer16I1=(U16*)0x32000000;

U16*pLCDBuffer16I2=(U16*)0x32096000;

U32LCDBufferII2[LCDHEIGHT][LCDWIDTH]; //定义显示缓存区

U16LCDBufferII1[307200];

voidLCD_Init() //初始化函数

{

U32 i; //unsignint i

U32 LCDBASEU,LCDBASEL,LCDBANK;

//配置LCD相关引脚

rGPCUP=0xffffffff; // Disable Pull-up register

rGPCCON=0xaaaaaaaa;

//InitializeVD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND

rGPDUP=0xffffffff; // DisablePull-up register

rGPDCON=0xaaaaaaaa; //InitializeVD[23:8]

rLCDCON1=0|LCDCON1_BPPMODE|LCDCON1_PNRMODE|LCDCON1_MMODE|LCDCON1_CLKVAL;

//等价于0|(0xc<<1)|(0x3<<5) |(0<<7) |(1<<8),ENVID关闭,TFT LCD像素模式设置为16bpp,选择TFT LCD类型,确定时钟

rLCDCON2=(LCDCON2_VBPD<<24)|(LCDCON2_LINEVAL<<14)|(LCDCON2_VFPD<<6)|LCDCON2_VSPW;

rLCDCON3=(LCDCON3_HBPD<<19)|(LCDCON3_HOZVAL<<8)|LCDCON3_HFPD;

rLCDCON4=LCDCON4_HSPW|(MVAL<<8);

rLCDCON5=(BPP24BL<<12)|(LCDCON5_FRM565<<11)|(LCDCON5_INVVCLK<<10)|(LCDCON5_INVVLINE<<9)|(LCDCON5_INVVFRAME<<8)|(LCDCON5_INVVD<<7)|\ (LCDCON5_INVVDEN<<6)|(LCDCON5_INVPWREN<<5)|(LCDCON5_INVLEND<<4)|(LCDCON5_PWREN<<3)|(LCDCON5_ENLEND<<2)|(LCDCON5_BSWP<<1)|LCDCON5_HWSWP;



LCDBANK=0x32000000>>22; //9位数据指定了LCD的[30:22]

LCDBASEU=0x0; //21位数据指向LCD的基址[21:1]

LCDBASEL=LCDBASEU+(480)*640; //初地址加上缓冲空间,即缓存区的空间大小

//rLCDADDR1=0x33000000>>1;

rLCDADDR1= (LCDBANK<<21)|LCDBASEU; //右移21位到[29:21] ,[20:0]不变为起始地址

rLCDADDR2=LCDBASEL; //缓冲区结束的地址

rLCDADDR3= (640)|(0<<11); //页面宽度加上偏移地址(0),640*32/16



rLCDINTMSK=(INT_FrSyn<<1)|INT_FiCnt; //|(FIWSEL<<2);

rLCDLPCSEL=0;

rTPAL=(0<<24);

for(i=0;i<640*480;i++)

//*(pLCDBuffer161+i)=0xffff;

*(pLCDBuffer16I1+i)=0x0;

//hudelay(5000);

rLCDCON1+=LCDCON1_ENVID;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: