专题16-LCD配置与使用

LCD硬件体系

OK6410使用一块4.3寸带触摸屏的TFT-LCD屏幕,内部集成驱动电路以及背光模块,其分辨率是480*272,其触摸屏是四线电阻式触摸屏。

LCD硬件体系包括LCD液晶屏、LCD驱动器、LCD控制器,其中液晶屏和驱动器往往集成在一起作为产品进行发布。LCD需要连接到ARM处理器的LCD控制器上,由LCD控制器负责提供给LCD驱动器必要的数据和控制信号。要操作LCD屏幕,就是要配置和使用LCD控制器。
Alt text

LCD屏幕由一行一行的像素点构成,LCD的显示过程如下:

  1. 显示从屏幕左上角第一行的第一个点开始,一个一个点地在LCD上显示,当显示到屏幕的最右边就结束这一行(Line)。
  2. 接下来显示指针又回到屏幕的左边从第二行开始显示,显示指针在从第一行的右边回到第二行需要一定的时间,这个过程称为行切换。
  3. 以此类推,显示指针一行一行地显示至矩形的右下角,把一幅图像(帧:frame)显示完成。

以下是LCD的时序图:
Alt text

相关的时序信号如下:

  • VSYNC:垂直同步信号,用于同步一帧的开始
  • HSYNC:水平同步信号,用于同步一行的开始
  • VCLK:像素时钟信号,用于表示像素点的时间间隔
  • VD0:LCD像素数据输出端口
  • VDEN:数据使能信号

显示过程与时序:

  1. 显示从屏幕左上角第一行的第一个点开始,一个一个点地在LCD上显示,点与点之间的时间间隔为VCLK,当显示到屏幕的最右边就结束这一行,对应时序图上的HSYNC。
  2. 接下来显示指针又回到屏幕的右边从第二行开始显示,显示指针在从第一行的右边回到第二行的左边是需要一定时间的,我们称之为行切换。
  3. 以此类推,显示指针把整幅图像显示完成,这一帧图像的显示时间在时序图上表示为VSYNC。

再参考屏幕中关于时序配置描述,如下:
Alt text
Alt text
Alt text

下面计算相关变量的值:

  1. FCLK取9MHz, FCLK即VCLK,VCLK = HCLK/(CLKVAL + 1), 而OK6410的HCLK是133MHz,计算得到CLKVAL = 14
  2. VSPW + 1 = tvp, tvp取10,则VSPW = 9
  3. VBPD + 1 = tvb,tvb取2,则VBPD = 1
  4. HSPW + 1 = thp, thp取典型值41,则HSPW = 40
  5. HBPD + 1 = thb,thb取典型值2,则HBPD = 1
  6. LINEVAL+1=272,则LINEVAL=271
  7. HOZVAL+1=480,则HOZVAL=479
  8. VFPD+1=tvf,tvf取典型值2,则VFPD=1
  9. HFPD+1=thf,thf取最小值2,则HFPD = 1

LCD程序设计

参考S3C6410的应用指南,其中关于LCD显示部分的流程图如下所示:
Alt text

对应的初始化代码如下:

/*引脚初始化*/
void lcd_port_init(void)
{
    GPICON = 0xaaaaaaaa;
    GPJCON = 0xaaaaaaaa;
}

/*lcd控制寄存器初始化*/
void lcd_control_init(void)
{
    MOFPCON &= (~(0x1 << 3)); /*SEL_BYPASS[3] must be set as '0'*/
    SPCON = 0x01; /*select LCD I/F pin configuration as RGB I/F style*/
    
    VIDCON0 = (CLKVAL << 6) | (0x1 << 4) | (0x3 << 0); /*设置时钟源及VCLK的值,VCLK = HCLK / (CLKVAL + 1)*/
    VIDCON1 = (0x1 << 5) | (0x1 << 6); /*对比屏幕的芯片手册和6410的LCD时序手册,发现HSYNC和VSYNC信号极性需要反转,VDEN不需要*/
    
    VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0); /*时钟初始化*/
    VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0);
    VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0); /*屏幕分辨率初始化*/
    
    WINCON0 = (0x1 << 16) | (0xb << 2) | (0x1 << 0); /*24bpp模式,打开半字交换*/
    
    VIDOSD0A = (LEFTTOPX << 11) | (LEFTTOPY << 0);  /*设置屏幕坐标,坐标(0,0)设置为左上角*/
    VIDOSD0B = (RIGHTBOTX << 11) | (RIGHTBOTY << 0);
    VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);
    
    VIDW00ADD0B0 = FRAME_BUFFER;
    VIDW00ADD1B0 = (FRAME_BUFFER + (LINEVAL + 1) * (HOZVAL + 1) * 4); /*注意24bpp模式每个像素占用4字节,而不是3字节,参考芯片手册14.4.4小节关于图像格式的说明*/
}

void lcd_init(void)
{
    lcd_port_init();
    lcd_control_init();
}

下面是在lcd上绘制点和绘制图片的函数,注意绘制图片时传入的图片数据用数组表示,需要用专门的软件进行生成。

void point(int row, int col, int color) 
{
    int red, green, blue;
    unsigned long *point = (unsigned long*)FRAME_BUFFER;
    red = (color>>16) & 0xff;
    green = (color>>8) & 0xff;
    blue = (color>>0) & 0xff;
    *(point + row*480 + col) = (green<<24) | (blue<<16) | red; /*从网上获取的RGB排布方式,非常奇怪*/
}

void paint_bmp(int height, int width, const unsigned char bmp[])
{
    int i,j;
    unsigned char *p = (unsigned char *)bmp;
    int blue, green,red;
    int color;
    
    for(i=0;i<height;i++) 
    {
        for(j=0;j<width;j++)
        {                            
            red = *p++;    /*注意导出图片的时候每像素的颜色排列为红/蓝/绿*/
            blue = *p++;            
            green = *p++;

            color = (red<<16)|(green<<8)|(blue<<0); 
                        
            point(i,j,color);
        }
    }
}

  • 无标签