s5pv210 LCD編程原理


1:LCD基本工作原理

(1)  LCD(Liquid Crystal Display)液晶顯示,液晶特性:在電信號的驅動下液晶分子進行旋轉,旋轉會影響透光性,因此整個液晶面板

后面用白光(背光)來照射,通過不同的電信號讓液晶分子進行旋轉性透光,此時液晶面板就會看到顯示不同的顏色。液晶本身不發光,而是

位於后面的背光發的光。

(2)  白光是由多種顏色的光組合而成,光的實質是一種波,不同波長/頻率的波具有不同的顏色,人眼可見光波長在390~780NM,RGB色彩模式是工業界的一種顏色標准,

是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標准幾乎包括了人類視

力所能感知的所有顏色,是目前運用最廣的顏色系統之一。

(3)  210控制器可以采用RGB888顏色編碼模式,紅綠藍各8位,紅色綠色藍色又稱為三原色光,用英文表示就是R(red)、G(green)、B(blue)。在電腦中,RGB的所謂“多少”

就是指亮度,並使用整數來表示。通常情況下,RGB各有256級亮度,用數字表示為從0、1、2...直到255。共256級。計算機所能表達的顏色種類個數,這個參數叫:像素深度bpp。

 (4)   LCD顯示圖像原理:LCD屏幕是由一個個像素點組成的矩陣(如resolution 1024*768,橫向有1024個像素點,縱向有768個

像素點),每個像素點都可以被單獨控制亮或者不亮或者亮度強弱等,LCD圖像就是通過不同的顏色強度的像素點組合而成。我們可采用RGB888編碼來表示每個像素

點的顏色模式(強弱、顏色等等),一幀數據就表示在LCD矩陣的每個像素點對應的顏色模式。

(5)  SoC如何控制LCD顯示原理:

  LCD驅動器:LCD驅動器一般與LCD面板集成在一起,面板需要一定的模擬電信號來控制液晶分子,LCD驅動器芯片負責給面板提供控制液晶分子的模擬電

信號,驅動器的控制信號(數字信號)來自於LCD控制器的提供的接口。

  LCD控制器:LCD控制器集成在SoC內部,它負責通過數字接口向外部的LCD驅動器提供要顯示的像素數字信號。它必須按照一定的時序和LCD驅動器通信,LCD

控制器受SoC控制,SoC會從內存中拿出像素數據給LCD控制器並最終傳給LCD驅動器。

  顯存:SoC在內存中選一段內存,用來存放顏色數據,然后通過配置將LCD控制器和這一段內存連接起來,構成一個映射關系,一旦這個關系建立以后

,LCD控制器就會自動從顯存中讀取像素數據傳給LCD驅動器,LCD驅動器會自動的控制每個像素點的液晶分子,以形成最終的圖像,建立這個映射以后

就不需要SoC在來參與任何行為了。

  總結一下:SoC控制LCD液晶顯示的過程分為兩個部分:

    (1) SoC的LCD控制器引出一定的引腳與LCD驅動器連接,按照標准設置一定的時序;

    (2) 把LCD要顯示的像素信息放入內存中,在通過設置LCD控制器中的寄存器,與LCD控制器建立映射;

之后過程就是LCD控制器芯片與驅動器芯片自動完成的事情了,整個LCD圖像的顯示過程就是這樣。

 

(6)  LCD接口技術:從電平角度來講LCD都是TTL電平,TTL缺陷是容易受到外界影響,傳輸距離近,一般像手機平板等直接用軟排線

連接即可,而遠距離則需要轉換,轉換方式為:TTL--》VGA--》TTL。

(7)  補充

虛擬屏幕疊加:

(1)虛擬屏幕的意思是,我們平時看到的屏幕上顯示出來的場景實際是很多個屏幕顯示疊加在一起的效果(譬如新聞圖像、電視台台標、下方飄動的字幕新聞)
(2)像S5PV210的LCD控制器中有5個虛擬屏幕Window0到Window4,虛擬屏幕不存在於真實而存在於內存中。(之前講過,LCd顯示時實際是顯示的是對應的內存中的顯存區域的數值)

虛擬屏幕其實就是一個內存中的顯存區域,有幾個顯存區域就有幾個虛擬屏幕,但是這些虛擬屏幕都被映射到一個真實的顯示屏上面,所以將來真實的現實效果實際是這幾個虛擬屏幕的顯示內容的疊加。

(疊加時要注意上面一層會覆蓋下面一層,所以要注意誰在前誰在后,設置寄存器時有這個選項)
(3)使用虛擬屏幕而不是整個LCD使用一個顯存是有一定好處的:第一,可以保證不污染源圖像,方便程序處理;第二,可以減少屏幕刷新,提高顯示效率,減少CPU工作量。

虛擬顯示

(1)如何實現在小分辨率的屏幕上(真實)顯示大分辨率的圖像
(2)細節上,我們需要屏幕上看到不同圖像時,需要對顯存區域進行刷新。即使我們只需要屏幕顯示移動一點點,整個屏幕對應的顯存空間也需要整個重新刷新,工作量和完全重新顯示一幅圖像是一樣的。

這個顯然不好,這樣CPU刷新屏幕的工作量太大了,效率很低。
(3)如何能夠在顯示一個大圖片的不同區域時讓CPU刷新屏幕工作量減少?有,方法就是虛擬顯示。具體做法就是在內存中建立顯示緩存的時候實際建立一個很大的區域,然后讓LCD去對應其中的一部分

區域作為有效的顯示區域。將來要顯示大圖像時,直接將大圖像全部一次性加載入顯示緩存區,然后通過移動有效顯示區域就可以顯示大圖像的不同區域了。

 

2:S5PV210 LCD時序

看一下核心板原理圖:LCD接線為24條VD數據輸出線,用來傳輸RGB888 24位顏色數據,VCLK時鍾線,HSYNC:水平同步信號線;VSYNC:垂直同步信號線,VDEN:數據使能線;

 

HSPW+1:HSYNC線上不工作是為低電平,拉高HSPW+1時鍾,在拉低,表示要准備開始傳輸顏色數據;(這個時間可以理解為切換到下一行所消耗的時間)

HBPD+1:在經過HBPD+1時鍾,VDEN線拉高,表示VD線上之后的都是RGB顏色數據,所以只有當VDEN信號線為高電平是,才認為是發送的真實數據,

開始發送水平顏色信息以后就會連續發送,如1024*768分辨率LCD,會一直把水平的1024個像素點的顏色數據都發送完以后才會拉低VDEN。(這個時間理解為

准備傳輸水平數據所要消耗時間)

HOZVAL+1:1024-1不表示時鍾,而是表示水平像素個數-1

表示傳輸橫線顏色數據的總時鍾,如一個時鍾頻率傳輸1個bit位,每個顏色數據設置為32位,橫向共傳輸1024個b顏色數據,總的時鍾為1024*32;

HFPD+1:數據傳輸完以后首先把VDEN拉低HFPD+1時鍾,整個水平傳輸周期完成;(這個時間可以理解為,結束數據傳輸所消耗時間)

VSPW+1:同樣可以理解為切換整幀圖像數據所消耗時間;

VBPD+1:准備傳輸整幀數據消耗時間;

LINEVAL+1:768-1;

VFPD+1:結束傳輸整幀數據的同步時間;

      要注意,這幾個時序參數本身是LCD屏幕本身的參數,與LCD控制器無關。所以同一個主板如果接的屏幕不一樣則時序參數設置也會不同。

 3:相關寄存器

寄存器:DISPAY_CONTROL 設置為10或11;RGB模式可行即可;

 

VIDCON0:Video Main Control 0 Register

bit18-26選擇為RGB模式

bit18:設置RGB數據傳輸為並行還是串行,因為有24根數據線所以為並行;

bit2選擇時鍾源,選HCLK 連的是HCLC_DSYS 為166MHz

bit4:開啟分頻;

 

bit13-6設置時鍾大小,時鍾頻率要小於控制器的最大時鍾,也要小於LCD驅動器的最大時鍾。

 

bit0 bit1為使能控制信號都使能

VIDCON1寄存器 Video Main Control 1 Register

bit5 bit6設置HSYNC和VSYNC的極性,如果LCD的高低電平脈沖是相同的話,則Normal,如果極性相反則Invert。

VIDTCON0:設置時序,根據LCD數據手冊中的時序來設置

 

VIDTCON1

 

VIDTCON2

 

WINCON0寄存器

bit1:使能window0 

 

bit5-2選擇RGB888模式

bit15:設置輸出順序為 red green blue還是 blue green red  設置為1:BGR  設置為0:RGB

VIDOSD0A VIDOSD0B這兩個寄存器是用來設置內存中window0的大小;

比如設置為LCD屏幕的尺寸(即左上坐標為(0, 0) 右下坐標為(1023, 767))

VIDOSD0C也是設置內存中window0的大小

比如設置為LCD屏幕的尺寸=1024*768

VIDW0xADD0Bx設置內存中window0的起始地址的

VIDW0xADD1Bx設置內存中window0的結束地址的

 

 SHODOWCON寄存器來設置虛擬windows顯示的;

以下位可以分別設置哪個windows顯示;

補充:看核心板、地板原理圖相應引腳要設置為LCD的引腳模式,LCD背光要打開;

 

以下位詳細代碼:

 

#include "lyq.h"
#define     _ZLS_MODE_
#define RED             (0xFF0000)
#define GREEN            (0x00FF00)
#define BLUE            (0x0000FF)
#define WHITE            (0xFFFFFF)
    

//配置相關引腳
#define    GPF0CON            0xE0200120
#define    GPF1CON            0xE0200140
#define    GPF2CON            0xE0200160
#define    GPF3CON            0xE0200180
#define GPD0CON            0xE02000A0
#define GPD0DAT            0xE02000A4
#define DISPLAY_CONTROL        0xE0107008

//配置控制器
#define VIDCON0            0xF8000000
#define VIDTCON0        0xF8000010
#define VIDCON1            0xF8000004
#define VIDTCON1        0xF8000014
#define VIDTCON2        0xF8000018
#define WINCON0            0xF8000020
#define VIDOSD0A        0xF8000040
#define VIDOSD0B        0xF8000044
#define VIDOSD0C        0xF8000048
#define VIDW00ADD0B0    0xF80000A0
#define VIDW00ADD1B0    0xF80000D0
#define SHODOWCON        0xF8000034

#define    _RGB_GPF0CON    (*(unsigned int*)0xE0200120)
#define    _RGB_GPF1CON    (*(unsigned int*)0xE0200140)
#define    _RGB_GPF2CON    (*(unsigned int*)0xE0200160)
#define    _RGB_GPF3CON    (*(unsigned int*)0xE0200180)
#define    _RGB_GPD0CON    (*(unsigned int*)0xE02000A0)
#define    _RGB_GPD0DAT    (*(unsigned int*)0xE02000A4)
#define    _RGB_DISPLAY_CONTROL    (*(unsigned int*)0xE0107008)

//配置控制器
#define    _RGB_VIDCON0    (*(unsigned int*)0xF8000000)
#define    _RGB_VIDTCON0    (*(unsigned int*)0xF8000010)
#define    _RGB_VIDCON1    (*(unsigned int*)0xF8000004)
#define    _RGB_VIDTCON1    (*(unsigned int*)0xF8000014)
#define    _RGB_VIDTCON2    (*(unsigned int*)0xF8000018)
#define    _RGB_WINCON0    (*(unsigned int*)0xF8000020)
#define    _RGB_VIDOSD0A    (*(unsigned int*)0xF8000040)
#define    _RGB_VIDOSD0B    (*(unsigned int*)0xF8000044)
#define    _RGB_VIDOSD0C    (*(unsigned int*)0xF8000048)
#define    _RGB_VIDW00ADD0B0    (*(unsigned int*)0xF80000A0)
#define    _RGB_VIDW00ADD1B0    (*(unsigned int*)0xF80000D0)
#define    _RGB_SHODOWCON    (*(unsigned int*)0xF8000034)

#define FB_ADDR            (0x23000000)

//Horizontal Pulse Width        20
//Horizontal Back Porch            140
//Horizontal Front Porch           160    
//Horizontal effective Time        1024
    
//Vertical Pulse Width            3
//Vertical Back Porch            20
//Vertical Front Porch            12
//Vertical Valid                600

#ifdef                    _ZLS_MODE_
#define HSPW             (40)                // 1~40 DCLK
#define HBPD            (10 - 1)            // 46
#define HFPD             (240 - 1)            // 16 210 354
#define VSPW            (20)                // 1~20 DCLK
#define VBPD             (10 - 1)            // 23
#define VFPD             (30 - 1)            // 7 22 147
#else 
#define HSPW             (20)                // 1~40 DCLK
#define HBPD            (140)            // 46
#define HFPD             (160)            // 16 210 354
#define VSPW            (3)                // 1~20 DCLK
#define VBPD             (20)            // 23
#define VFPD             (12)            // 7 22 147
#endif

#define ROW                (600)
#define COL                (1024)
#define FB_ADDR            (0x23000000)
#define HOZVAL            (COL-1)
#define LINEVAL            (ROW-1)
#define LeftTopX        (0)
#define LeftTopY        (0)
#define RightBotX        (COL - 1)
#define RightBotY        (ROW - 1)
unsigned int *pfb = (unsigned int *)FB_ADDR;



void lcd_init(void)
{
    //設置相應引腳為LCD模式
    _RGB_GPF0CON = 0x22222222;
    _RGB_GPF1CON = 0x22222222;
    _RGB_GPF2CON = 0x22222222;
    _RGB_GPF3CON = 0x22222222;
    
    //設置背光開啟,輸出低電平
    _RGB_GPD0CON &= ~(0xF << 0);
    _RGB_GPD0CON |= (0x1 << 0);
    _RGB_GPD0DAT &= ~(0x1 << 0);
    
    //設置FIMD的輸出為RGB模式輸出
    _RGB_DISPLAY_CONTROL &= ~(3 << 0);
    _RGB_DISPLAY_CONTROL |= (2 << 0);
    
    
    //基本設置
    _RGB_VIDCON0 &= ~(0x3 << 26);                //設置為RGB模式
    _RGB_VIDCON0 &= ~(0x1 << 18);                //設置為RGB並行
    _RGB_VIDCON0 &= ~(0x1 << 2);                //設置時鍾源為HCLK_DSYS
    _RGB_VIDCON0 |= (1 << 4);                    //開啟分頻    
    _RGB_VIDCON0 &= ~(0xFF << 6);                //設置時鍾分頻為4 166/(4+1) = 33
    _RGB_VIDCON0 |=    (4 << 6);
    _RGB_VIDCON0 |= (3 << 0);                    //使能signal

    
    _RGB_VIDCON1 |= (3 << 5);                    //開啟HSYNC、VSYNC極性反轉
    
    //設置時序等
    _RGB_VIDTCON0 &= ~(0xFFFFFF << 0);
    _RGB_VIDTCON0 |= ((VSPW << 0) | (VFPD << 8) | (VBPD) << 16);
    
    _RGB_VIDTCON1 &= ~(0xFFFFFF << 0);
    _RGB_VIDTCON1 |= ((HSPW << 0) | (HFPD << 8) | (HBPD) << 16);
    
    _RGB_VIDTCON2 = ((HOZVAL << 0) | (LINEVAL << 11));
    
    //設置window0
    _RGB_WINCON0 |= (1 << 0);                    //使能window0
    _RGB_WINCON0 &= ~(0xF << 2);                //設置window0位RGB888模式
    _RGB_WINCON0 |= (0xB << 2);
    
    //設置window0在內存中的坐標
    _RGB_VIDOSD0A &= ~(0x3FFFFF << 0);
    _RGB_VIDOSD0A |= ((LeftTopX << 0) | (LeftTopX << 11));
    _RGB_VIDOSD0B &= ~(0x3FFFFF << 0);
    _RGB_VIDOSD0B |= ((RightBotY << 0) | (RightBotX << 11));
    _RGB_VIDOSD0C = (RightBotX + 1) * (RightBotY + 1);

    //設置顯存的起始地址
    _RGB_VIDW00ADD0B0 = (unsigned int)FB_ADDR;    
    
    //設置顯存結束地址
    //_RGB_VIDW00ADD1B0 = (((HOZVAL )*4 + 0) * (LINEVAL + 1)) & (0xffffff);
    _RGB_VIDW00ADD1B0 = _RGB_VIDW00ADD0B0 + (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1));
    
    //使能channel0
    _RGB_SHODOWCON = 1;
    
}



static void lcd_point_draw_func(unsigned int x, unsigned int y, unsigned int color)
{
    
    unsigned int mem_val, i;
    
    mem_val = (unsigned int)FB_ADDR + (COL*(y-1) + (x-1)) * sizeof(int);
    *(unsigned int *)mem_val = color;    
    
}

void clean_window(void)
{
    int i = 0;
    
    for (i=0; i<614400; i++) {
        *pfb = 0;
        pfb++;
        
    }
    
}

static void lcd_bckgrd_draw(unsigned int color)
{
    int i, j;
    
    for (j=0; j<ROW; j++) {
        for (i=0; i<COL; i++) {
            lcd_point_draw_func(i, j, color);
        }
    }
    
}

static void lcd_line_draw(unsigned int y, unsigned int color)
{
    int i = 0;
    for (i=0; i<1024; i++) {
        lcd_point_draw_func(i, (y-1), color);
    }    
}

void lcd_pic_draw(const unsigned char *pcolor)
{
    int i, j;
    int color;
    
    for (j=0; j<ROW; j++) {
        for (i=0; i<COL; i++) {
            color = ((*pcolor) << 0) | ((*(pcolor+1)) << 8) | ((*(pcolor+2)) << 16);
            lcd_point_draw_func(i, j, color);
            pcolor +=3; 
        }
}
}
// 在像素點(x, y)處填充為color顏色
/*
static inline void lcd_draw_pixel(unsigned int x, unsigned int y, unsigned int color)
{
    *(pfb + COL * y + x) = color;
}

// 把整個屏幕全部填充成一個顏色color
static void lcd_draw_background(unsigned int color)
{
    unsigned int i, j;
    
    for (j=0; j<ROW; j++)
    {
        for (i=0; i<COL; i++)
        {
            lcd_draw_pixel(i, j, color);
        }
    }
}


*/

void lcd_test(void)
{    
        lcd_init();
        //clean_window();
        //lcd_bckgrd_draw(RED);
        //delay();
        lcd_pic_draw(gImage_lyq);    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM