天天看點

基于ARM裸機的知識點總結(14)------- LCD顯示器一,LCD簡介二,LCD顯示的主要相關概念三,顔色在計算機中的表示四,LCD如何顯示圖像五, S5PV210的LCD控制器六,LCD控制器初始化

目錄

  • 一,LCD簡介
  • 二,LCD顯示的主要相關概念
  • 三,顔色在計算機中的表示
  • 四,LCD如何顯示圖像
    • LCD的接口技術
    • LCD的六個主要時序參數
  • 五, S5PV210的LCD控制器
  • 六,LCD控制器初始化

一,LCD簡介

1.什麼是LCD?

(1)LCD(Liquid Crystal Display)俗稱液晶.

(2)液晶是一種材料,液晶這種材料具有一種特點:可以在電信号的驅動下液晶分子進行旋轉,旋轉時會影響透光性,是以我們可以在整個液晶面闆後面用白光照(稱為背光),可以通過不同電信号讓液晶分子進行選擇性的透光,此時在液晶面闆前面看到的就是各種各樣不同的顔色,這就是LCD顯示。白光其實是由各種不同顔色的光組成的,是以白光被選擇性透光之後可以産生各種不同顔色的光。

(3)被動發光和主動發光。有些顯示器(譬如LED顯示器、CRT顯示器)自己本身會發光稱為主動發光,有些(LCD)本身不會發光隻會透光,需要背光的協助才能看起來是發光的,稱為被動發光。

(4)液晶應用領域:電視機、電腦顯示屏、手機顯示屏、工業顯示屏等····

2、其他主流顯示裝置(LED、CRT、等離子、OLED)

(1)CRT:陰極攝像管顯示器。

(2)等離子顯示:未成為主流

(3)OLED:目前未成為主流,但是很有市場潛力

(4)LED:主要用在戶外大螢幕

(5)LCD:目前是主流顯示器

3、LCD的發展史和種類(TN/STN/TFT)

(1)TN最早。壞處是響應性不夠好,有拖尾現象。

(2)STN是TN的更新版。有效解決拖尾現象,顯示更清晰。

(3)TFT的最大特點就是超薄。

二,LCD顯示的主要相關概念

1、像素(pixel)

(1)像素就是組成圖像的最基本元素,或者說顯示中可以被控制的最小機關,整個圖像就是由很多個像素組成的。

(2)像素可以被單獨控制,或控制其亮或不亮(單色屏)、或控制其亮度強弱(譬如亮50%,35%,這樣叫灰階屏,以前的黑白電視機)、或控制其顯示一定的顔色(這就是我們現在最常用的彩色顯示屏)。

總結:像素很重要,整個顯示圖像是由一個個的像素組成的。我們要在顯示器上顯示一個圖像,就是把這個圖像離散化成一個一個的點,然後把各個點的顔色對應在顯示器的像素上。

2、掃描

(1)掃描是一個動作而不是一個名字,掃描就是依次将顔色數值放入螢幕中所有的像素的這個過程。

(2)掃描這個詞是由最早的CRT顯示器遺留下來的,到LCD顯示器的年代本來已經失去意義了,但是我們還是延續着這麼叫。

(3)顯示器的掃描顯示原理依賴于人眼的視覺暫留。隻要顯示器掃描頻率大于人眼的發現頻率,人眼看到的圖像就是恒定的。如果掃描頻率偏小人眼就會看到閃動。(掃描頻率的概念就叫做重新整理率)

3、驅動器&控制器

(1)LCD驅動器一般和LCD顯示面闆內建在一起(本來是分開的,做面闆的是隻做面闆的,譬如說三星、LG、台灣的友達、奇美都是做面闆的;驅動器也由專門的IC廠商生産;內建廠商買來面闆和驅動器後內建在一起做成LCD螢幕),面闆隻負責裡面的液晶分子旋轉透光,面闆需要一定的模拟電信号來控制液晶分子;LCD驅動器晶片負責給面闆提供控制液晶分子的模拟電信号,驅動器的控制信号(數字信号)來自于自己的數字接口,這個接口就是LCD螢幕的外部接口。

(2)LCD控制器一般內建在SoC内部,他負責通過數字接口向遠端的LCD驅動器提供控制像素顯示的數字信号。LCD控制器的關鍵在于時序,它必須按照一定的時序和LCD驅動器通信;LCD控制器受SoC控制,SoC會從記憶體中拿像素資料給LCD控制器并最終傳給LCD驅動器。

4、顯示記憶體(簡稱:顯存)

(1)SoC在記憶體中挑選一段記憶體(一般來說是程式員随便挑選的,但是挑選的時候必須符合一定規矩),然後通過配置将LCD控制器和這一段記憶體(以後稱為顯存)連接配接起來構成一個映射關系。一旦這個關系建立之後,LCD控制器就會自動從顯存中讀取像素資料傳輸給LCD驅動器。這個顯示的過程不需要CPU的參與。

(2)顯示體系建立起來後,CPU就不用再管LCD控制器、驅動器、面闆這些東西了;以後CPU就隻關心顯存了,因為我隻要把要顯示的圖像的像素資料丢到顯存中,硬體就會自動響應(螢幕上就能自動看到顯示的圖像了)。

基于ARM裸機的知識點總結(14)------- LCD顯示器一,LCD簡介二,LCD顯示的主要相關概念三,顔色在計算機中的表示四,LCD如何顯示圖像五, S5PV210的LCD控制器六,LCD控制器初始化

總結:LCD顯示是分為2個階段的:第一個階段就是建立顯示體系的過程,目的就是CPU初始化LCD控制器使其和顯存聯系起來構成映射;第二個階段就是映射建立之後,此階段主要任務是将要顯示的圖像丢到顯存中去。

5、像素間距(pitch)

(1)pitch是連續2個像素的像素中心的距離。一般的像素是方形的,是以橫向pitch和縱向的pitch一樣的。但是也有不一樣的。

(2)像素間距會影響螢幕的最佳觀看距離。像素間距大的适合遠距離看,像素間距小的适合近距離看。

6、分辨率(resolution)

(1)整個螢幕的橫向和縱向的像素個數就叫分辨率,譬如X210開發闆用的螢幕是1026×400.

(2)螢幕尺寸和分辨率無關的,像開發闆的螢幕尺寸是7寸的(純螢幕對角線尺寸是7英寸)。

(3)螢幕尺寸和分辨率和像素間距三者之間有關聯。

7、清晰度

(1)清晰度是一個主觀概念,是人眼對顯示效果的一個主觀判斷。說白了就是人看起來感覺清晰不清晰。

(2)客觀來講,清晰度由分辨率和像素間距共同決定。一般的,螢幕尺寸固定時分辨率越高越清晰,分辨率越低就越不清晰;分辨率固定下,螢幕尺寸越小越清晰,越大越不清晰。

(3)清晰度還由其他很多因素共同決定。

8、像素深度(bits per pixel,簡稱bpp)

(1)一個像素在計算機中由多少個位元組資料來描述。

(2)計算機中用二進制位來表示一個像素的資料,用來表示一個像素的資料位越多,則這個像素的顔色值更加豐富、分的更細,顔色深度就更深。

(3)一般來說像素深度有這麼幾種:1位、8位、16位、24位、32位。

三,顔色在計算機中的表示

1、顔色的本質

(1)顔色是主觀存在,顔色其實是自然光在人的眼睛中和大腦中産生的一種映像。

(2)顔色的本質決定于光的波長。

2、自然光的顔色是連續的

(1)光的波長是連續的,導緻顔色也是連續的。理論上,隻要你的眼睛分辨能力足夠好,可以在自然界中發現無數中顔色。

3、計算機中的顔色是離散的

(1)計算機中不可能存儲無數種顔色,是以必須将顔色有限化,是以就用有限種顔色來代表自然界中的無限種顔色。這個理論非常類似于之前學過的AD轉換。

(2)這種離散化表達顔色的缺點是不夠真實,漏掉了很多種顔色。是以計算機中所能表達的顔色沒有自然界中豐富(計算機螢幕上顯示的圖像和真實圖像有差别)

(3)計算機所能表達的顔色種類個數,這個參數叫:像素深度bpp。

4、常見像素深度:1位、8位、16位、24位、32位

1位:用1個二進制位來表示顔色,這種就叫單色顯示。示例就是小飯店、理發店門口的LED屏。

8位:用8個二進制位來表示顔色,此時能表示256種顔色。這種叫灰階顯示。這時候是黑白的,沒有彩色,我們把純白到純黑分别對應255到0,中間的數值對應不同的灰。示例就是以前的黑白電視機。

16位:用16個二進制位表示顔色,此時能表示65536種顔色。這時候就可以彩色顯示了,一般是RGB565的顔色分布(用5位二進制表示紅色、用6位二進制表示綠色、用5位二進制表示藍色)。這種紅綠藍都有的顔色表示法就是一種模拟自然界中所有顔色的表示方式。但是因為RGB的顔色表達本身二進制位數不夠多(導緻紅綠藍三種顔色本身分的都不夠細緻),是以這樣顯示的彩色失真比較重,人眼能明顯看到顯示的不真實。

24位:用24個二進制位來表示顔色,此時能表示16777216種顔色。這種表示方式和16位色原理是一樣的,隻是RGB三種顔色各自的精度都更高了(RGB各8位),叫RGB888。此時顔色比RGB565更加真實細膩,雖然說比自然界無數種顔色還是少了很多,不過由于人眼的不理想性是以人眼幾乎不能區分1677萬種顔色和無數種顔色的差别了。于是乎就把這種RGB888的表示方法叫做真彩色。(RGB565就是假彩色)

32位:總共用32位二進制來表示顔色,其中24位表示紅綠藍三元色(還是RGB888分布),剩下8位表示透明度。這種顯色方式就叫ARGB(A是阿爾法,表示透明度),現在PC機中一般都用ARGB表示顔色。

補充:顔色的組成,三元色(三基色)是RGB,也就是說所有的顔色都可以由紅綠藍三種顔色組成。

四,LCD如何顯示圖像

LCD的接口技術

1、從電平角度來講本質上都是TTL信号

(1)什麼是TTL接口。+5V表示邏輯1,0V表示邏輯0.這種就叫TTL電平,和CMOS電平相對比。

(2)SoC的LCD控制器硬體接口是TTL電平的,LCD這邊硬體接口也是TTL電平的。是以他們倆本來是可以直接對接的,手機、平闆、開發闆都是這樣直接對接的(一般用軟排線連接配接)。

(3)TTL電平的缺陷就是不能傳遞太遠,如果LCD螢幕和主機闆控制器太遠(1米甚至更遠)就不能直接TTL連接配接了,要進行轉換。轉換方式:主機SoC(TTL) ->VGA-> LCD螢幕(TTL)

2、各種接口(TTL、LVDS、EDP、MIPI、)在傳輸速率、距離、适配性方面不同(參考資料:各種接口的差別)

3、RGB接口詳解(參考資料手冊時序圖)

(1)VD[23:0]:24根資料線,用來傳輸圖像資訊。可見LCD是并行接口,速率才夠快。

(2)HSYNC(水準同步信号)

(3)VSYNC(垂直同步信号):時序信号線,為了讓LCD能夠正常顯示給的控制信号

(4)VCLK(像素時鐘):LCD工作時需要主機闆控制器給LCD模組一個工作時鐘信号,就是VCLK。

(5)VDEN(資料有效标志):時序信号,和HSYNC、VSYNC結合使用。

(6)LEND(行結束标志,不是必須的):時序信号,非必須,譬如X210接口就沒有。

LCD的六個主要時序參數

1、LCD顯示機關:幀(frame)

(1)顯示器上一整個畫面的内容成為一個幀(frame),整個顯示器工作時是一幀一幀的在顯示。

(2)電影實際就是以每秒種24幀的速度在播放圖檔。

(3)幀内資料:一幀分為多行,一行分為多像素,是以一幀圖像其實就是多個像素組成的矩陣。

(4)幀外資料:整個視訊由很多個幀構成,最終播放視訊時逐個播放各個圖像幀即可。

2、LCD顯示一幀圖像的過程

(1)首先把幀分為行,然後再把行分為像素,然後逐個像素去顯示。(顯示像素:其實就是LCD驅動器按照接收到的LCD控制器給的顯示資料,驅動一個像素的液晶分子旋轉,讓這個像素顯示出相應的顔色值的過程)

(2)關鍵點:LCD控制器和驅動器之間一次隻能傳一個像素點的顯示資料。是以一幀圖像在螢幕上其實是串行的依次被顯示上去的,不是同一時間顯示出來的。

3、為了向前相容出現的六個時序參數

HSPW 水準同步信号脈寬

HBPD 水準同步信号前肩

HFPD 水準同步信号後肩

VSPW 垂直同步信号脈寬

VBPD 垂直同步信号前肩

VFPD 垂直同步信号後肩

基于ARM裸機的知識點總結(14)------- LCD顯示器一,LCD簡介二,LCD顯示的主要相關概念三,顔色在計算機中的表示四,LCD如何顯示圖像五, S5PV210的LCD控制器六,LCD控制器初始化

(1)一行的通信過程是這樣的:LCD控制器先發送一個HSYNC高電平脈沖(脈沖寬度是HSPW),脈沖告訴驅動器下面的資訊是一行資訊。然後開始這一行資訊,這一行資訊包括3部分:HBPD+有效行資訊+HFPD。其中前肩和後肩都屬于時序資訊(和LCD螢幕具體有關),有效行資訊就是橫向分辨率。是以你可以認為一行總共包含4部分:HSPW+HBPD+有效行資訊+HFPD。

(2)一幀圖像其實就是一列,一列圖像由多個行組成,每行都是上面講的這個時序。

(3)一幀圖像的通信過程是這樣的:整個幀圖像信号分為4部分:VSPW+VBPD+幀有效信号+VFPD。VSPW是幀同步信号寬度,用來告訴驅動器一幀圖像要開始了;VBPD和VFPD分别是垂直同步信号前後肩。

(4)必須說明:這6個參數對于LCD顯示器其實本來是沒用的,這些信号其實是老式的CRT顯示器才需要的,LCD本身不需要,但是出于曆史相容性要求,LCD選擇了相容CRT顯示器的這些時序要求,是以了解LCD顯示器時序和程式設計時,用CRT的方式來了解不會錯。

(5)要注意,這幾個時序參數本身是LCD螢幕本身的參數,與LCD控制器無關。是以同一個主機闆如果接的螢幕不一樣則時序參數設定也會不同。這些參數的來源一般是:第一,廠家會直接給出,一般以執行個體代碼的形式給出;第二,來自于LCD的資料手冊。

第一種方式,檢視九鼎的210裸機教程

代碼裡面的值          資料手冊推薦值
	.h_fp			= 210,		// 160-210-354         
	.h_bp			= 38,		// 46
	.h_sw			= 10,		// 1-40
	.v_fp			= 22,		// 7-22-147
	.v_fpe			= 1,
	.v_bp			= 18,		// 23
	.v_bpe			= 1,		
	.v_sw			= 7,		// 1-20
           

第二種方式,檢視LCD資料手冊。

補充:

1、注意這些數字的機關。H開頭的三個機關都是DCLK(像素時鐘),V開頭的三個機關是TH。這樣設定的好處是我們改變了像素時鐘的設定時,不用改變這裡的時序參數。

2、這些時序參數如果沒設定好會影響什麼?螢幕會跑偏。

五, S5PV210的LCD控制器

1、FIMD結構框圖

(1)210的LCD控制器叫FIMD,FIMD是210内部和圖像處理相關的一些部件,在攝像頭等和圖像處理有關的部分都可以有關聯。

(2)FIMD在内部與AHB總線等相連接配接,在外部提供RGB接口、I80接口、YUV接口與外部相連接配接,我們實際使用的是RGB接口。

2、虛拟螢幕疊加

(1)虛拟螢幕的意思是,我們平時看到的螢幕上顯示出來的場景實際是很多個螢幕顯示疊加在一起的效果(譬如新聞圖像、電視台台标、下方飄動的字幕新聞)

(2)像S5PV210的LCD控制器中有5個虛拟螢幕Window0到Window4,虛拟螢幕不存在于真實而存在于記憶體中。(之前講過,LCd顯示時實際是顯示的是對應的記憶體中的顯存區域的數值)虛拟螢幕其實就是一個記憶體中的顯存區域,有幾個顯存區域就有幾個虛拟螢幕,但是這些虛拟螢幕都被映射到一個真實的顯示屏上面,是以将來真實的現實效果實際是這幾個虛拟螢幕的顯示内容的疊加。(疊加時要注意上面一層會覆寫下面一層,是以要注意誰在前誰在後,設定寄存器時有這個選項)

(3)使用虛拟螢幕而不是整個LCD使用一個顯存是有一定好處的:第一,可以保證不污染源圖像,友善程式處理;第二,可以減少螢幕重新整理,提高顯示效率,減少CPU工作量。

基于ARM裸機的知識點總結(14)------- LCD顯示器一,LCD簡介二,LCD顯示的主要相關概念三,顔色在計算機中的表示四,LCD如何顯示圖像五, S5PV210的LCD控制器六,LCD控制器初始化

3、虛拟顯示

(1)如何實作在小分辨率的螢幕上(真實)顯示大分辨率的圖像

(2)細節上,我們需要螢幕上看到不同圖像時,需要對顯存區域進行重新整理。即使我們隻需要螢幕顯示移動一點點,整個螢幕對應的顯存空間也需要整個重新重新整理,工作量和完全重新顯示一幅圖像是一樣的。這個顯然不好,這樣CPU重新整理螢幕的工作量太大了,效率很低。

(3)如何能夠在顯示一個大圖檔的不同區域時讓CPU重新整理螢幕工作量減少?有,方法就是虛拟顯示。具體做法就是在記憶體中建立顯示緩存的時候實際建立一個很大的區域,然後讓LCD去對應其中的一部分區域作為有效的顯示區域。将來要顯示大圖像時,直接将大圖像全部一次性加載入顯示緩存區,然後通過移動有效顯示區域就可以顯示大圖像的不同區域了。

基于ARM裸機的知識點總結(14)------- LCD顯示器一,LCD簡介二,LCD顯示的主要相關概念三,顔色在計算機中的表示四,LCD如何顯示圖像五, S5PV210的LCD控制器六,LCD控制器初始化

六,LCD控制器初始化

#define GPF0CON			(*(volatile unsigned long *)0xE0200120)
#define GPF1CON			(*(volatile unsigned long *)0xE0200140)
#define GPF2CON			(*(volatile unsigned long *)0xE0200160)
#define GPF3CON			(*(volatile unsigned long *)0xE0200180)

#define GPD0CON			(*(volatile unsigned long *)0xE02000A0)
#define GPD0DAT			(*(volatile unsigned long *)0xE02000A4)

#define CLK_SRC1		(*(volatile unsigned long *)0xe0100204)
#define CLK_DIV1		(*(volatile unsigned long *)0xe0100304)
#define DISPLAY_CONTROL	(*(volatile unsigned long *)0xe0107008)

#define VIDCON0			(*(volatile unsigned long *)0xF8000000)
#define VIDCON1			(*(volatile unsigned long *)0xF8000004)
#define VIDTCON2		(*(volatile unsigned long *)0xF8000018)
#define WINCON0 		(*(volatile unsigned long *)0xF8000020)
#define WINCON2 		(*(volatile unsigned long *)0xF8000028)
#define SHADOWCON 		(*(volatile unsigned long *)0xF8000034)
#define VIDOSD0A 		(*(volatile unsigned long *)0xF8000040)
#define VIDOSD0B 		(*(volatile unsigned long *)0xF8000044)
#define VIDOSD0C 		(*(volatile unsigned long *)0xF8000048)

#define VIDW00ADD0B0 	(*(volatile unsigned long *)0xF80000A0)
#define VIDW00ADD1B0 	(*(volatile unsigned long *)0xF80000D0)

#define VIDTCON0 		(*(volatile unsigned long *)0xF8000010)
#define VIDTCON1 		(*(volatile unsigned long *)0xF8000014)

#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



// FB位址
#define FB_ADDR			(0x23000000)
#define ROW				(480)
#define COL				(800)
#define HOZVAL			(COL-1)
#define LINEVAL			(ROW-1)

#define XSIZE			COL
#define YSIZE			ROW


// 初始化LCD
void lcd_init(void)
{
	// 配置引腳用于LCD功能
	GPF0CON = 0x22222222;
	GPF1CON = 0x22222222;
	GPF2CON = 0x22222222;
	GPF3CON = 0x22222222;

	// 打開背光	GPD0_0(PWMTOUT0)
	GPD0CON &= ~(0xf<<0);
	GPD0CON |= (1<<0);			// output mode
	GPD0DAT &= ~(1<<0);			// output 0 to enable backlight

	// 10: RGB=FIMD I80=FIMD ITU=FIMD
	DISPLAY_CONTROL = 2<<0;

	// bit[26~28]:使用RGB接口
	// bit[18]:RGB 并行
	// bit[2]:選擇時鐘源為HCLK_DSYS=166MHz
	VIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );

	// bit[1]:使能lcd控制器
	// bit[0]:目前幀結束後使能lcd控制器
	VIDCON0 |= ( (1<<0)|(1<<1) );

	// bit[6]:選擇需要分頻
	// bit[6~13]:分頻系數為5,即VCLK = 166M/(4+1) = 33M
	VIDCON0 |= 4<<6 | 1<<4;


	// H43-HSD043I9W1.pdf(p13) 時序圖:VSYNC和HSYNC都是低脈沖
	// s5pv210晶片手冊(p1207) 時序圖:VSYNC和HSYNC都是高脈沖有效,是以需要反轉
	VIDCON1 |= 1<<5 | 1<<6;

	// 設定時序
	VIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;
	VIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;
	// 設定長寬(實體螢幕)
	VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

	// 設定window0
	// bit[0]:使能
	// bit[2~5]:24bpp(RGB888)
	WINCON0 |= 1<<0;
	WINCON0 &= ~(0xf << 2);
	WINCON0 |= (0xB<<2) | (1<<15);

#define LeftTopX     0
#define LeftTopY     0
#define RightBotX   799
#define RightBotY   479

	// 設定window0的上下左右
	// 設定的是顯存空間的大小
	VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);
	VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);
	VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);


	// 設定fb的位址
	VIDW00ADD0B0 = FB_ADDR;
	VIDW00ADD1B0 = (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);

	// 使能channel 0傳輸資料
	SHADOWCON = 0x1;
}