文章目錄
1.LCD與OLED的區別
-
LCD背光源與OLED自發光
-
LCD無機材料,LCD壽命較長。OLED廣視角、幾乎無窮高的對比度、可以彎曲、較低耗電優點。
2.LCD原理
- 屏幕上的每一個點稱爲像素
- 每個像素點由RGB三原色組成
2.1 顏色如何確定?
- 由RGB三組信號線組成
- 由下原理圖可知:R5條、G6條,B5條,即
RGB565
(彩色模式, 一個像素佔兩個字節) - 因此其每個像素佔用多少位(BBP:bit per piexl)爲2個字節
2.2 LCD如何“行掃描”?
- 有一條CLK時鐘線與LCD相連,每發出一次CLK(高低電平),就移動一個像素。
2.3 如何跳到下一行進行“行掃描”?
- 有一條HSYNC(水平同步信號)信號線與LCD相連,每發出一次脈衝(高低電平),行掃描跳到下一行的起始位置。
2.4 如何進行下一個“場掃描”?
- 有一條VSYNC(垂直同步信號)信號線與LCD相連,每發出一次脈衝(高低電平),就跳到原點。
注意:RGB數據線上的數據從何而來?
內存裏面手動劃分一塊顯存(FrameBuffer),裏面存放了要顯示的數據,LCD控制器從裏面將數據讀出來,通過RGB三組線傳給LCD,再依次打到顯示屏上。
3.LCD時序
- 分辨率 = Hsync的個數 * 一行中的有效CLK
完整時序圖:
形象時序圖:
以上兩張圖可以解釋LCD控制時序中的
Hsync
與Vsync
的協同(可以理解 一幀是一個垂直同步信號、一行是一個水平同步信號)
- 1.首先一幀(Vsync)中有若干個行(Hsync),設爲y,Vsync發出幀脈衝寬度
Tvp
- 2.經過
Tvb
時間,纔可以發送一幀的數據,從第一行開始- 3.其次一行(Hsync)中有若干個時鐘信號(CLK),有效的設爲x,Hsync發出脈衝寬度
Thp
- 4.經過
Thb
時間,纔可以發送一行的數據- 5.直到發送到一行的最後一個像素,經過
Thf
時間,纔會有下一個水平同步信號(Hsync)- 6.直到發送到最後一行,經過
Tvf
時間,纔會有下一個垂直同步信號(Vsync)
由上可知幾個重要的信號引腳:Hsync
、Vsync
、CLK
、Dn
由上可知幾個重要的時間參數:Tvp
、Tvb
、Thp
、Thb
、Thf
、Tvf
4.LCD控制器
思路:
- 1.取數據:把
FrameBuffer
的地址、bpp
、分辨率
告訴LCD控制器 - 2.發數據:把時序告訴LCD控制器、並設置引腳的極性(本款是下降沿取數據,但是有的LCD是上升沿有效,因此需要設置極性)
4.1 像素數據格式
- 使用的像素數格式如下:16BPP
565數據格式引腳連接圖:
4.2 調色板
- 本應該用
FrameBuffer
中用16bit表示1像素,可以用8bit存放在FrameBuffer
來省空間 - 8bit存放的是調色板中顏色的索引(共256中16bit顏色)
那麼當使用像素深度爲8pp時候,像素深度和我們的帶寬不一致,我們的顏色要用16位表示,如果直接用上肯定不可能,那我們就可以選擇用調色板,調色板中存放了256種16bpp的顏色,這時候我們color存放的就不是真實的顏色值了,而是存放的是調色板中256種顏色的
索引
,成線性關係一一對應,這樣我們大大減輕了系統的負擔。用16bpp還是8bpp這得取決實際情況,16bpp肯定比8pp清晰,但同時帶來的負荷也更加重。
調色板工作示意圖
5.編程框架
面向對象編程
參數層:
- 1.抽象出(不同設備)共同的參數結構體
- 2.上層的設備結構體指針指向所需的參數結構體
驅動層
- 1.抽象不同平臺的LCD控制器結構體
- 2.上層的LCD控制器結構體指針指向所需的結構體
6. 結構體參數
6.1 引腳極性結構體
由上3.LCD時序可知幾個重要的信號引腳:Hsync
、Vsync
、CLK
、Dn
:Hsync
、Vsync
、CLK
、Dn
/* 引腳極性結構體
* NORMAL:正常極性
* INVERT:反轉極性
*/
typedef struct pins_polarity{
int vclk; /* normal:下降沿獲取數據 */
int rgb; /* normal:高電平表示1 */
int hsync; /* normal:高脈衝 */
int vsync; /* normal:高脈衝 */
}pins_polarity, *p_pins_polarity;
6.2 時序結構體
由上3.LCD時序可知幾個重要的時間參數:Tvp
、Tvb
、Thp
、Thb
、Thf
、Tvf
/* 時序結構體
* NORMAL:正常極性
* INVERT:反轉極性
*/
typedef struct time_sequence{
/* 垂直方向 */
int tvp; /* Vsync脈衝寬度 */
int tvb; /* 上邊黑框 Vertical Back porch */
int tvf; /* 下邊黑框 Vertical Front porch */
/* 水平方向 */
int thp; /* Hsync脈衝寬度 */
int thb; /* 左邊黑框 Horizontal Back porch*/
int tvf; /* 右邊黑框 Horizontal Front porch */
}time_sequence,*p_time_sequence;
6.3 LCD控制器結構體
包含初始化、使能、禁止函數
/* 抽象LCD控制器結構體
* 向上:接收不同的LCD參數
* 向下:使用這些參數設置對應的LCD Controller
*/
typedef struct lcd_controller{
void (*init)(p_lcd_params plcdparams); //初始化
void (*enable)(void); //使
void (*disable)(void); //禁止
}lcd_controller,*p_lcd_controller;
7.初始化LCD引腳
- 初始LCD專用引腳,配置其模式:
LCD Data
與LCD Control
/* 初始化LCD引腳 */
void jz2440_pin_init(void)
{
/* 初始化 背光引腳: GPB0 */
GPBCON &= ~0x03;
GPBCON |= 0x01; //輸出模式
/* 初始化LCD專用引腳 */
GPCCON = 0xAAAAAAAA;
GPDCON = 0xAAAAAAAA;
/* 電源引腳 LCD_PWRDN */
GPGCON |= (3<<8);
}
爲了方便GPC、GPD兩組,都設置爲LCD專用引腳爲 0xAAAAAAAA
- 由下圖S3C2440 LCD控制器時序可得,在設置寄存器時需要在時間參數上-1
8.LCD控制器初始化
8.1 LCDCON1
/* LCDCON1[17:8] : CLKVAL, vclk = HCLK/[(CLKVAL+1)*2]
* = 100M/[(CLKVAL+1)*2]
* CLKVAL = 100/vclk/2 - 1 , vclk
* [6:5]:0b11,TFT LCD
* [4:1]:bpp mode
* [0] :LCD video output and the logic enable(1)/disable(0)
*/
int clkval = (double)100/plcdparams->time_seq.vclk/2 - 1 + 0.5;
int bppmode = (plcdparams == 8) ? 0x0B :\ //8bpp
(plcdparams == 16) ? 0x0C :\ //16bpp
0x0D; //24bpp
LCDCON1 = (clkval << 8) | (3 << 5) | (bppmode << 1);
8.2 LCDCON2
/* 垂直
* [31:24] :VBPD = Tvb - 1
* [23:14] :LINEVAL = line - 1 行數值
* [13:6] :VFPD = Tvf - 1
* [5:0] :VSPW = Tvp -1
*/
LCDCON2 = ((plcdparams->time_seq.tvb -1) << 24) | \
((plcdparams->yres -1) << 14) | \
((plcdparams->time_seq.tvf -1) << 6 ) | \
((plcdparams->time_seq.tvp -1) << 0 );
8.3 LCDCON3
/* 水平
* [31:19] :HBPD = Thb - 1
* [18:8] :HOZVAL = 列 - 1 橫向像素點
* [7:0] :HFPD = Thf - 1
*/
LCDCON3 = ((plcdparams->time_seq.thb -1) << 19) | \
((plcdparams->xres -1) << 8) | \
((plcdparams->time_seq.thf -1) << 0 );
8.4 LCDCON4
/* [23:14] :HSPW = thp - 1 行脈衝寬度
*/
LCDCON4 = ((plcdparams->time_seq.thp -1) << 0 );
8.5 LCDCON5
/* 用來設置引腳極性, 設置16bpp數據格式, 設置內存中象素存放的格式
* [12] : BPP24BL,This bit determines the order of 24 bpp video memory.
* [11] : FRM565, 1-565
* [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
* [9] : HSYNC是否反轉
* [8] : VSYNC是否反轉
* [7] : INVVD, rgb是否反轉
* [6] : INVVDEN
* [5] : INVPWREN
* [4] : INVLEND
* [3] : PWREN, LCD_PWREN output signal enable/disable
* [2] : ENLEND
* [1] : BSWP
* [0] : HWSWP
*/
pixelformat = plcdparams->pins_pol.bpp == 24 ? (1<<12) : \//24bpp
plcdparams->pins_pol.bpp == 16 ? (1) : \ //16bpp
(1<<1);//8ppp
LCDCON5 = (plcdparams->pins_pol.vclk<<10) |\
(plcdparams->pins_pol.hsync<<9) |\
(plcdparams->pins_pol.vsync<<8) |\
(plcdparams->pins_pol.rgb<<7) |\
(plcdparams->pins_pol.de<<6) |\
(plcdparams->pins_pol.pwren<<5) |\
(1<<11) | pixelformat;
8.6 LCDSADDR
- 由下圖可知:是將fb_base的[30:1]直接寫入LCDSADDR1寄存器
起始地址
結束地址 = 起始地址 + x * y * bpp/8
即爲:起始地址+一幀所佔空間大小
9.構造LCD參數結構體
對於該款4.3寸LCD而言的參數設置
/* 該款4.3寸 LCD參數結構體 */
lcd_params lcd_4_3_params{
.name = "lcd4.3",
.pins_pol = {
vclk = NORMAL, /* normal:下降沿獲取數據 */
hsync = INVERT, /* normal:高脈衝 */
vsync = INVERT, /* normal:高脈衝 */
rgb = NORMAL, /* normal:高電平表示1 */
de = NORMAL, /* normal:高電平使能 data enable */
pwren = NORMAL, /* normal:高電平使能power enable */
},
.time_seq = {
/* 垂直方向 */
tvp = 10, /* Vsync脈衝寬度 */
tvb = 2, /* 上邊黑框 Vertical Back porch */
tvf = 2, /* 下邊黑框 Vertical Front porch */
/* 水平方向 */
thp = 41, /* Hsync脈衝寬度 */
thb = 2, /* 左邊黑框 Horizontal Back porch*/
thf = 2, /* 右邊黑框 Horizontal Front porch */
vlck = 9,/* MHz */
}.
.xres = 480,
.yres = 272,
.bpp = 16, /* 16bit */
.fb_base,
};