专题16-LCD配置与使用
LCD硬件体系
OK6410使用一块4.3寸带触摸屏的TFT-LCD屏幕,内部集成驱动电路以及背光模块,其分辨率是480*272,其触摸屏是四线电阻式触摸屏。
LCD硬件体系包括LCD液晶屏、LCD驱动器、LCD控制器,其中液晶屏和驱动器往往集成在一起作为产品进行发布。LCD需要连接到ARM处理器的LCD控制器上,由LCD控制器负责提供给LCD驱动器必要的数据和控制信号。要操作LCD屏幕,就是要配置和使用LCD控制器。
LCD屏幕由一行一行的像素点构成,LCD的显示过程如下:
- 显示从屏幕左上角第一行的第一个点开始,一个一个点地在LCD上显示,当显示到屏幕的最右边就结束这一行(Line)。
- 接下来显示指针又回到屏幕的左边从第二行开始显示,显示指针在从第一行的右边回到第二行需要一定的时间,这个过程称为行切换。
- 以此类推,显示指针一行一行地显示至矩形的右下角,把一幅图像(帧:frame)显示完成。
以下是LCD的时序图:
相关的时序信号如下:
- VSYNC:垂直同步信号,用于同步一帧的开始
- HSYNC:水平同步信号,用于同步一行的开始
- VCLK:像素时钟信号,用于表示像素点的时间间隔
- VD0:LCD像素数据输出端口
- VDEN:数据使能信号
显示过程与时序:
- 显示从屏幕左上角第一行的第一个点开始,一个一个点地在LCD上显示,点与点之间的时间间隔为VCLK,当显示到屏幕的最右边就结束这一行,对应时序图上的HSYNC。
- 接下来显示指针又回到屏幕的右边从第二行开始显示,显示指针在从第一行的右边回到第二行的左边是需要一定时间的,我们称之为行切换。
- 以此类推,显示指针把整幅图像显示完成,这一帧图像的显示时间在时序图上表示为VSYNC。
再参考屏幕中关于时序配置描述,如下:
下面计算相关变量的值:
- FCLK取9MHz, FCLK即VCLK,VCLK = HCLK/(CLKVAL + 1), 而OK6410的HCLK是133MHz,计算得到CLKVAL = 14
- VSPW + 1 = tvp, tvp取10,则VSPW = 9
- VBPD + 1 = tvb,tvb取2,则VBPD = 1
- HSPW + 1 = thp, thp取典型值41,则HSPW = 40
- HBPD + 1 = thb,thb取典型值2,则HBPD = 1
- LINEVAL+1=272,则LINEVAL=271
- HOZVAL+1=480,则HOZVAL=479
- VFPD+1=tvf,tvf取典型值2,则VFPD=1
- HFPD+1=thf,thf取最小值2,则HFPD = 1
LCD程序设计
参考S3C6410的应用指南,其中关于LCD显示部分的流程图如下所示:
对应的初始化代码如下:
/*引脚初始化*/ 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); } } }
- 无标签