S3C2440的LCD編程
4. 幀緩沖(FrameBuffer):
幀緩沖是Linux為顯示設(shè)備提供的一個(gè)接口,它把一些顯示設(shè)備描述成一個(gè)緩沖區(qū),允許應(yīng)用程序通過 FrameBuffer定義好的接口訪問這些圖形設(shè)備,從而不用去關(guān)心具體的硬件細(xì)節(jié)。對于幀緩沖設(shè)備而言,只要在顯示緩沖區(qū)與顯示點(diǎn)對應(yīng)的區(qū)域?qū)懭腩伾?值,對應(yīng)的顏色就會自動的在屏幕上顯示。下面來看一下在不同色位模式下緩沖區(qū)與顯示點(diǎn)的對應(yīng)關(guān)系:本文引用地址:http://www.ex-cimer.com/article/201611/322380.htm
volatile static unsigned short LCD_BUFFER[240][320];
void Pixel(U32 x,U32 y, U16 c )
{
if ( (x < SCR_XSIZE_TFT_320240) && (y < SCR_YSIZE_TFT_320240) )
LCD_BUFFER[y][x] = c;
}
很容易發(fā)現(xiàn)TFT LCD上顯示單個(gè)像素的函數(shù)實(shí)際上很簡潔,看來似乎只需要LCD_BUFFER[(y)][(x)] = c這一句話.下面就來分析下,是如何通過這一句話來實(shí)現(xiàn)在LCD上顯示單個(gè)像素的,先分析下Lcd_Init()即LCD初始化函數(shù):
#define rGPCCON
#define rGPCUP
#define rGPDCON
#define rGPDUP
#define rLCDCON1
#define rLCDCON2
#define rLCDCON3
#define rLCDCON4
#define rLCDCON5
#define rLCDSADDR1
#define rLCDSADDR2
#define rLCDSADDR3
#define rLCDINTMSK
#define rTPAL
void Lcd_Init(void)
{
}
程序分析至此,大概已經(jīng)清楚是如何通過LCD_BUFFER[(y)][(x)] = c來實(shí)現(xiàn)在LCD上顯示單個(gè)像素了。就是在設(shè)置好各個(gè)LCD寄存器之后,通過將LCD_BUFFER地址與LCDBANK以及LCDBASEU、 LCDBASEL對應(yīng)之后,通過改變LCD_BUFFER里不同單元存儲的值(即像素的顏色),即可在LCD相應(yīng)位置上做出顯示。
那么在應(yīng)用不同LCD的時(shí)候,只需對LCDCONx以及LCDSADDRx做出相應(yīng)的配置,再創(chuàng)建一個(gè)數(shù)組,做出上述的地址映射即可。
關(guān)于VCLK計(jì)算,由于配置的是TFT,可用到公式VCLK = HCLK / [(CLKVAL+1) * 2] ( CLKVAL>=0 ),設(shè)置的Fclk為400MHz,Hclk為100MHz(Fclk:Hclk=1:4),CLKVAL = 4,因此VLCK = 10MHz。
筆記:
首先說一下我們平時(shí)所說的多少位的LCD,有24位的,有16位的指的是LCD數(shù)據(jù)的位數(shù),LCD的數(shù)據(jù)實(shí)際上是LCD要顯示的顏色,24位的是紅綠 藍(lán)各占8位,16位則是紅綠藍(lán)按照565分配的,其實(shí)24的也可以只接16位,每個(gè)顏色地位接地就可以,所以要給LCD的緩沖區(qū)一個(gè)數(shù)據(jù)才能在LCD上顯 示出來。那究竟是怎么顯示的呢,那就得先說一下像素了,LCD的像素實(shí)際上就LCD屏幕有多少個(gè)點(diǎn),LCD顯示的東西都是一個(gè)一個(gè)點(diǎn)拼湊出來的,比如我用 的是320*240的LCD,就是說LCD每一行有320個(gè)點(diǎn),而每一列有240個(gè)點(diǎn),所以總共有320*240個(gè)點(diǎn),我們讓適當(dāng)?shù)狞c(diǎn)顯示適當(dāng)?shù)念伾瓦_(dá) 到了我們的目的。
其實(shí)剛開始困擾我們的是LCD的初始化的問題,要設(shè)置的東西比較多,其實(shí)我們是記不住這些東西的,呵呵,作為入門我們可以參考別人的初始化程序,把里面的參數(shù)改成我們自己的LCD的參數(shù)就OK了。
那么我們到底是怎么把我們要顯示的數(shù)據(jù)送給LCD控制起的呢?是這樣的,我們可以定義一個(gè)二維數(shù)組,把我們要顯示的數(shù)據(jù)存到里面,然后把這個(gè)數(shù)組的地 址賦給LCD的相應(yīng)的寄存器,這個(gè)寄存器是LCDSADDRn,具體的設(shè)置大家可以參考數(shù)據(jù)手冊,我們可以把二維數(shù)組的坐標(biāo)和LCD的坐標(biāo)對應(yīng)起來,那么 我們就可以隨意的讓哪一個(gè)像素點(diǎn)顯示什么顏色就顯示什么顏色了。這就把數(shù)據(jù)送出的過程,也就是顯示一個(gè)像素點(diǎn)的過程。
到現(xiàn)在我們已經(jīng)知道如何顯示一個(gè)像素了,那接下來就是LCD顯示最基本的東西了----字符和圖片。漢字和圖片的顯示都是基于像素點(diǎn)的顯示的,我們把 要顯示的字符和圖片轉(zhuǎn)化成相應(yīng)的數(shù)據(jù),然后傳遞給LCD即可。我們可以專門的寫一個(gè)顯示字符的函數(shù)和一個(gè)顯示圖片的函數(shù)。顯示字符的數(shù)據(jù)可以用取模軟件生 成,因?yàn)樯傻淖址麛?shù)據(jù)是表示的每一個(gè)點(diǎn)要不要亮,亮的地方用1表示,不亮的地方用0表示,所以如果用LCD顯示,我們還要告訴LCD顯示什么顏色,這才 是LCD需要的數(shù)據(jù),比如說16*16的數(shù)據(jù),有16行16列,我們將一行的數(shù)據(jù),也就是16位數(shù)據(jù)的每一位都取出來,為1的地方,我們就給LCD一個(gè) 16位的數(shù)據(jù),為0的地方就不給數(shù)據(jù),這樣就能顯示了,取模生成的數(shù)據(jù)都是按行來的。圖片的顯示直接就將16位的數(shù)據(jù)傳遞給LCD,這個(gè)圖片數(shù)據(jù)的產(chǎn)生, 我們可以用軟件LCD彩色圖片轉(zhuǎn)換工具(BMP_to_H)生成C語言文件,我們只需對文件進(jìn)行簡單的修改就能加入到我們的程序中,修改方法在軟件的說明 中都有。
編程要點(diǎn):
1、打開LCD背光
將LCD背光對應(yīng)的GPIO設(shè)置為禁止上拉(GPxUP相應(yīng)位寫入1),選擇output類型(GPxCON相應(yīng)位寫入01),輸出為高電平(GPxDAT相應(yīng)位寫入1)。
2、打開LCD電源
可以將GPG4選擇為LCD_PWREN(GPGCON:9-8寫入11),這時(shí)候LCD電源的打開/關(guān)閉可以通過LCDCON5:3來控制。也可以自定 義其他GPIO用作LCD電源開關(guān),只需將此GPIO設(shè)置為禁止上拉(GPxUP相應(yīng)位寫入1),選擇output類型(GPxCON相應(yīng)位寫入01), 輸出為高電平(GPxDAT相應(yīng)位寫入1)打開LCD電源。
3、設(shè)置其他信號線
其他信號線包括VD0-VD23和VFRAME、VLINE、VCLK等,分別在GPCCON,GPDCON中選擇相應(yīng)功能。
4、設(shè)置LCD的頻率(VCLK)
LCD的Datasheet上一般會寫有一個(gè)推薦的頻率,比如我使用的屏幕推薦頻率為6.4M,我需要通過一些計(jì)算選擇一個(gè)合適的CLKVAL以產(chǎn)生這個(gè)頻率:
對于TFT LCD,S3C2440提供的VCLK的計(jì)算公式為:VCLK = HCLK / ((CLKVAL+1)*2)
可以得出:CLKVAL = HCLK / (VCLK * 2) - 1
我 的HCLK是100Mhz(CPU運(yùn)行在400Mhz, CLKDIV_VAL設(shè)置為5,F(xiàn)clk:Hclk:Pclk = 1:4:8),VCLK使用屏幕推薦的6.4M,得到:CLKVAL = 100000000 / (6400000 * 2) - 1 = 6.8
選擇最接近的整數(shù)值7,寫入LCDCON1:17-8。
(VCLK其實(shí)就是根據(jù) 每秒幀數(shù)*幀行數(shù)*行像素 計(jì)算出來的,幀行數(shù)和行像素需要包含空白數(shù)和同步數(shù))
5、設(shè)置其他相關(guān)參數(shù)
LCD相關(guān)的參數(shù)主要還有這幾個(gè):LINEVAL: LCD水平像素-1,如320-1 = 319HOZVAL: LCD垂直像素-1,如240-1 = 239HFPD: 行開始前的VCLK時(shí)鐘數(shù)(LCD屏幕的Datasheet一般有推薦值)HBPD: 行結(jié)束后的VCLK時(shí)鐘數(shù)(LCD屏幕的Datasheet一般有推薦值)HSPW: 行之間水平同步的無效VCLK時(shí)鐘數(shù)(LCD屏幕的Datasheet一般有推薦值)VFPD: 幀數(shù)據(jù)開始前的空白行數(shù)(LCD屏幕的Datasheet一般有推薦值)VBPD: 幀數(shù)據(jù)結(jié)束后的空白行數(shù)(LCD屏幕的Datasheet一般有推薦值)VSPW: 幀之間垂直同步的無效行數(shù)(LCD屏幕的Datasheet一般有推薦值)
(相關(guān)寄存器LCDCON2, LCDCON3, LCDCON4)
6、設(shè)置視頻緩沖區(qū)的地址
2440支持虛擬屏幕,可以通過改變LCD寄存器實(shí)現(xiàn)屏幕快速移動:
PAGEWIDTH:虛擬屏幕一行的字節(jié)數(shù),如果不使用虛擬屏幕,設(shè)置為實(shí)際屏幕的行字節(jié)數(shù),如16位寬320像素,設(shè)為320 * 2OFFSIZE:虛擬屏幕左側(cè)偏移的字節(jié)數(shù),如果不使用虛擬屏幕,設(shè)置為0
LCDBANK: 視頻幀緩沖區(qū)內(nèi)存地址30-22位LCDBASEU: 視頻幀緩沖區(qū)的開始地址21-1位LCDBASEL: 視頻幀緩沖區(qū)的結(jié)束地址21-1位
(相關(guān)寄存器LCDSADDR1,LCDSADDR2,LCDSADDR3)
7、確定信號的極性
2440的LCD控制器允許設(shè)置VCLK、VLINE、VFRAME等信號的極性(上升沿有效還是下降沿有效),需要對照LCD的Datasheet一一確認(rèn)。
(相關(guān)寄存器LCDCON5)
8、禁止LPC3600/LCC3600模式
如果不是使用三星LPC3600/LCC3600 LCD,必須禁止LPC3600/LCC3600模式(寫入0到TCONSEL)。
評論