S3C2410之LCD
將LCD背光對應的GPIO設(shè)置為禁止上拉(GPxUP相應位寫入1),選擇output類型(GPxCON相應位寫入01),輸出為高電平(GPxDAT相應位寫入1)。
2、打開LCD電源
可以將GPG4選擇為LCD_PWREN(GPGCON:9-8寫入11),這時候LCD電源的打開/關(guān)閉可以通過LCDCON5:3來控制。
也可以自定義其他GPIO用作LCD電源開關(guān),只需將此GPIO設(shè)置為禁止上拉(GPxUP相應位寫入1),選擇output類型(GPxCON相應位寫入01),輸出為高電平(GPxDAT相應位寫入1)打開LCD電源。
3、設(shè)置其他信號線
其他信號線包括VD0-VD23和VFRAME、VLINE、VCLK等,分別在GPCCON,GPDCON中選擇相應功能。
4、設(shè)置LCD的頻率(VCLK)
LCD的Datasheet上一般會寫有一個推薦的頻率,比如我使用的屏幕推薦頻率為6.4M,我需要通過一些計算選擇一個合適的CLKVAL以產(chǎn)生這個頻率:
對于TFT LCD,S3C2440提供的VCLK的計算公式為:
VCLK = HCLK / ((CLKVAL+1)*2)
可以得出:
CLKVAL = HCLK / (VCLK * 2) - 1
我的HCLK是100Mhz(CPU運行在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其實就是根據(jù) 每秒幀數(shù)*幀行數(shù)*行像素 計算出來的,幀行數(shù)和行像素需要包含空白數(shù)和同步數(shù))
5、設(shè)置其他相關(guān)參數(shù)
LCD相關(guān)的參數(shù)主要還有這幾個:
LINEVAL: LCD水平像素-1,如320-1 = 319
HOZVAL: LCD垂直像素-1,如240-1 = 239
HFPD: 行開始前的VCLK時鐘數(shù)(LCD屏幕的Datasheet一般有推薦值)
HBPD: 行結(jié)束后的VCLK時鐘數(shù)(LCD屏幕的Datasheet一般有推薦值)
HSPW: 行之間水平同步的無效VCLK時鐘數(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寄存器實現(xiàn)屏幕快速移動
PAGEWIDTH:虛擬屏幕一行的字節(jié)數(shù),如果不使用虛擬屏幕,設(shè)置為實際屏幕的行字節(jié)數(shù),如16位寬320像素,設(shè)為320 * 2
OFFSIZE:虛擬屏幕左側(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一一確認。
(相關(guān)寄存器LCDCON5)
8、禁止LPC3600/LCC3600模式!
如果不是使用三星LPC3600/LCC3600 LCD,必須禁止LPC3600/LCC3600模式(寫入0到TCONSEL)!
9、打開視頻輸出
ENVID設(shè)為1 (LCDCON1:0寫入1)
void Test_Lcd_Tft_8Bit_640480(void)
{
int i,j,k;
Lcd_Palette8Bit_Init();//調(diào)色板初始化,格式為 5:6:5 并賦值調(diào)色板的初始地址
void Lcd_Palette8Bit_Init(void)
{
int i;
U32 *palette;
rLCDCON5|=(1<<11); // 5:6:5 Palette Setting
palette=(U32 *)PALETTE;
for(i=0;i<256;i++)
*palette++=DEMO256pal[i];
}
Lcd_Port_Init(); //LCD端口引腳初始化,包括第二功能,數(shù)據(jù)線及控制信號線等設(shè)置, Disable Pull-up registe
static void Lcd_Port_Init(void)
{
save_rGPCCON=rGPCCON;
save_rGPCDAT=rGPCDAT;
save_rGPCUP=rGPCUP;
save_rGPDCON=rGPDCON;
save_rGPDDAT=rGPDDAT;
save_rGPDUP=rGPDUP;
rGPCUP=0xffffffff; // Disable Pull-up register
rGPCCON=0xaaaaaaaa; //Initialize VD[7:0],LCDVF[2:0], VM, VFRAME,
//VLINE, VCLK,LEND 初始化數(shù)據(jù)線與各控制信號
rGPDUP=0xffffffff; // Disable Pull-up register
rGPDCON=0xaaaaaaaa; //Initialize VD[23:8]
}
Lcd_Init(MODE_TFT_8BIT_640480);//針對各模式下對幀緩沖起始地址及各控制寄存器rLCDCONn等進行相應設(shè)置等進行設(shè)置
void Lcd_Init(int type)
{
switch(type)
{......
case MODE_TFT_1BIT_640480:
frameBuffer1BitTft640480=(U32 (*)[SCR_XSIZE_TFT_640480/32])LCDFRAMEBUFFER;
/*//定義一個行數(shù)組指針extern U32 (*frameBuffer1BitTft640480)[SCR_XSIZE_TFT_640480/32],每行包括320個U32單元指針LCDFRAMEBUFFER進行強制類型轉(zhuǎn)換后賦給frameBuffer8BitTft240320,即frameBuffer8BitTft240320指向LCDFRAMEBUFFER*/
rLCDCON1=(CLKVAL_TFT_640480<<8)|(MVAL_USED<<7)|(3<<5)|(8<<1)|0;
/*//#define CLKVAL_TFT_640480 (1)
//53.5hz @90Mhz
//VSYNC,HSYNC should be inverted
//HBPD=47VCLK,HFPD=15VCLK,HSPW=95VCLK
//VBPD=32HSYNC,VFPD=9HSYNC,VSPW=1HSYNC
// TFT LCD panel,8bpp TFT,ENVID=off 顯示模式為TFT, VM速率為每幀一次,bpp為8bpp,禁止輸出LCD視頻數(shù)據(jù)及控制信號*/
rLCDCON2=(VBPD_640480<<24)|(LINEVAL_TFT_640480<<14)|(VFPD_640480<<6)|(VSPW_640480);
rLCDCON3=(HBPD_640480<<19)|(HOZVAL_TFT_640480<<8)|(HFPD_640480);
rLCDCON4=(MVAL<<8)|(HSPW_640480);
rLCDCON5=(1<<11)|(1<<9)|(1<<8);//FRM5:6:5,HSYNC and VSYNC are inverted
rLCDSADDR1=(((U32)frameBuffer1BitTft640480>>22)<<21)|M5D((U32)frameBuffer1BitTft640480>>1);
rLCDSADDR2=M5D( ((U32)frameBuffer1BitTft640480+(SCR_XSIZE_TFT_640480*LCD_YSIZE_TFT_640480/8))>>1 );
rLCDSADDR3=(((SCR_XSIZE_TFT_640480-LCD_XSIZE_TFT_640480)/16)<<11)|(LCD_XSIZE_TFT_640480/16);
rLCDINTMSK|=(3);// MASK LCD Sub Interrupt
rLPCSEL&=(~7);// Disable LPC3600
rTPAL=0;// Disable Temp Palette
break;
........
}
}
Glib_Init(MODE_TFT_8BIT_640480);//設(shè)置各像素點bpp的格式
void Glib_Init(int type)
{
switch(type)
{
case MODE_STN_1BIT:
...................
case MODE_TFT_8BIT_640480://#define MODE_TFT_8BIT_640480
PutPixel=_PutTft8Bit_640480;
break;
..................
}
void _PutTft8Bit_640480(U32 x,U32 y,U32 c)
{
if(x
frameBuffer8BitTft640480[(y)][(x)/4]=( frameBuffer8BitTft640480[(y)][x/4]
& ~(0xff000000>>((x)%4)*8) ) | ( (c&0x000000ff)<<((4-1-((x)%4))*8) );
}
/*
U32 (*frameBuffer8BitTft640480)[SCR_XSIZE_TFT_640480/4];//定義一行數(shù)組指針,具有SCR_XSIZE_TFT_640480/4=320個U32類型的元素
frameBuffer8BitTft640480=(U32 (*)[SCR_XSIZE_TFT_640480/4])LCDFRAMEBUFFER;//將LCDFRAMEBUFFER強制轉(zhuǎn)換為數(shù)組指針類型后賦給frameBuffer8BitTft640480 //#define LCDFRAMEBUFFER 0x33800000
rLCDSADDR1=(((U32)frameBuffer8BitTft640480>>22)<<21)|M5D((U32)frameBuffer8BitTft640480>>1);rLCDSADDR2=M5D( ((U32)frameBuffer8BitTft640480+(SCR_XSIZE_TFT_640480*LCD_YSIZE_TFT_640480/1))>>1 );
frameBuffer8BitTft640480[(y)][(x)/4]=( frameBuffer8BitTft640480[(y)][x/4]
& ~(0xff000000>>((x)%4)*8) ) | ( (c&0x000000ff)<<((4-1-((x)%4))*8) );
//extern U32 (*frameBuffer8BitTft640480)[SCR_XSIZE_TFT_640480/4];共包括行單元為320的U32行數(shù)組指針
//由于一個像素只占8個BIT,故一個U32單元存放了四個像素,對于一個X,需要先找到其所在的字:X/4,然后找到它所在該字中的位置:(x)%4),將其清0后再賦上相應的顏色值即: & ~(0xff000000>>((x)%4)*8) ) | ( (c&0x000000ff)<<((4-1-((x)%4))*8) :BSWP = 0//字節(jié)不可交抑郁, HWSWP = 0半字不可交換(1:可交換);P1在[31:24],P1在[23;16]....
*/
Lcd_PowerEnable(0, 1);//關(guān)掉電源
void Lcd_PowerEnable(int invpwren,int pwren)
{
//GPG4 is setted as LCD_PWREN定義引腳為第四功能即LCD_PWREN
rGPGUP=rGPGUP&(~(1<<4))|(1<<4); // Pull-up disable
rGPGCON=rGPGCON&(~(3<<8))|(3<<8); //GPG4=LCD_PWREN
//Enable LCD POWER ENABLE Function
rLCDCON5=rLCDCON5&(~(1<<3))|(pwren<<3); // PWREN
rLCDCON5=rLCDCON5&(~(1<<5))|(invpwren<<5); // INVPWREN
}
Lcd_EnvidOnOff(1);//允許LCD視頻數(shù)據(jù)及LCD控制信號
void Lcd_EnvidOnOff(int on
{
if(on
rLCDCON1|=1; // ENVID=ON
else
rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
}
Uart_Printf("[TFT 256 COLOR(8bit/1pixel) LCD TEST] ");
Glib_ClearScr(0, MODE_TFT_8BIT_640480);//清除屏幕
void Glib_ClearScr(U32 c, int type)
{
//Very inefficient function.
int i,j;
//if((type==MODE_TFT_1BIT_800600)|(type==MODE_TFT_8BIT_800600) |//(type==MODE_TFT_16BIT_800600))
if((type&0x4000)&&(type&0x400))
for(j=0;j
for(i=0;i
PutPixel(i,j,c);
//else if((type==MODE_TFT_1BIT_640480)|(type==MODE_TFT_8BIT_640480)|(type==MODE_TFT_16BIT_640480))
else if((type&0x4000)&&(type&0x200))
for(j=0;j
for(i=0;i
PutPixel(i,j,c); //在前面函數(shù)指針已賦值PutPixel=_PutTft8Bit_640480
............
}
rTPAL = (1<<24)|((0xff)<<0); // Enable Temporary Palette : Blue
Uart_Printf("TFT 256 color mode test 1. Press any key! ");
Uart_Getch();
k=0;
for(i=0;i<640;i+=40)
for(j=0;j<480;j+=30)
{
Glib_FilledRectangle(i,j,i+39,j+29,(k%256));
k++;
}
rTPAL = 0;
Uart_Printf("TFT 256 color mode test 2. Press any key! ");
Uart_Getch();
......
}
frameBuffer8BitTft640480=(U32 (*)[SCR_XSIZE_TFT_640480/4])LCDFRAMEBUFFER;//將LCDFRAMEBUFFER強制轉(zhuǎn)換為數(shù)組指針類型后賦給frameBuffer8BitTft640480 //#define LCDFRAMEBUFFER 0x33800000
rLCDSADDR1=(((U32)frameBuffer8BitTft640480>>22)<<21)|M5D((U32)frameBuffer8BitTft640480>>1);rLCDSADDR2=M5D( ((U32)frameBuffer8BitTft640480+(SCR_XSIZE_TFT_640480*LCD_YSIZE_TFT_640480/1))>>1 );
frameBuffer8BitTft640480[(y)][(x)/4]=( frameBuffer8BitTft640480[(y)][x/4]
& ~(0xff000000>>((x)%4)*8) ) | ( (c&0x000000ff)<<((4-1-((x)%4))*8) );
*/
Lcd_PowerEnable(0, 1);//關(guān)掉電源
void Lcd_PowerEnable(int invpwren,int pwren)
{
//GPG4 is setted as LCD_PWREN定義引腳為第四功能即LCD_PWREN
rGPGUP=rGPGUP&(~(1<<4))|(1<<4); // Pull-up disable
rGPGCON=rGPGCON&(~(3<<8))|(3<<8); //GPG4=LCD_PWREN
//Enable LCD POWER ENABLE Function
rLCDCON5=rLCDCON5&(~(1<<3))|(pwren<<3); // PWREN
rLCDCON5=rLCDCON5&(~(1<<5))|(invpwren<<5); // INVPWREN
}
Lcd_EnvidOnOff(1);//允許LCD視頻數(shù)據(jù)及LCD控制信號
void Lcd_EnvidOnOff(int on
{
if(on
rLCDCON1|=1; // ENVID=ON
else
rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
}
Uart_Printf("[TFT 256 COLOR(8bit/1pixel) LCD TEST] ");
Glib_ClearScr(0, MODE_TFT_8BIT_640480);//清除屏幕
void Glib_ClearScr(U32 c, int type)
{
//Very inefficient function.
int i,j;
//if((type==MODE_TFT_1BIT_800600)|(type==MODE_TFT_8BIT_800600) |//(type==MODE_TFT_16BIT_800600))
if((type&0x4000)&&(type&0x400))
for(j=0;j
for(i=0;i
PutPixel(i,j,c);
//else if((type==MODE_TFT_1BIT_640480)|(type==MODE_TFT_8BIT_640480)|(type==MODE_TFT_16BIT_640480))
else if((type&0x4000)&&(type&0x200))
for(j=0;j
for(i=0;i
PutPixel(i,j,c); //在前面函數(shù)指針已賦值PutPixel=_PutTft8Bit_640480
............
}
rTPAL = (1<<24)|((0xff)<<0); // Enable Temporary Palette : Blue
Uart_Printf("TFT 256 color mode test 1. Press any key! ");
Uart_Getch();
k=0;
for(i=0;i<640;i+=40)
for(j=0;j<480;j+=30)
{
Glib_FilledRectangle(i,j,i+39,j+29,(k%256));
k++;
}
rTPAL = 0;
Uart_Printf("TFT 256 color mode test 2. Press any key! ");
Uart_Getch();
......
}
評論