本节来学习裸机下的LCD 驱动,本节学完后,再来学习Linux下如何使用LCD驱动
Linux中的LCD驱动,链接如下:
(Linux-LCD层次分析链接:http://www.cnblogs.com/lifexy/p/7603327.html)
(Linux-LCD驱动分析链接:http://www.cnblogs.com/lifexy/p/7604011.html)
横屏4.3寸LCD为480*272(行:480个像素点 列:272个行)
1.LCD原理图 :
Pin1- Pin6:Von/ Voff 电源正/负(由GPG4控制,高电平有效)
Pin2:VM/VDEN 数据使能信号 (0:表示正在跳行,1:表示可以传输像素数据)
Pin8:VLINE/HSYNC 水平同步信号(每扫完一行,即发一次水平同步信号)
Pin28:VFRAME/VSNC 垂直同步信号(每扫完一屏,即发一次垂直同步信号)
Pin30:VLCK 时钟信号
Pin42,Pin45 LED+,LED- 背光显示开关 (由0:off 1:no)
VD23~VD19:R信号
VD15~VD10:G信号
VD7~VD3 :B信号
数据是采用16Bpp像素,RGB565格式(因为LCD控制器不支持18Bpp格式)
例如:粉色RGB值分别为209,92,174(11010001,01011100,10101110)
数据从高位往下取,R和B取5位,G取6位,那么值为0XD2F5。
565RGB引脚连接图如下:
1.2配置引脚
1 GPCUP = 0xffffffff; // 禁止内部上拉
2 GPCCON = 0xaaaaaaaa; // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
3 GPDUP = 0xffffffff; // 禁止内部上拉
4 GPDCON = 0xaaaaaaaa; // GPIO管脚用于VD[23:8]
5 GPBCON &= ~(GPB0_MSK); // Power enable pin
6 GPBCON |= GPB0_out;
7 GPBDAT &= ~(1<<0); // Power off
2.设置LCDCON1~5控制寄存器
2.1BSWP和HWSWP介绍
更改存储格式,对于16bppRGB565(高数据在后)来说,BSWP=0, HWSWP=1
2.2查看2440中LCD控制器初始状态时序图:
VSPW: 垂直同步脉冲宽度 pulse widch
VBPD: 垂直脉冲后沿延迟(用来等待LCD模块响应的时间) back delay
VFPD: 垂直脉冲前沿延迟(用来等待LCD模块响应的时间) Front delay
HSPW: 行同步脉冲宽度 pulse widch
HBPD: 行脉冲后沿延迟(用来等待LCD模块响应的时间) back delay
HFPD: 行脉冲前沿延迟(用来等待LCD模块响应的时间) Front delay
LINEVAL:行数,用来决定垂直尺寸,对于4.3寸时,LINEVAL=272-1
HOZVAL:行数,用来决定水平像素点个数,对于4.3寸时,HOZVAL=480-1
2.3 查看 LCD芯片手册时序图,计算周期时间:
从上图2中得到时钟周期为10Mhz(100ns)
通过图1和图3计算出:
HSPW+1=T7=5 clock
HFPD+1=T8-T11=11 clock
HBPD+1=T6-T7-T8=17 clock
VSPW+1=T1=1 Line
VFPD+1=T2-T5=2 Line
VBPD+1=T0-T2-T1=4 Line
2.4 配置LCDCON1~5
根据上面就先来定义全局变量:
#define HSPW_16bpp 5-1 #define HFPD _16bpp 11-1 #define HBPD _16bpp 17-1 #define VSPW _16bpp 1-1 #define VFPD _16bpp 2-1 #define VBPD _16bpp 4-1
设置LCDCON1寄存器:
CLKVAL[17:8]:
设置VCLK时钟, CLKVAL =HCLK/(LCD时钟*2)-1
本裸板的HCLK=100Mhz,LCD时钟=10MHZ,所以CLKVAL =4
PNRMODE [6:5]:
设置为TFT模式,PNRMODE =0x3
BPPMODE[4:1]:
设置为16BPP, BPPMODE=0x0C
ENVID [0]:
控制PWREN信号(GPG4)输出,先配置好再输出PWREN, ENVID =0
(开启之前应该设置LCDCON5位[3]允许PWREN信号才有效)
设置LCDCON2寄存器:
VBPD [31:24]:垂直脉冲后沿延时, VBPD=VBPD_16bpp;
LINEVAL[23:14]:垂直行数,决定垂直大小, LINEVAL=272-1;
VFPD[13:6]:垂直脉冲前沿延时, VFPD= VFPD_16bpp;
VSPW[5:0]:垂直同步脉冲宽度, VSPW= VSPW_16bpp;
设置LCDCON3寄存器:
HBPD[25:19]:水平脉冲后沿延时, HBPD= HBPD_16bpp;
HOZVAL[18:8]:水平像素点个数, HBPD= 479;
HFPD[7:0]:水平脉冲前沿延时, HFPD= HFPD_16bpp;
设置LCDCON4寄存器:
HSPW[7:0]:水平同步脉冲宽度, HSPW = HSPW_16bpp;
设置LCDCON5寄存器:
FRM565[11]:设置16bpp输出格式, FRM565=1(RGB565);
INVVCLK[10]:设置VCLK记性,LCD手册如下,所以等于0,不设置(下降沿读取数据)
INVVLINE [9]:HSYNC水平同步信号反转, 因为LCD手册和2440手册不一样,所以INVVLINE=1;
INVVFRAME[8]:VSYNC垂直同步信号反转, 因为LCD手册和2440手册不一样,所以INVVFRAME =1;
INVVFRAME[3]:PWREN信号(GPG4)允许位,=0,不设置,等设置了缓存寄存器后才设置
HWSWP [0]:更改存储格式,这里HWSWP=1,BSWP[1]默认等于0,使我们的LCD像素显示从低到高排列
代码如下:
LCDCON1 = (4<<8) | (0X3<<5) | (0x0C <<1) | (0<<0);
LCDCON2 = ((VBPD_16bpp)<<24) | (271<<14) | ((VFPD_16bpp)<<6) |((VSPW_16bpp)<<0);
LCDCON3 = ((HBPD_16bpp)<<19) | (479<<8) | ((HFPD_16bpp));
LCDCON4 = (HSPW_16bpp);
LCDCON5 = (1<<11) | (1<<9) | (1<<8) | (1<<0);
LCDCON1 &=~(1<<0); // 关闭PWREN信号输出
LCDCON5 &=~(1<<3); //禁止PWREN信号
3.设置LCDSADDR1~3缓冲地址寄存器
设置LCDSADDR1寄存器:
LCDBANK[29:21]:
保存缓冲起始地址A[30:22]
LCDBASEU[20:0]:
保存缓冲起始地址A[21:1]
设置LCDSADDR2寄存器:
LCDBASEL[20:0]:
保存存缓冲结束地址A[21:1],这里我们 采用4.3寸LCD,所以等于((0x30400000+(480)*(272)*2)>>1)&0x1fffff; 这里*2是代表一个像素占了2字节,若是8bpp模式,则就不需要乘以2
设置LCDSADDR3寄存器:
OFFSIZE[21:11]:
保存LCD上一行结尾和下一行开头的地址之间的差(半字数为单位),我们使用的是连续地址,所以不设置,默认为0
PAGEWIDTH [10:0]:
保存LCD一行占的宽度(半字数为单位),我们每个像素点是半字数,所以等于480
代码如下:
1 LCDSADDR1 = ((0x30400000>>22)<<21) | ((0x30400000>>1)& 0x1fffff);
2 LCDSADDR2 = ((0x30400000+(480)*(272)*2)>>1)& 0x1fffff;
3 LCDSADDR3 = (0<<11) | (480*2/2);
4.允许并输出PWREN信号
GPGCON = (GPGCON & (~(3<<8))) | (3<<8); // GPG4用作LCD_PWREN GPGUP = (GPGUP & (~(1<<4))) | (1<<4); // 禁止内部上拉 LCDCON5 = (LCDCON5 & (~(1<<5))) | (0<<5); // 设置LCD_PWREN的极性: 正常 LCDCON5 = (LCDCON5 & (~(1<<3))) | (1<<3); // 允许LCD_PWREN信号输出 LCDCON1 |= 1; //输出LCD_PWREN信号
5.驱动LCD显示白色
fb_base_addr=0x30400000; //缓存起始地址
LCDCON1 |= 1; // 使能LCD驱动
GPBDAT |= (1<<0); // 开背光
color=0xffffff; //显示白色颜色
for (y = 0; y < 272; y++) //向缓存地址里存数据
for (x = 0; x < 480; x++)
{
UINT16 *addr = (UINT16 *)fb_base_addr + (y * 480 + x); //定义指针变量等于缓存地址
red = (color >> 19) & 0x1f;
green = (color >> 10) & 0x3f;
blue = (color >> 3) & 0x1f;
color = (red << 11) | (green << 5) | blue; // 格式5:6:5
*addr = (UINT16) color; //addr表示缓存地址,*addr表示缓存地址里的变量,
}
LCDCON1 &= 0x3fffe; // 失能LCD驱动
GPBDAT &= ~(1<<0); // 关背光
6.TPAL临时调色板寄存器介绍
当清屏时,可以使用TPAL寄存器,快速清屏
位[24] TPAL使能位
位[23:0] RGB数据位
例如: TPAL=0x1ffffff (使能TPAL寄存器,并设为白色屏)