1、时序
LCD一般需求三个时序信号:VSYNC、HSYNC和VCLK。VSYNC是笔直同步信号,在每进行一个帧(即一个屏)的扫描之前,该信号就有用一次,由该信号能够确认LCD的场频,即每秒屏幕改写的次数(单位Hz)。HSYNC是水平同步信号,在每进行一行的扫描之前,该信号就有用一次,由该信号能够确认LCD的行频,即每秒屏幕从左到右扫描一行的次数(单位Hz)。VCLK是像素时钟信号。
s3c2440处理LCD的时钟源是HCLK,经过寄存器LCDCON1中的CLKVAL能够调整VCLK频率巨细,它的公式为:
VCLK=HCLK÷[(CLKVAL+1)×2]
例如,HCLK的频率为100MHz,要想驱动像素时钟信号为6.4MHz的LCD屏,则经过上式核算CLKVAL值,成果CLKVAL为6.8,取整后(值为6)放入寄存器LCDCON1中相应的方位即可。由于CLKVAL进行了取整,因而咱们把取整后的值代入上式,从头核算VCLK,得到VCLK=7.1MHz。
按理说,关于一个已知尺度(即水平显现尺度HOZVAL和笔直显现尺度LINEVAL已知)的LCD屏,只需确认了VCLK值,行频和场频就应该知道了。但这样还不可的,由于在每一帧时钟信号中,还会有一些与屏显现无关的时钟出现,这就给确认行频和场频带来了必定的复杂性。如在HSYNC信号先后会有水平同步信号前肩(HFPD)和水平同步信号后肩(HBPD)出现,在VSYNC信号先后会有笔直同步信号前肩(VFPD)和笔直同步信号后肩(VBPD)出现,在这些信号时序内,不会有有用像素信号出现,别的HSYNC和VSYNC信号有用时,其电平要坚持必定的时刻,它们别离叫做水平同步信号脉宽HSPW和笔直同步信号脉宽VSPW,这段时刻也不能有像素信号。因而核算行频和场频时,必定要包含这些信号。HBPD、HFPD和HSPW的单位是一个VCLK的时刻,而VSPW、VFPD和VBPD的单位是扫描一行所用的时刻。在s3c2440中,一切的这些信号(VSPW、VFPD、VBPD、LINEVAL、HBPD、HFPD、HSPW和HOZVAL)都是实践值减1的成果。这些值是经过寄存器LCDCON2、LCDCON3和LCDCON4来装备,只需把这些值装备成与所要驱动的LCD中相关内容的数据共同即可。例如,咱们所要显现的LCD屏巨细为320×240,因而HOZVAL=320-1,LINEVAL=240-1。水平同步信号的脉宽、前肩和后肩别离为30、20和38,则HSPW=30-1,HFPD=20-1,HBPD=38-1;笔直同步信号的脉宽、前肩和后肩别离为3、12和15,则VSPW=3-1,VFPD=12-1,VBPD=15-1。
下面咱们就详细核算一下行频(HSF)和场频(VSF):
HSF=VCLK÷[(HSPW+1)+(HSPD+1)+(HFPD+1)+(HOZVAL+1)]
=7.1÷408=17.5kHz
VSF=HSF÷[(VSPW+1)+(VBPD+1)+(VFPD+1)+(LINEVAL+1)]
=17.5÷270=64.8Hz
在有些情况下,s3c2440的LCD时钟信号的默许极性与所操控的LCD时钟信号的极性相反,这时能够经过寄存器LCDCON5的相关位来改动某些时钟信号的极性。
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。
下面咱们给出一段详细的TFT型LCD显现的实例,其间,屏幕的巨细为320×240,所设置的色彩为24位真彩色形式。
#define U32 unsigned int
#define M5D(n) ((n) & 0x1fffff) //用于设置显现缓存区时,取低21位地址
#define rGPCCON (*(volatile unsigned *)0x56000020) //Port C control
#define rGPCDAT (*(volatile unsigned *)0x56000024) //Port C data
#define rGPCUP (*(volatile unsigned *)0x56000028) //Pull-up control C
#define rGPDCON (*(volatile unsigned *)0x56000030) //Port D control
#define rGPDDAT (*(volatile unsigned *)0x56000034) //Port D data
#define rGPDUP (*(volatile unsigned *)0x56000038) //Pull-up control D
#define rGPGCON (*(volatile unsigned *)0x56000060) //Port G control
#define rGPGDAT (*(volatile unsigned *)0x56000064) //Port G data
#define rGPGUP (*(volatile unsigned *)0x56000068) //Pull-up control G
#define rLCDCON1 (*(volatile unsigned *)0x4d000000) //LCD control 1
#define rLCDCON2 (*(volatile unsigned *)0x4d000004) //LCD control 2
#define rLCDCON3 (*(volatile unsigned *)0x4d000008) //LCD control 3
#define rLCDCON4 (*(volatile unsigned *)0x4d00000c) //LCD control 4
#define rLCDCON5 (*(volatile unsigned *)0x4d000010) //LCD control 5
#define rLCDSADDR1 (*(volatile unsigned *)0x4d000014) //STN/TFT Frame buffer start address 1
#define rLCDSADDR2 (*(volatile unsigned *)0x4d000018) //STN/TFT Frame buffer start address 2
#define rLCDSADDR3 (*(volatile unsigned *)0x4d00001c) //STN/TFT Virtual screen address set
#define rLCDINTMSK (*(volatile unsigned *)0x4d00005c) //LCD Interrupt mask
#define rTCONSEL (*(volatile unsigned *)0x4d000060) //LPC3600 Control — edited by junon
#define LCD_WIDTH 320 //屏幕的宽
#define LCD_HEIGHT 240 //屏幕的高
//笔直同步信号的脉宽、后肩和前肩
#define VSPW (3-1)
#define VBPD (15-1)
#define VFPD (12-1)
//水平同步信号的脉宽、后肩和前肩
#define HSPW (30-1)
#define HBPD (38-1)
#define HFPD (20-1)
//显现尺度
#define LINeval_r(LCD_HEIGHT-1)
#define HOZVAL (LCD_WIDTH-1)
//for LCDCON1
#define CLKVAL_TFT 6 //设置时钟信号
#define MVAL_USED 0 //
#define PNRMODE_TFT 3 //TFT型LCD
#define BPPMODE_TFT 13 //24位TFT型LCD
//for LCDCON5
#define BPP24BL 0 //32位数据表明24位色彩值时,低位数据有用,高8位无效
#define INVVCLK 0 //像素值在VCLK下降沿有用
#define INVVLINE 1 //翻转HSYNC信号
#define INVVFRAME 1 //翻转VSYNC信号
#define INVVD 0 //正常VD信号极性
#define INVVDEN 0 //正常VDEN信号极性
#define PWREN 1 //使能PWREN信号
#define BSWP 0 //色彩数据字节不交流
#define HWSWP 0 //色彩数据半字不交流
//界说显现缓存区
volatile U32 LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];
//延时程序
void delay(int a)
{
int k;
for(k=0;k
;
}
//制作屏幕布景色彩,色彩为c
void Brush_Background( U32 c)
{
int x,y ;
for( y = 0 ; y < LCD_HEIGHT ; y++ )
{
for( x = 0 ; x < LCD_WIDTH ; x++ )
{
LCD_BUFFER[y][x] = c ;
}
}
}
//画实心圆,色彩为c。圆心在屏幕中心,半径为80个像素
void Draw_Circular(U32 c)
{
int x,y ;
int tempX,tempY;
int radius = 80;
int SquareOfR = radius*radius;
for( y = 0 ; y < LCD_HEIGHT ; y++ )
{
for( x = 0 ; x < LCD_WIDTH ; x++ )
{
if(y<=120 && x<=160)
{
tempY=120-y;
tempX=160-x;
}
else if(y<=120&& x>=160)
{
tempY=120-y;
tempX=x-160;
}
else if(y>=120&& x<=160)
{
tempY=y-120;
tempX=160-x;
}
else
{
tempY = y-120;
tempX = x-160;
}
if ((tempY*tempY+tempX*tempX)<=SquareOfR)
LCD_BUFFER[y][x] = c ;
}
}
}
void Main(void)
{
//装备LCD相关引脚
rGPCUP = 0x00000000;
rGPCCON = 0xaaaa02a9;
rGPDUP = 0x00000000;
rGPDCON=0xaaaaaaaa;
rLCDCON1=(CLKVAL_TFT<<8)|(MVAL_USED<<7)|(PNRMODE_TFT<<5)|(BPPMODE_TFT<<1)|0;
rLCDCON2=(VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW);
rLCDCON3=(HBPD<<19)|(HOZVAL<<8)|(HFPD);
rLCDCON4=(HSPW);
rLCDCON5 = (BPP24BL<<12) | (INVVCLK<<10) | (INVVLINE<<9) | (INVVFRAME<<8) | (0<<7) | (INVVDEN<<6) | (PWREN<<3) |(BSWP<<1) | (HWSWP);
rLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|M5D((U32)LCD_BUFFER>>1);
rLCDSADDR2=M5D( ((U32)LCD_BUFFER+(LCD_WIDTH*LCD_HEIGHT*4))>>1 );
rLCDSADDR3=LCD_WIDTH*32/16;
rLCDINTMSK|=(3); // 屏蔽LCD中止
rTCONSEL = 0; //无效LPC3480
rGPGUP=rGPGUP&(~(1<<4))|(1<<4); //GPG4上拉电阻无效
rGPGCON=rGPGCON&(~(3<<8))|(3<<8); //设置GPG4为LCD_PWREN
rGPGDAT = rGPGDAT | (1<<4) ; //GPG4置1
rLCDCON5=rLCDCON5&(~(1<<3))|(1<<3); //有用PWREN信号
rLCDCON5=rLCDCON5&(~(1<<5))|(0<<5); //PWREN信号极性不翻转
rLCDCON1|=1; //LCD敞开
while(1)
{
//黑色布景,白色实心圆
Brush_Background(0x0);
Draw_Circular(0xffffff);
delay(5000000);
//白色布景,黑色实心圆
Brush_Background(0xffffff);
Draw_Circular(0x0);
delay(5000000);
//蓝色布景,黄色实心圆
Brush_Background(0xff);
Draw_Circular(0xffff00);
delay(5000000);
//绿色布景,品色实心圆
Brush_Background(0xff00);
Draw_Circular(0xff00ff);
delay(5000000);
//赤色布景,青色实心圆
Brush_Background(0xff0000);
Draw_Circular(0xffff);
delay(5000000);
//青色布景,赤色实心圆
Brush_Background(0xffff);
Draw_Circular(0xff0000);
delay(5000000);
//品色布景,绿色实心圆
Brush_Background(0xff00ff);
Draw_Circular(0xff00);
delay(5000000);
//黄色布景,蓝色实心圆
Brush_Background(0xffff00);
Draw_Circular(0xff);
delay(5000000);
}
}
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/259947.html