六、lcd的控制
LCD ( Liquid Crystal Display 的簡稱)液晶顯示器。LCD 的構造是在兩片平行的玻璃基板當中放置液晶盒,下基板玻璃上設置TFT(薄膜晶體管),上基板玻璃上設置彩色濾光片,通過TFT上的信號與電壓改變來控制液晶分子的轉動方向,從而達到控制每個像素點偏振光出射與否而達到顯示目的。現在LCD已經替代CRT成爲主流,價格也已經下降了很多,並已充分的普及。
s3c2440通過lcd來顯示圖像,在2440內部,存在lcd控制相關的寄存器,其結構圖如下:
其中,REABANK是一些寄存器組主要包含17個設置參數的寄存器和256x16的調色板內存,其每個寄存器的作用將在下文一一展開;LCDCDMA是供LCD專用的DMA通道,用於獲取總線上面的圖像數據;TIMEGEN和LPC3600用來產生LCD控制時序,VIDRCS,將DMA獲取來的數據以設定的格式傳送給LCD。LPC3600和LCC3600爲三星公司生產的lcd,假如不使用三星公司生產的lcd,需要禁止LPC3600和LCC3600。
數據手冊給出了兩種類型的lcd,一種是STN(Super Twisted Nematic)lcd,這裏不再介紹,一種是TFT LCD這裏只介紹TFT LCD。
在介紹LCD顯示之前,先介紹對於LCD顯示的幾個重要的名詞,首先看圖:
圖中,是現實整個一幅圖的概括圖,其中,深藍色的部分爲實際顯示出來的部分,其餘的部分是非顯示部分,但是非顯示部分對LCD來說也是必須的。如圖中的箭頭部分,LCD是按照由上到下,由左到右的順序顯示的。圖中HSYNC和VSYNC是跳轉信號,在每一行結束,下一行開始的時候,會產生一個HSYNC信號,在一幅圖(幀)顯示完畢,要顯示下一張圖的時候,會發出VSYNC信號。
這裏值得關注的是,除了深藍色的部分外,其周圍還有其他顏色的部分。也就是說當像素點掃描到每一行深藍色部分(能顯示給用戶的部分)最右邊的時候,還需要掃描幾個無用的像素點才能跳轉到下一行平且發出HSYNC信號(無用的點裏對應的右邊紫色的部分),此時,在發出HSYNC信號之後,仍需要掃描幾個無用的點(此時的無用點是指顯示不出來的點,所謂無用的點是指左邊紫色的部分)才能掃描出要顯示給用戶的點。
從縱向的來說。當像素掃描到要顯示圖像的最右端的時候,也就是圖中對應的A點,此時掃描點並不馬上調轉到左上角顯示下一幀,而是仍要不斷的掃描幾個無用的行再跳轉併發出VSYNC信號(此時對應的是圖中黃色的部分),在發出VSYNC信號後,仍需要掃面幾行無用的像素點(對應圖中的紅色部分)纔可以顯示要顯示的圖像。
所有的這些要掃描的像素點稱爲一幀,也就是掃描完圖中所有的像素點稱爲一幀(有用的沒用的點都要算),所以說VSYNC信號出現的頻率稱爲垂直頻率代表每秒中可以顯示的圖像數,簡單的話解釋就是每出現一個VSYNC就證明一張圖片顯示完畢。對應的HSYNC稱爲水平頻率。簡單的解釋就是每出現一次HSYNC信號就證明完成一行的掃描。
圖中深藍色部分,也就是有效數據的行數列數稱爲分辨率。
基本的名詞,及其lcd的基本的顯示原理已經介紹完畢,接下就來控制lcd來顯示想要顯示的東西,首要要控制就需要有時序圖,接下來來看lcd控制器的時序圖:
首先圖中可以看出,VSYNC的一個週期就是一幀的週期,VSYNC的高電平的時間(脈寬)爲VSPW+1個HSYNC信號週期;時序圖中的VBPD+1部分就是對應上面那個圖的上面紅色的部分;接下來就是有效顯示的行數一共有LINEVAL+1個有效的行數(對應上圖藍色部分的行數);在後面就是需要VFPD+1個HSYNC週期的時間後纔開始下一幀的顯示,這裏VFPD+1個HSYNC週期的時間就是對應圖中下面黃色的部分;總的來說,一幀(也就顯示一幅圖片的時間)就是(VSPW+1)+ (VBPD+1)+(LINEVAL+1)+(VFPD+1)個HSYNC週期。
然後時序圖中把一個HSYNC週期放大,圖中HSYNC高電平持續的時間(脈寬)爲HSPW+1個VCLK週期;接下來需要HBPD+1個VCLK個週期纔可以顯示有效數據,此時HBPD+1個VCLK個週期的時間就是對應上圖中左邊紫色的部分;接下來就開始顯示有效數據部分,一共需要HOZVAL+1個VCLK週期(這裏對應的是上圖的藍色部分的列數);再往後就是需要HFPD+1個VCLK週期的時間纔可以繼續顯示下一行,HFPD+1個VCLK週期的時間就是對應圖中右邊紫色的部分。這裏掃描一行所需要的時間就是(HSPW+1)+(HBPD+1)+(HOZVAL+1)+(HFPD+1)個VCLK週期。
爲了具體的確定VSPW VBPD LINEVAL VFPD HSPW HBPD HOZVAL HFPD的具體數值,就要根據LCD的芯片手冊來對比得出結果。來對比一下LCD芯片的數據手冊,圖中單位有兩種,其中的H代表HSYNC,其中的CLK爲像素的時鐘週期。
對比上面的圖可以得知VSPW=9 VBPD=1 LINEVAL=271 VFPD=1 HSPW=40 HBPD=1 HOZVAL=479 HFPD=1
通過上面兩段的分析,可以看出:
一幀週期(也就顯示一幅圖片的時間)就是(VSPW+1)+ (VBPD+1)+(LINEVAL+1)+(VFPD+1)個HSYNC週期,
一個HSYNC週期爲(HSPW+1)+(HBPD+1)+(HOZVAL+1)+(HFPD+1)個VCLK週期
所以,一幀週期= {(VSPW+1)+ (VBPD+1)+(LINEVAL+1)+(VFPD+1) } * { (HSPW+1)+(HBPD+1)+(HOZVAL+1)+(HFPD+1)}個VCLK週期
這裏的數據手冊給出了:
VCLK的頻率(hz)=VCLK(Hz) = HCLK / [ ( CLKVAL+1) * 2 ]
其中CLKVAL的最小值取0。
所以一幀的頻率就是:
Frame Rate = 1 / [ { (VSPW+1 ) + (VBPD+1 ) + (LIINEVAL + 1 ) +(VFPD+1 ) } * {(HSPW+1 ) + (HBPD +1 ) + (HFPD+1 ) + (HOZVAL + 1 ) } *{ 2 x (CLKVAL+1 ) / ( HCLK ) } ]
因此只需要設置上面公式的那個變量值然後給出幀內存的地址就可以進行數據的顯示。
接下來說一下圖像是如何存儲的,在說着之前需要了解一個概念BPP:
BPP(像素深度):像素深度是指存儲每個像素所用的位數,它也是用來度量圖像的分辨率。像素深度決定彩色圖像的每個像素可能有的顏色數,或者確定灰度圖像的每個像素可能有的灰度級數。
例如,一幅彩色圖像的每個像素用R,G,B三個分量表示,若每個分量用8位,那麼一個像素共用24位表示,就說像素的深度爲24,每個像素可以是16 777 216(2的24次方)種顏色中的一種。在這個意義上,往往把像素深度說成是圖像深度。表示一個像素的位數越多,它能表達的顏色數目就越多,而它的深度就越深。
2440數據手冊中有2BPP、4BPP、8BPP、16BPP、24BPP,這裏只介紹16BPP其餘的也類似。
假如LCD採用,16BPP來顯示,2440採用的方式是用4個字節來存儲兩個像素點的BPP,其中給個像素點的BPP爲佔用2個字節,但是這樣就有兩種存儲方式:
當BSWP = 0, HWSWP = 0時,2440採用的是上面的存儲方式,當BSWP = 0, HWSWP = 2440採用的是下面的存儲方式:
在LCD中,像素點P1、P2、P3等的排列方式爲:
採用16BPP存儲方式,也就是紅綠藍RGP一個佔有16個bit,他們的分配方式有兩種5:6:5和5:5:5:1,對於第二種方式,最後一個強度位,可以看作是GRB每個有顏色的最低位,就像下圖中的下面的那個表格,VD的18位,10位,2位分別有一位,因此5:5:5:1和R(5+1):G(5+1):B(4+1)是一樣的(但是不能理解爲2^18個顏色值)。
lcd採用的24位數據線來傳遞數據,兩種方式的在24位傳送過程中的安排分別爲:
至於其他格式的bpp可以參考數據手冊,接下來說一下調色板,直白的說,調色板就是一塊256*16的一塊內存,使用8BPP模式的時候,可以通過索引值查找調色板,調色板跟16BPP類似可以使用5:6:5和5:5:5:1兩種模式,其存放格式分別如下圖:
可以看到,調色板的深度爲0到0Xff,寬度爲16bit,通過圖中可以看出,調色板的起始地址爲0X4D000400,結束地址爲0X4D0007FC,這裏調色板只用到32內存的低16位DATA[31 :1 6]上的數據是無效數據。假如是5:5:5:1格式存儲,傳輸的VD1 8, VD1 0 和VD2都是傳輸的同一個值data(l)。
下面就開始一一介紹控制lcd的寄存器:
先看下LCDCON1,功能如下圖:
ENVID:LCD 輸出信號控制位 爲1表示使能
BPPMODE:屏幕類型的對應BPP的選擇
PNRMODE:屏幕類型的選擇
MMODE :對於STN LCD設置VM的反轉頻率
CLKVAL :設置像素時鐘
對於TFT: VCLK=HCLK/((CLKVAL+1)*2)
HCLK=100Mhz的情況下,lcd手冊說明VCLK典型的是9Mhz,CLKVAL=4或者5
LINECNT :只讀位,每掃描一行LINECNT的值減去1,直到減到0
LCDCON2,LCDCON3,LCDCON4其具體含義在前面已經分析,不再贅述,寄存器功能如下圖:
LCDCON5寄存器主要是包含包含一些狀態的只讀寄存器和有關一些信號的極性設置:
HWSWP:半字交換使能位
BSWP:字交換是使能位
(上面兩個寄存器用來設置像素點在內存的存儲排列格式)
ENLEND:LEND使能寄存器
PWREN: LCD_PWREN使能寄存器
INVLEND:LEND信號的極性,是否反轉
INVWREN:pwren信號極性是否反轉
INVVEN:VDEN信號的極性,是否反轉
INVVD:VD數據傳輸的極性是否反轉
INVVFRAME:VFINE/HSYNC信號的極性是否反轉
INVVLINE:VLINE/HSYNC信號的極性是否反轉
INVVCLK:設置爲0在VCLK下降沿讀數據;設置爲10在VCLK上升沿讀數據
FRM565:設置16BPP時候,是565還是5551
BPP24BL:24BPP模式下,是低字節數據有效還是高字節數據有效
HSTATUS/ VSTATUS:只讀寄存器,用來獲取當前像素掃描到什麼部分。
LCDCON1到LCDCON5寄存器介紹完畢,這5個寄存器主要是設置與硬件密切相關的參數,接下來說的是有關幀內存方面的寄存器,介紹之前需瞭解一些概念,在LCD顯示的圖中,可以看到真正的顯示有效數據周圍還有許多無用的數據,這些所有的數據(有效數據+無效數據)稱爲一幀,而真正顯現出來的有效數據稱爲VIEW PORT,其圖可表示爲:
通過圖可以看出來,view port的大小就是實際LCD屏幕的大小,一幀中包含着view port,而且view port在一幀當中的位置是是可以移動的,其位置有LCDBASEU 、LCDBASEL(view port上下兩點顯示的起始地址),PAGEWIDTH(view port的寬度也就是lcd的寬度)決定的。這些值具體的設定需要看下面的寄存器。
首先是LCDSADDR1寄存器:
LCDBASEU:對於TFT LCD,用來保存視口(view port)對應的內存的起始地址(view port的第一個數值的地址即對應圖中view port左上角的位置地址),也就是幀緩衝區的開始地址。(可以參考上面的位移圖來理解)。其存放的是幀內存首地址(32位的數值)的第21~1位。
LCDBANK:保存幀內存的起始地址(保存幀內存首地址(首地址爲32位的數值)的第30~22位),爲了當移動view port窗口的時候不影響LCDBANK的值,必須4m對齊。
總的來說LCDBASEU存放的是幀內存起始地址的【21:1】位,LCDBANK保存的是幀內存起始地址的【30:22】位
接下來LCDSADDR2:
LCDBASEL:具體的含義可以看上面的那個VIEW PORT的移動的圖理解,對於TFT LCD,保存的是view port最後一行的起始地址,其計算公式爲:
LCDBASEL = ((the frame end address) >>1 ) +1
= LCDBASEU +(PAGEWIDTH+OFFSIZE) x (LINEVAL+1 )
上面的公式通過上面的那個位移圖應該不難理解,只是要注意的就是這裏的OFFSIZE是view port位圖上的左右兩個標出的OFFSIZE的和。一般情況下LCDBASEL存放的是緩存區的大小的【21:1】(幀內存最大是4m,也就是最大爲22位)+偏移地址(幀內存的首地址)。
接下來就是
PAGEWIDTH:view port的寬度,以半字爲單位(32位的cpu 半字就是16bit)
OFFSIZE:表示上一行最後一個數據與下一行第一個數據間的地址差的一半,以半字爲單位。假如OFFSIZE數值2代表相差4個半字。
設置一且完畢後,再來看一下調色板的信息設置:
TPALVAL:這隻調色板的GPG的數值
TPAL調色板的使能位。
設置前面的這些寄存器lcd就可以穩定的工作了,但是lcd控制器爲了更可能的節約時間,滿足不同需求,其拱了一個lcd中斷等的操作,具體的看下面的幾個寄存器:
LCDINTPND中斷掛起寄存器,主要是表示lcd的中斷掛起的情況
INT_FiCnt:中斷掛起位,該位爲0表示沒有發生中斷請求,當該位是1表明lcd的FIFO的已經達到指定的閾值。
INT_FrSyn:幀同步中斷掛起位,該位爲0表示沒有幀同步中斷請求,該位爲1表明幀發出中斷請求(lcd已經顯示完一幀)。
與中斷掛起寄存器LCDINTPND雷同的另一個寄存器是,中斷源掛起寄存器,他們的功能相同,這裏解釋一下中斷源,大家都知道中斷是指由於某種事件的發生(硬件或者軟件的),計算機暫停執行當前的程序,轉而執行另一程序,以處理髮生的事件,處理完畢後又返回原程序繼續作業的過程。中斷是處理器一種工作狀態的描述。我們把引起中斷的原因,或者能夠發出中斷請求信號的來源統稱爲中斷源。
對應的中斷源掛起寄存器爲中斷源掛起寄存器,表明中斷源掛起狀態
INT_FiCnt:中斷掛起位,該位爲0表示沒有發生中斷請求,當該位是1表明lcd的FIFO的已經達到指定的閾值。
INT_FrSyn:幀同步中斷掛起位,該位爲0表示沒有幀同步中斷請求,該位爲1表明幀發出中斷請求(lcd已經顯示完一幀)。
既然lcd有前面的這兩個狀態寄存器那麼一定有與之對應的中斷屏蔽寄存器來屏蔽中斷的發生,這裏的寄存器是LCDINTMSK,中斷屏蔽寄存器可以決定屏蔽那個中斷源(被屏蔽掉的中斷源將不會發生作用)。
INT_FiCnt:屏蔽lcd FIFO中斷位,該位設置爲0表明相應lcd的FIFO的中斷,該位設置爲1表示屏蔽lcd的FIFO的中斷。
INT_FrSyn:屏蔽lcd 幀同步中斷位,該位是指爲1表明屏蔽幀同步中斷。
FIWSEL: 決定lcd的FIFO出發的閾值,設置爲0閾值爲4字,設置爲1表示深度爲8字
此外三星公司爲自己生產的lcd增加了控制LPC3600/LCC3600 模式的寄存器TCONSEL:
對於該寄存器不做介紹,使用的非LPC3600 LCC3600給該寄存的【0 1】寫0禁止該模塊就可以。
所有有關TFT lcd的寄存器已經大致介紹完畢,接下來說明控制lcd的步驟:
總結:
1、初始化有關連接lcd的引腳,連接方式看開發板原理圖
2、LCDCON1到LCDCON5 用於選擇lcd的了類型,設置一些硬件的信息。
3、CDSADDR1到LCDSADDR3設置幀內存的地址
4、TPAL設置,是否使用調色板及其設置調色板的數據。
5、根據自身是否使用三星公司的 lpc3600 和lcc3600 LCD,假如不使用的話需要禁止相應模塊
可以通過TCONSEL來設置。
6、設置是否使用中斷,可通過LCDINTMSK來設置
7、控制lcd的打開或者關閉。
下面給出設置代碼:
voidlcd_Init(void)
{
#define VBPD (1) //垂直同步信號的後肩
#define VFPD (1) //垂直同步信號的前肩
#define VSPW (9) //垂直同步信號的脈寬
#define HBPD (1) //水平同步信號的後肩
#define HFPD (1) //水平同步信號的前肩
#define HSPW (40) //水平同步信號的脈寬
1、初始化有關連接lcd的引腳,連接方式看開發板原理圖
rGPCUP = 0xffffffff; // 禁止內部上拉
rGPCCON = 0xaaaaaaaa; // GPIO管腳用於VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
rGPDUP = 0xffffffff; // 禁止內部上拉
rGPDCON = 0xaaaaaaaa; // GPIO管腳用於VD[23:8]
rGPBCON &= ~(3<<0); // lcd背光燈控制引腳
rGPBCON |= (1<<0);
rGPBDAT &= ~(1<<0); //關閉背光燈
2、 LCDCON1到LCDCON5用於選擇lcd的了類型,設置一些硬件的信息。
// 設置像素時鐘頻率,屏幕模型,bpp模式
rLCDCON1 = (5<< 8)|(3 <<5 )|(12<< 1) ;
rLCDCON2 = (VBPD << 24)|(271<< 14)|(VFPD << 6)|(VSPW);
rLCDCON3 = (HBPD << 19)|(479<< 8)|(HFPD);
rLCDCON4 = (HSPW);
//信號極性 數據存儲格式等的設置
rLCDCON5 = (1 << 11) |(1 <<10)| (1 << 9) | (1 << 8) |(1) ;
//選擇565格式 上升沿鎖存數據 VLINE/HSYNC VFIAME/VSYNC 反轉 存儲格式P1 P2
3、 CDSADDR1到LCDSADDR3設置幀內存的地址
//這裏的LCDBANK定義爲volatile unsigned shortLCDBANK[272][480]; //申請幀內存LCDBANK是系統隨機分配的
rLCDSADDR1 =(((unsigned int)LCDBANK >> 22) << 21) | ((((unsignedint)LCDBANK)>> 1)& 0x1fffff );
//((unsigned int)LCDBANK >> 22)<< 21) 將內存地址的22到30位存到寄存器的21到29位中
//(unsigned int)LCDBANK)& 0x1fffff 取出低21位
//(((unsigned int)LCDBANK)&>> 1)0x1fffff 內存首地址(32位的數值)的第21~1位放到寄存器的20~0
rLCDSADDR2 = ( ((unsigned int)LCDBANK + ( (480* 272 *2) ) >> 1 )) &0x1fffff;
//((the frame end address) >>1 ) +1 之所以有(480 * 272 *2)的乘以2是因爲16BPP假如8BPP則乘以1
//先左移1位後取低21位
rLCDSADDR3 = (0 << 11) | (480 / 1);
//offsize爲0 16bpp正好一個像素佔用一個半字
4、TPAL設置,是否使用調色板及其設置調色板的數據
///禁止臨時調色板寄存器
rTPAL = 0;
5、根據自身是否使用三星公司的 lpc3600和lcc3600LCD,假如不使用的話需要禁止相應模塊
可以通過TCONSEL來設置。
//禁止LPC3600/LCC3600模式
rTCONSEL &= ~((1 << 0)| (1 <<1) | (1 << 2)) ;
6、設置是否使用中斷,可通過LCDINTMSK來設置
rLCDINTMSK |= (3); //MASK LCD Sub Interrupt
7、控制lcd的打開或者關閉
rLCDCON1 |= 1;//使能LCD數據信號的傳輸
lcd_power_control(1);//使能lcd
}