基于S3C6410&WINCE6.0的LCD驱动详解

 花了几天时间把6410的点屏代码研究了一下,这里分享出来供大家参考。

      先大致说下目前LCD的类型以及渠道。针对手持设备,如手机,PMP,MID,GPS,UMPC,相机等,大多采用的是TFT,LTPS(低温多晶硅屏),OLED等。其中以TFT屏用的最广泛,LTPS屏以其色彩鲜艳,视角广而闻名,目前也逐渐多起来。OLED显示效果是以上三者中最好的,能够达到全视角,而且在阳光照射下也能清晰的观看,但由于技术还不够成熟,价格一直居高不下,但是OLED是未来屏的主流趋势。现在很多价值上千元的手机都采用了OLED的屏,色彩鲜艳,拿在手上感觉就不一样。LTPS以统宝的屏最为典型,如统宝4.3寸,4.8寸的WVGA屏。大名鼎鼎的艾诺V3000就是采用的统宝4.3寸WVGA屏,效果远比TFT要好。另外,大名鼎鼎的诺基亚N97也采用了统宝的3.2寸屏。当然使用最广泛也是最泛滥的,就非TFT屏莫属了。一般将TFT屏分成日韩系,台系,以及大陆系三个级别,其质量基本上也是依次降低。日韩以三星,LG,夏普为典型,当然价格一直是居高不下。台系以友达,奇美,汉彩,群创为代表,大陆的如比亚迪,国显,京东方等。在中国中低端市场,基本上都采用奇美的IC,玻璃拼成的模组,因此虽然很多虽然不同的厂家,但屏的驱动不用变。但是如果驱动IC变了,驱动也要稍加调整。下面就以三星的6410处理器为例讲述如何调整这些参数。

      液晶屏的硬件接口如下图所示:

基于S3C6410&WINCE6.0的LCD驱动详解_第1张图片

    上面是40PIN的LCD的电路接口,该接口基本上兼容了市面上大多数的4.3,5.0寸的屏。4.3的屏如群创,信利,比亚迪,国显,高显,奇美,汉彩等;5.0寸的屏如奇美,比亚迪,国显,高显,汉彩等,都采用上面的接口。虽然有些屏用的driver IC不尽相同,但是都是八九不离十,要知道在中国很多IC本身就是抄来抄去的。

      针对S3C6410的LCD驱动,首先,在bootloader中,会配置LCD的一些寄存器参数,配置overlay,window等寄存器参数,在进入系统后,会调用LCD驱动,驱动中又会重新刷一片LCD的寄存器,最终进入系统。这里主要说明关于LCD本身的一些参数,代码如下:

[cpp]  view plain copy
  1. case LDI_SMRP_LTE480WV_RGB:  
  2.     LDI_INF((_T("[LDI:INF] Output Devce Type [%d] = LDI_(SMRP)LTE480WV_RGB/n/r"), g_ModuleType));  
  3.     pDeviceInfo->RGBOutMode = DISP_16BIT_RGB565_P;  
  4.     pDeviceInfo->uiWidth = 800;  
  5.     pDeviceInfo->uiHeight = 480;  
  6.     pDeviceInfo->VBPD_Value = 8;  
  7.     pDeviceInfo->VFPD_Value = 35  
  8.     pDeviceInfo->VSPW_Value = 2;  
  9.     pDeviceInfo->HBPD_Value = 88;  
  10.     pDeviceInfo->HFPD_Value = 40;  
  11.     pDeviceInfo->HSPW_Value = 128;  
  12.     pDeviceInfo->VCLK_Polarity = IVCLK_FALL_EDGE;  
  13.     pDeviceInfo->HSYNC_Polarity = IHSYNC_LOW_ACTIVE;  
  14.     pDeviceInfo->VSYNC_Polarity = IVSYNC_LOW_ACTIVE;  
  15.     pDeviceInfo->VDEN_Polarity = IVDEN_HIGH_ACTIVE;  
  16.     pDeviceInfo->PNR_Mode = PNRMODE_RGB_P;  
  17.     pDeviceInfo->VCLK_Source = CLKSEL_F_LCDCLK;  
  18.     pDeviceInfo->VCLK_Direction = CLKDIR_DIVIDED;  
  19.     pDeviceInfo->Frame_Rate = 60; // VCLK > 24.5 MHz (Max 35.7 MHz)  
  20.     break;  

 

 

程序中uiWidth,uiHeight,VBPD,VFPD,VSPW,HBPD,HFPD,HSPW即为相关屏的参数,上面的参数是国显5寸屏的参数。

uiWidth:液晶屏的行点数,即扫描一行需要在屏上绘制多少个点。

uiHeight:液晶屏的列点数。

VBPD:列开始等待周期,即LCD显示每帧开始时有VBPD个周期没有图像输出。

VFPD:列结束等待周期,即LCD显示每帧结束时有VFPD个周期没有图像输出。

VSPW:场同步脉宽,指Vsync为低电平时的行脉冲周期数目。

HBPD:行开始等待周期,即LCD显示每行开始时有HBPD个周期没有图像输出。

HFPD:行结束等待周期,即LCD显示每行结束时有HFPD个周期没有图像输出。

HSPW:行同步脉宽,指Hsync为低电平时占用的DCLK的周期。

以上VBPD,VFPD,VSPW是为了场同步,HBPD,HFPD,HSPW是为了行同步,在硬件接口中有Vsync和Hsync两个PIN脚,就是帧同步信号和行同步信号。

Vsync:帧同步信号,整幅图像输出后会产生一个下降沿,即帧同步的标志。

Hsync:行同步信号,扫描完一行后会产生一个下降沿,即行同步的标志。

国显屏的时序图如下:

 

 基于S3C6410&WINCE6.0的LCD驱动详解_第2张图片

 基于S3C6410&WINCE6.0的LCD驱动详解_第3张图片

 

从上面图可以看出,

TWH=HSPW,

THS-TWH=HBPD,

THA=uiWidth,

TH-THA-THS=HFPD,

TWV=VSPW,

TVS-TWV=VBPD,

TVA=uiHeight,

TV-TVS-TVA=VFPD.

再参看下面的表,即可计算出相应的值。

将值填入上面的代码,到目前为止,离成功已经不远了。

 基于S3C6410&WINCE6.0的LCD驱动详解_第4张图片

 

最后,还有屏的帧频没有设置。国显屏规格书的建议值是DCLK=33.26M,这里,通过S3C6410手册上提供的公式,

RGB_VCLK (Hz) =HCLK/ (CLKVAL+1) where CLKVAL >= 1;

 

Frame Rate = 1/ [ { (VSPW+1) + (VBPD+1) + (LIINEVAL + 1) + (VFPD+1) } x {(HSPW+1) + (HBPD +1)

                              + (HFPD+1) + (HOZVAL + 1) } x { ( CLKVAL+1 ) / ( Frequency of Clock source ) } ]

 

这里RGB_VCLK=33.26M,HCLK=133000000,可以计算出CLKVAL=3.我们将这个值填入6410的寄存器,代码如下:

[cpp]  view plain copy
  1. static DISP_ERROR Disp_initialize_RGBIF(void)  
  2. {  
  3.     DISP_ERROR error = DISP_SUCCESS;  
  4.     unsigned int VCLKDivider;  
  5.   
  6.     DISP_MSG((_T("[DISP]++Disp_initialize_RGBIF()/n/r")));  
  7.   
  8.     if (Disp_get_vclk_direction_divider(g_DevInfoRGB.VCLK_Source, &g_DevInfoRGB.VCLK_Direction, &VCLKDivider))  
  9.     {  
  10.         g_pDispConReg->VIDCON0 = PROGRESSIVE | VIDOUT_RGBIF | g_DevInfoRGB.PNR_Mode | CLKVALUP_ALWAYS |  
  11.                                 CLKVAL_F(VCLKDivider) | VCLK_NORMAL | g_DevInfoRGB.VCLK_Direction |  
  12.                                 g_DevInfoRGB.VCLK_Source | ENVID_DISABLE | ENVID_F_DISABLE;  
  13.   
  14.         g_pDispConReg->VIDCON1 = g_DevInfoRGB.VCLK_Polarity | g_DevInfoRGB.HSYNC_Polarity |  
  15.                                 g_DevInfoRGB.VSYNC_Polarity | g_DevInfoRGB.VDEN_Polarity;  
  16.   
  17.         g_pDispConReg->VIDCON2 = TVIF_FMT_YUV444;    // Should be this value  
  18.   
  19.         g_pDispConReg->VIDTCON0 = VBPDE(1) | VBPD(g_DevInfoRGB.VBPD_Value) |  
  20.                                 VFPD(g_DevInfoRGB.VFPD_Value) | VSPW(g_DevInfoRGB.VSPW_Value);  
  21.   
  22.         g_pDispConReg->VIDTCON1 = VFPDE(1) | HBPD(g_DevInfoRGB.HBPD_Value) |  
  23.                                 HFPD(g_DevInfoRGB.HFPD_Value) | HSPW(g_DevInfoRGB.HSPW_Value);  
  24.   
  25.         g_pDispConReg->VIDTCON2 = LINEVAL(g_DevInfoRGB.uiHeight) | HOZVAL(g_DevInfoRGB.uiWidth);  
  26.     }  
  27.     else  
  28.     {  
  29.         DISP_ERR((_T("[DISP:ERR] Disp_initialize_RGBIF() : Clock Source Decision Failed/n/r")));  
  30.         error = DISP_ERROR_ILLEGAL_PARAMETER;  
  31.     }  
  32.   
  33.     DISP_MSG((_T("[DISP]--Disp_initialize_RGBIF() : %d/n/r"), error));  
  34.   
  35.     return error;  
  36. }  

到此为止,屏已经正常点亮了。

你可能感兴趣的:(基于S3C6410&WINCE6.0的LCD驱动详解)