S3C2440 TFTLCD驅(qū)動詳解
S3C2440自帶有LCD控制器,該控制器主要有以下接口
僅僅說TFT顯示器,TFT顯示器的時序如下
TFT顯示器的驅(qū)動是以行列的形式逐點掃描過來的,驅(qū)動時鐘有三種,一種是行時鐘,一種是列時鐘,還有一個點時鐘, VSYNC低電平期間需要掃描完一列數(shù)據(jù), HSYNC低電平期間要寫完一個點的數(shù)據(jù),vclk負責一個點的每一位數(shù)據(jù)寫入,實際上就是說,如果有a列,b行,一個點需c個VCLK時鐘,那么掃描完成需要的中vclk為a*b*c(近似,中間還有一些延時時間)
可以將這個過程看作是1602的刷新過程, VSYNC為低選擇一列, HSYNC為低選擇一行,然后寫入顯示數(shù)據(jù)還需要一個數(shù)據(jù)時鐘,寫完之后指針自動增長,中間的等待時間是設備響應時間,在TFT上叫做同步時間,用于時鐘的同步,防止時鐘混亂
那么現(xiàn)在就有這些參數(shù)需要設置
VBPD: VSYNC與VCLK的開始同步時間
VSPW: VHYNC脈沖的高電平寬度
LINEVAL LCD面板的垂直尺寸:
VFPD: VSYNC與VCLK的結束同步時間
HBPD: HSYNC與VCLK的開始同步時間
HFPD: HSYNC與VCLK的結束同步時間
HOZVAL: 決定了LCD面板的水平尺寸
HSPW: HSYNC脈沖的高電平寬度
配置這些參數(shù)一般都依靠顯示器的數(shù)據(jù)手冊進行配置,我使用群創(chuàng)4.3寸屏幕,數(shù)據(jù)手冊上顯示
也就是說,確定一個DCLK時間,剩下的都可以確定了.(配置之前注意IO口功能配置GPIOC和D)
根據(jù)這張表,驅(qū)動S3C2440的步驟分為以下幾步
1.設置DCLK頻率,像素比以及信號輸出
2.確定VSYC的開始同步結束同步以及高電平寬度還有尺寸
3.3.設置HSYC的開始同步結束同步以及高電平寬度還有尺寸
4.設置HSPW時間
5.對于輸出的圖像格式進行一些選擇
6.設置LCD顯示緩沖區(qū)相關的數(shù)據(jù)
然后,CPU系統(tǒng)就會去自動刷新屏幕(使用緩沖區(qū)數(shù)據(jù)),而我們的讀出寫入都針對于緩沖區(qū),再由顯示器接口寫入顯示器
具體設置請查看程序:
Lcd.c
#include"tftlcd.h"volatilestaticunsignedshortLCD_BUFFER[SCR_YSIZE_TFT][SCR_XSIZE_TFT];//定義顯示緩存區(qū)/**************************************************************TFTLCD功能模塊初始化**************************************************************/voidLCDInit(void){//配置引腳rGPCUP=0x00000000;rGPCCON=0xaaaa02a9;rGPDUP=0x00000000;rGPDCON=0xaaaaaaaa;//InitializeVD[15:8]//TFTLCDpanel,16bppTFT,ENVID=offrLCDCON1=(CLKVAL_TFT<<8)"(MVAL_USED<<7)|(3<<5)|(12<<1)|0;rLCDCON2=(VBPD<<24)|(LINEVAL_TFT<<14)|(VFPD<<6)|(VSPW);rLCDCON3=(HBPD<<19)|(HOZVAL_TFT<<8)|(HFPD);rLCDCON4=HSPW;rLCDCON5=(1<<11)|(0<<10)|(1<<9)|(1<<8)|(0<<7)|(0<<6)|(1<<3)|(BSWP<<1)|(HWSWP);//16位輸出格式565,VCLK下降沿取數(shù)據(jù)等(看數(shù)據(jù)手冊)這里指定目的地址rLCDSADDR1=(((u32)LCD_BUFFER>>22)<<21)|M5D((u32)LCD_BUFFER>>1);//單掃描rLCDSADDR2=M5D(((u32)LCD_BUFFER+(SCR_XSIZE_TFT*LCD_YSIZE_TFT*2))>>1);//LCD_WIDTH×16/16;由于是選擇的16位模式,//如果是24位模式,每個像素4字節(jié)則為LCD_WIDTH×32/16//(LCD_WIDTH在此為LCD_XSIZE_TFT)rLCDSADDR3=(((SCR_XSIZE_TFT-LCD_XSIZE_TFT)/1)<<11)|(LCD_XSIZE_TFT/1);rLCDINTMSK|=(3);//MASKLCDSubInterruptrTCONSEL&=(~7);//DisableLPC3600rTPAL=0;//禁止臨時調(diào)色板寄存器}/***************************************************************LCD視頻和控制信號輸出或者停止,1開啟視頻輸出**************************************************************/voidLCDEnvidOnOff(intonoff){if(onoff==1)rLCDCON1|=1;//ENVID=ONelserLCDCON1=rLCDCON1&0x3fffe;//ENVIDOff}/***************************************************************TFTLCD電源控制引腳使能*pwren=1時,允許PWREN信號*pwren=0時,禁止PWREN信號*invpwre=1,PWREN信號極性反轉*invpwre=0,PWREN信號極性正常**************************************************************/voidLCDPowerEnable(intinvpwren,intpwren){//GPG4issettedasLCD_PWRENrGPGUP|=(1<<4);//GPG4上拉電阻無效rGPGCON|=(3<<8);//GPG4=LCD_PWRENrGPGDAT|=1<<4;//GPG4置1//invpwren=pwren;//EnableLCDPOWERENABLEFunctionif(pwren)rLCDCON5|=1<<3;elserLCDCON5&=~(1<<3);if(invpwren)rLCDCON5|=1<<5;elserLCDCON5&=~(1<<5);}/**************************************************************TFTLCD單個象素的顯示數(shù)據(jù)輸出**************************************************************/voidLCDPutPixel(u32x,u32y,u32color){if((x0)incx=1;//設置單步方向elseif(delta_x==0)incx=0;//垂直線else{incx=-1;delta_x=-delta_x;}if(delta_y>0)incy=1;elseif(delta_y==0)incy=0;//水平線else{incy=-1;delta_y=-delta_y;}if(delta_x>delta_y)distance=delta_x;//選取基本增量坐標軸elsedistance=delta_y;for(t=0;t<=distance+1;t++)//畫線輸出{LCDPutPixel(uRow,uCol,color);//畫點xerr+=delta_x;yerr+=delta_y;if(xerr>distance){xerr-=distance;uRow+=incx;}if(yerr>distance){yerr-=distance;uCol+=incy;}}}//畫矩形voidLCDDrawRectangle(u16x1,u16y1,u16x2,u16y2,u16color){LCDDrawLine(x1,y1,x2,y1,color);LCDDrawLine(x1,y1,x1,y2,color);LCDDrawLine(x1,y2,x2,y2,color);LCDDrawLine(x2,y1,x2,y2,color);}//在指定位置畫一個指定大小的圓//(x,y):中心點//r:半徑voidLCDDrawCircle(u16x0,u16y0,u8r,u16color){inta,b;intdi;a=0;b=r;di=3-(r<<1);//判斷下個點位置的標志while(a<=b){LCDPutPixel(x0-b,y0-a,color);//3LCDPutPixel(x0+b,y0-a,color);//0LCDPutPixel(x0-a,y0+b,color);//1LCDPutPixel(x0-b,y0-a,color);//7LCDPutPixel(x0-a,y0-b,color);//2LCDPutPixel(x0+b,y0+a,color);//4LCDPutPixel(x0+a,y0-b,color);//5LCDPutPixel(x0+a,y0+b,color);//6LCDPutPixel(x0-b,y0+a,color);a++;//使用Bresenham算法畫圓if(di<0)di+=4*a+6;else{di+=10+4*(a-b);b--;}LCDPutPixel(x0+a,y0+b,color);}}