当前位置: 首页 > 技术资料 > S3C2440开发板-LCD基础

S3C2440开发板-LCD基础

QooIC.com 新闻出处:电子市场 | 发布时间:2011/5/9 17:14:01

  首先了解TFT LCD的时序,每个VSYNC信号表示一帧数据的开始,每个HSYNC表示一行数据的开始,无论这些数据是否有效,每个VCLK表示正在传输一个像素的数据,无论它是否有效。VSPW称为垂直同步信号的脉宽,VBPD称为垂直同步信号的后肩,VFPD称为垂直同步信号的前肩。HSPW称为水平同步信号的脉宽,HBPD称为水平同步信号的后肩,HFPD称为水平同步信号的前肩。查看时序图,VSYNC信号有效时,表示一帧数据的开始,VSPW表示VSYNC信号的脉冲宽度为(VSPW+1)个HSYNC信号周期,即(VSYNC+1)行,这(VSPW+1)行的数据无效。VSYNC信号脉冲之后,还要经过(VBPD+1)个HSYNC信号周期,有效的行数据才出现。所以,在VSYNC信号之后,总共还要经过(VSPW+1+VBPD+1)个无效行,第一个有效的行才会出现。随后即发出(LINEVAL+1)行的有效数据,随后是(VFPD+1)个无效行。HSYNC的类似。不过是以VCLK信号周期为单位。然后主要就是配置5个LCD控制寄存器,3个帧缓冲区起始地址寄存器。注意HSYNC和VSYNC信号,CPU发出的是正脉冲,LCD需要的是负的,所以极性取反,INVVLINE和INVVFRAME置1。M5D宏是用来取低21位。有一些右移一位的操作,主要是进行字节和半字地址的转换。LCD中需要的半字地址,帧缓冲区最低位是A[1]。BSWP和HWSWP是字节和半字交换,主要是处理大小端问题,如果输出的汉字反了,置这个位为1。volatile U32 LCD_BUFFER[240][320];这个是设的帧缓冲区,即视口,是帧内存的一部分,这个程序中,帧内存和帧缓冲区一样大。帧内存在SDRAM中,相当于显存。只要向帧缓冲区中写入数据,LCD的DMA控制器会自动将数据从总线发到LCD驱动器。在VCLK的上升沿发送数据,在VCLK的下降沿,LCD驱动器接受数据。BPP24BL是设置LCD的显示模式为24BPP时,一个4字节中哪3个字节有效。PAGESIZE是帧缓冲区的水平宽度,OFFSET是一行剩下的长度。VD[23]"VD[0],是24根数据线,即RGB信号线。

  下面的程序将LCD涂成红色,然后画一个蓝色的矩形。

  #define rGPCCON    (*(volatile unsigned *)0x56000020)

  #define rGPCUP     (*(volatile unsigned *)0x56000028)

  #define rGPDCON    (*(volatile unsigned *)0x56000030)

  #define rGPDUP     (*(volatile unsigned *)0x56000038)

  #define rLCDCON1    (*(volatile unsigned *)0x4d000000)

  #define rLCDCON2    (*(volatile unsigned *)0x4d000004)

  #define rLCDCON3    (*(volatile unsigned *)0x4d000008)

  #define rLCDCON4    (*(volatile unsigned *)0x4d00000c)

  #define rLCDCON5    (*(volatile unsigned *)0x4d000010)

  #define rLCDSADDR1  (*(volatile unsigned *)0x4d000014)

  #define rLCDSADDR2  (*(volatile unsigned *)0x4d000018)

  #define rLCDSADDR3  (*(volatile unsigned *)0x4d00001c)

  #define rLCDINTMSK  (*(volatile unsigned *)0x4d00005c)

  #define rTPAL       (*(volatile unsigned *)0x4d000050)

  #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 rLCDINTMSK  (*(volatile unsigned *)0x4d00005c)

  #define rTPAL       (*(volatile unsigned *)0x4d000050)

  #define rTCONSEL     (*(volatile unsigned *)0x4d000060)   //LPC3600 Control --- edited by junon

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

  #define VSPW       15

  #define VBPD       3

  #define VFPD       5

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

  #define HSPW       8

  #define HBPD       58

  #define HFPD      15

  #define CLKVAL 10

  #define HOZVAL 319

  #define LINEVAL 239

  #define PWREN 1

  #define MMODE 0

  #define PNRMODE 3

  #define BPPMODE 13

  #define INVVCLK 0

  #define INVVD 0

  #define INVVDEN 0

  #define U32 unsigned int

  #define M5D(n) ((n) & 0x1fffff)

  #define PAGEWIDTH 320

  #define OFFSIZE 0

  #define LCD_XSIZE 320

  #define LCD_YSIZE 240

  #define SCR_XSIZE 320

  #define SCR_YSIZE 240

  #define INVVLINE  1

  #define INVVFRAME 1

  #define BPP24BL 0

  #define BSWP 0

  #define HWSWP 0

  volatile U32 LCD_BUFFER[240][320];

  void Init_LCD(){

  rLCDCON1=(CLKVAL<<8)|(MMODE<<7)|(PNRMODE<<5)|(BPPMODE<<1)|0;   //设置CLKVAL,VCLK=HCLK/[(CLKVAL+1)*2],决定VM的触发方式,选择显示模式和BPP模式,暂时不要开启LCD,因为还没有设置好

  rLCDCON2=(VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW);    //rLCDCON2,rLCDCON3和rLCDCON4主要设置时序

  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);

  //INVVLINE和INVVFRAME需要进行翻转,因为CPU发出的是正脉冲,LCD使用的是负脉冲,所以要改变极性,PWREN使能电源信号

  rLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|M5D((U32)LCD_BUFFER>>1);

  rLCDSADDR2=M5D(((U32)LCD_BUFFER+(SCR_XSIZE*SCR_YSIZE*4))>>1 );

  rLCDSADDR3=PAGEWIDTH*32/16;

  rLCDINTMSK|=(3);

  rTCONSEL = 0;

  rGPCUP = 0x0;

  rGPDCON = 0xaaaaaaaa;

  rGPCCON = 0xaaaa02a9;

  rGPDUP = 0x0;

  rGPGUP=rGPGUP&("(1<<4))|(1<<4);

  rGPGCON=rGPGCON&("(3<<8))|(3<<8);

  rLCDCON1 |= 1;   //使能数据输出和LCD控制信号

  }

  void Paint_background(U32 c){

  unsigned int i, j;

  for(j = 0; j < LCD_YSIZE; j++)

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

  LCD_BUFFER[j][ i] = c;

  }

  void Paint_rectangle(U32 c){

  int i, j;

  for(i = 100; i < 200; i++)

  for(j = 100; j < 200; j++)

  LCD_BUFFER[ i][j] = c;

  }

  int LcdMain(){

  Init_LCD();

  Paint_background(0xCD5C5C);

  Paint_rectangle(0x000080);

  while(1);

  }