(详细的实验代码,在这里:https://github.com/elvinsys/arm_tq2440/tree/master/1_uboot/1-16.lcd)
一、 LCD的工作原理解析
1. LCD硬件体系结构
1.1 液晶的概念
属于一种有机化合物,分子形态为长棒状,在不同的电流作用下,分子会做有规律的旋转,对光线产生一定的控制形成一个像素,而多个像素构成完整的图像。
1.2 分类:STN、GF、TFD、还有常用的TFT
1.3 LCD驱动芯片
是用来控制液晶分子发生变化的模块,它为液晶分子的偏转提供电压。
1.4 LCD控制器(参考2440芯片手册中的LCD Controller一节 图15-1)
为LCD驱动芯片提供必需的数据和控制信号
LCD 数据、控制、时钟 LCD
控制器————————————> 驱动芯片
REGBANK包括:17个 R/W REGISTER
256 X 16 的调色板内存
LCDCDMA:把帧内存的视频数据传送到LCD驱动器的专用DMA通道
VIDPRCS:接受来自LCDCDMA的数据,将数据转换格式。(如4/8位单扫或4位双扫显示)
TIMEGEN:生成LCD控制信号,如:VSYNC、HSYNC、VCLK和LEND等信号
2. LCD显示与信号
2.1 显示流程
2.1.1 从第一行第一个点,到第一行最后一个点
2.1.2 显示指针回到下一行第一个点的时间称为切换时间
2.1.3 显示完一副图像,一帧显示完成
2.2 时序信号(参考15-6,TFT LCD Timing Example)
VSYNC |
垂直同步信号 |
HSYNC | 水平同步信号 |
VCLK | 像素时钟信号 |
VD[23:0] | LCD像素数据输出端口 |
VDEN | 数据使能信号 |
LEND | 行结束信号 |
二、 基于S3C2440的LCD驱动程序设计
大概的步骤如下:
1. LCD初始化
1.1 引脚初始化
1.2 时序初始化
1.3 帧缓冲初始化
1.4 杂项初始化
2. LCD图像显示
2.1 数据显示
2.2 单色显示
1.LCD初始化
1.1 引脚初始化(touch lcd.c,记得把lcd.o丢进dev/Makefile里面)
(查看原理图可知,LCD的VD0~VD23分别对应GPC8-GPC15,GPD0-GPD15),因此配置一下寄存器:
GPCCON R/W 0x5600 0020 ——> 0xaaaa aaaa
GPDCON R/W 0x5600 0030 ——> 0xaaaa aaaa
创建函数——void lcd_port_init();
1.2 时序初始化
查看原理图,参考15-6图可知,需要被初始化的时序信号如下:
VSPW | HSPW | CLKVAL |
VFPD | HFPD | LINEVAL |
VBPD | HBPD | HOZVAL |
上面信号的寄存器位置如下,创建函数——void lcd_control_init();
LCDCON1 | R/W | 0x4d00 0000 |
CLKVAL | [17:8] | |
LCDCON2 | R/W | 0x4d00 0004 |
VBPD | [31:24] | |
LINEVAL | [23:14] | |
VFPD | [13:6] | |
VSPW | [5:0] | |
LCDCON3 | R/W | 0x4d00 0008 |
HBPD | [25:19] | |
HOZVAL | [18:8] | |
HFPD | [7:0] | |
LCDCON4 | R/W | 0x4d00 000c |
HSPW | [7:0] |
按照时序信号的值,计算出需要初始化寄存器的值(参考4.3寸屏手册中7.1表和2440手册LCDCON0)
DCLK = VCLK = HCLK / [ ( CLKVAL +1 ) X 2 ] = 10
HCLK = 100, 故 CLKVAL = 4
(参考2440的4.3寸屏手册和15-6图)
VSPW +1 =10 故 VSPW = 9
VBPD +1 = 2 故 VBPD = 1
VFPD +1 = 2 故 VFPD = 1
HSPW + 1 = 41 故 HSPW = 40
HBPD + 1 = 2 故 HBPD = 1
HFPD +1 = 2 故 HFPD = 1
LINEVAL + 1 = 272 故 LINEVAL = 271
HOZVAL +1 = 480 故 HOZVAL = 479
1.3 帧缓冲初始化 (272行 X 480列) X 2字节
unsigned short LCDBUFFER[272][480];
typedef unsigned int U32;
typedef unsigned short U16;
typedef unsigned char U8;
把LCD帧缓冲区地址填装进LCD Controller里面
LCDSADDR1 R/W 0x4d00 0014
LCDBANK [29:21] :放BUFFER地址的[30:22]
LCDBASEU [20:0] :放地址的[21:1]
具体代码为:LCDSADDR1 = (((U32)LCDBUFFER>>22)<<21) | (((U32)LCDBUFFER>>1)&0x1fffff);
LCDSADDR2 R/W 0x4d00 0018
LCDBASEL [20:0] :因为是single scan LCD,故存放的是结束地址[21:1]
具体代码为:LCDSADDR2 = (((U32)LCDBUFFER + 272 * 480 *2) >> 1) &0x1fffff;
LCDSADDR3 R/W 0x4d00 001c
OFFSIZE [21:11] :两个像素点的距离为0
PAGEWIDTH [10:0] :半字页宽为480 *2 / 2
具体代码为:LCDSADDR3 = (0 << 11) | (480 * 2 / 2 );
1.4 杂项初始化
LCDCON1
PNRMODE [6:5] : 1 = TFT LCD
BPPMODE [4:1] : 1100 = 16 BPP TFT
ENVID [0] : 0 = Disable LCD (关闭LCD Controller)
LCDCON5 R/W 0x4d00 0010
FRM565 [11] : 1 = 5 : 6 : 5 format (RGB)
INVVLINE [9] : 1 = lnverted //极性相反
INVVD [8] : 1 = lnverted //极性相反
HWSWP [0] : 1 = Swap Enable 半字转换
TPAL R/W 0x4d00 0050 临时调色板
TPALEN [24] : 0 = DISABLE //暂时关闭
直接TPAL = 0
1.5 建立函数——void led_init(), 并添加到main.c中
1.5.1 把lcd_port_init() 和 lcd_control_init() 加到main.c里面
1.5.2 打开LCD 电源:LCD_PWR : GPG4
GPGON R/W 0x5600 0060
GPG4 [9:8] : 11 = LCD_PWRDN
LCDCON5 R/W
PWREN [3] : 1 = ENABLE PWREN
LCDCON1 R/W
ENVID [0] : 1 = ENABLE OUTPUT
2. LCD图形显示
2.1 数据显示
建立——void point(U32 x, U32 y, U32 color) 用来画一个点(参考2440手册15-18:VD Pin D at 16BPP 5:6:5)提取red、green、blue,具体代码如下:
void print_point(U32 x, U32 y, U32 color)
{
U32 red, green, blue;
red = ((color>>19)&0x1f);
green = ((color>>10)&0x3f);
blue = ((color>>3)&0x1f);
LCDBUFFER[y][x] = (unsigned short)((red<<11)|(green<<5)|(blue<<0));
}
建立测试函数——void lcd_test(); 用来画一行线
void print_line(U32 y, U32 color)
{
int i;
for(i=0;i<480;i++)
print_point(i,y,color);
}
在LCD上显示一张图的函数:
void print_picture(U16 x0, U16 y0, U16 wide, U16 high, const U8 *bmp)
{
U16 x, y, c;
U32 p = 0;
for(y = y0; y < y0+high; y++)
{
for (x = x0; x < x0+wide; x++)
{
c = (bmp[p] | (bmp[p+1]<<8));
if((x<480)&&(y<272))
LCDBUFFER[y][x] = c;
p = p + 2;
}
}
}
/* 把一张位图转换成一个bmp.c的数组文件,可利用工具Img2Lcd进行转换,
把bmp.c丢在dev目录下,修改Makefile,把bmp.c中的数组名修改为bmp,
在lcd.c中加入extern unsigned char bmp[90200],在lcd_test中加入Paint_Bmp(0,0,220,220,bmp);
2.2 单色显示(利用临时调色板)
TPAL R/W 0x4d00 0050
TPALEN [24] 1 : ENABLE //启动调色板
TPALVAL [23:0]
[23:16 ] red
[15:8 ] green
[7:0 ] blue
具体代码如下:
void clearSrc(U32 color)
{
TPAL = (1<<24)|(color&0xffffff);
}