电竞比分网-中国电竞赛事及体育赛事平台

分享

s3c2440的LCD應用

 cici5177 2010-10-28

人機交互是嵌入式系統(tǒng)必須具有的功能。比較簡單的人機交互有按鍵、LED、蜂鳴器,稍微復雜的有7段數(shù)碼管和點陣。但如今這些都不能滿足人們的需求了,所以又出現(xiàn)了LCD和觸摸屏技術。s3c2440具有LCD和觸摸屏接口,可以很好的連接LCD和觸摸屏。這篇文章主要介紹TFTLCD的用法。

 

       要想正確使用LCD,必須注意兩點:1、時序;2、顯示緩存區(qū)。

 

1、時序

LCD一般需要三個時序信號:VSYNC、HSYNCVCLK。VSYNC是垂直同步信號,在每進行一個幀(即一個屏)的掃描之前,該信號就有效一次,由該信號可以確定LCD的場頻,即每秒屏幕刷新的次數(shù)(單位Hz)。HSYNC是水平同步信號,在每進行一行的掃描之前,該信號就有效一次,由該信號可以確定LCD的行頻,即每秒屏幕從左到右掃描一行的次數(shù)(單位Hz)。VCLK是像素時鐘信號。

       s3c2440處理LCD的時鐘源是HCLK,通過寄存器LCDCON1中的CLKVAL可以調整VCLK頻率大小,它的公式為:

VCLKHCLK÷[(CLKVAL1)×2]

例如,HCLK的頻率為100MHz,要想驅動像素時鐘信號為6.4MHzLCD屏,則通過上式計算CLKVAL值,結果CLKVAL6.8,取整后(值為6)放入寄存器LCDCON1中相應的位置即可。由于CLKVAL進行了取整,因此我們把取整后的值代入上式,重新計算VCLK,得到VCLK7.1MHz。

按理說,對于一個已知尺寸(即水平顯示尺寸HOZVAL和垂直顯示尺寸LINEVAL已知)的LCD屏,只要確定了VCLK值,行頻和場頻就應該知道了。但這樣還不行的,因為在每一幀時鐘信號中,還會有一些與屏顯示無關的時鐘出現(xiàn),這就給確定行頻和場頻帶來了一定的復雜性。如在HSYNC信號先后會有水平同步信號前肩(HFPD)和水平同步信號后肩(HBPD)出現(xiàn),在VSYNC信號先后會有垂直同步信號前肩(VFPD)和垂直同步信號后肩(VBPD)出現(xiàn),在這些信號時序內,不會有有效像素信號出現(xiàn),另外HSYNCVSYNC信號有效時,其電平要保持一定的時間,它們分別叫做水平同步信號脈寬HSPW和垂直同步信號脈寬VSPW,這段時間也不能有像素信號。因此計算行頻和場頻時,一定要包括這些信號。HBPDHFPDHSPW的單位是一個VCLK的時間,而VSPW、VFPDVBPD的單位是掃描一行所用的時間。在s3c2440中,所有的這些信號(VSPW、VFPD、VBPD、LINEVALHBPD、HFPDHSPWHOZVAL)都是實際值減1的結果。這些值是通過寄存器LCDCON2LCDCON3LCDCON4來配置,只要把這些值配置成與所要驅動的LCD中相關內容的數(shù)據(jù)一致即可。例如,我們所要顯示的LCD屏大小為320×240,因此HOZVAL3201,LINEVAL2401。水平同步信號的脈寬、前肩和后肩分別為302038,則HSPW301,HFPD201,HBPD381;垂直同步信號的脈寬、前肩和后肩分別為3、1215,則VSPW31,VFPD121,VBPD151

下面我們就具體計算一下行頻(HSF)和場頻(VSF):

HSFVCLK÷[(HSPW1)(HSPD1)(HFPD1)(HOZVAL1)]

       7.1÷40817.5kHz

VSFHSF÷[(VSPW1)(VBPD1)(VFPD1)(LINEVAL1)]

       17.5÷27064.8Hz

在有些情況下,s3c2440LCD時鐘信號的默認極性與所控制的LCD時鐘信號的極性相反,這時可以通過寄存器LCDCON5的相關位來改變某些時鐘信號的極性。

 

2、顯示緩存區(qū)

       只要把所要顯示的數(shù)據(jù)放入顯示緩存區(qū)內,就可以在屏幕上呈現(xiàn)內容。該緩存區(qū)是我們自己編程時開辟的一段內存區(qū)。一般我們是通過定義一個與屏幕尺寸大小相同的二維數(shù)組來開辟該空間的,這樣控制屏幕內容會方便一些,如當屏幕的尺寸為320×240時,可以定義該緩存區(qū)為LCD_BUFFER[240][320]。由于s3c2440支持16位和24位的非調色板真彩色的TFTLCD模式,而24位顏色模式是用32位數(shù)據(jù)來表示的,所以前面定義的那個二維數(shù)據(jù)的數(shù)據(jù)類型應該是半字整型或全字整型的。例如,在24位顏色模式下,我們想要在尺寸大小為320×240屏幕的中心處設置為白色像素,則:LCD_BUFFER[120][160]0xffffffff。

       s3c2440中,寄存器LCDSADDR1LCDSADDR2用于設置顯示緩存區(qū),即把我們定義的那個二維數(shù)組告訴s3c2440。其中LCDBANK9位數(shù)據(jù)指定LCDBANK,即顯示緩存區(qū)的第30位到第22位地址;LCDBASEU21位數(shù)據(jù)指定了LCD的基址,即顯示緩存區(qū)開始地址的第21位到第1位;LCDBASEL21位數(shù)據(jù)指定了LCD的尾址,即顯示緩存區(qū)結束地址的第21位到第1位。例如,我們想要在尺寸為320×240的屏幕上顯示24位顏色,定義的顯示緩存區(qū)數(shù)組為LCD_BUFFER[240][320],則LCDBANK等于LCD_BUFFER的第30位到第22位數(shù)據(jù)值(因為LCD_BUFFER表示的就是數(shù)組的首地址),LCDBASEU等于LCD_BUFFER的第21位到第1位數(shù)據(jù)值,由于是用32位數(shù)據(jù)表示24為顏色,因此每個像素值是4個字節(jié),所以LCDBASEL等于(LCD_BUFFER(240×320×4))結果的第21位到第1位的數(shù)據(jù)值。另外寄存器LCDSADDR3有兩個內容:OFFSIZEPAGEWIDTH。OFFSIZE用于虛擬屏幕的偏移長度,如果我們不使用虛擬屏幕,就把它置為0PAGEWIDTH定義了視口的寬,單位是半字,如在上面的例子中,PAGEWIDTH應該為320×32÷16。

 

下面我們給出一段具體的TFTLCD顯示的實例,其中,屏幕的大小為320×240,所設置的顏色為24位真彩色模式。

 

#define U32 unsigned int

#define M5D(n)            ((n) & 0x1fffff)     //用于設置顯示緩存區(qū)時,取低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  (LCD_HEIGHT-1)

#define HOZVAL   (LCD_WIDTH-1)

 

//for LCDCON1

#define CLKVAL_TFT          6            //設置時鐘信號

#define MVAL_USED          0            //

#define PNRMODE_TFT      3            //TFTLCD

#define BPPMODE_TFT      13           //24TFTLCD

 

//for LCDCON5

#define BPP24BL          0     //32位數(shù)據(jù)表示24位顏色值時,低位數(shù)據(jù)有效,高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     //顏色數(shù)據(jù)字節(jié)不交換

#define HWSWP           0     //顏色數(shù)據(jù)半字不交換

//定義顯示緩存區(qū)

volatile U32 LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];

 

//延時程序

void delay(int a)

{

       int k;

       for(k=0;k<a;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); //設置GPG4LCD_PWREN

       rGPGDAT = rGPGDAT | (1<<4) ;               //GPG41

  

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

}

}

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多