S3C2440自带有LCD控制器,该控制器主要有以下接口

仅仅说TFT显示器,TFT显示器的时序如下

TFT显示器的驱动是以行列的形式逐点扫描过来的,驱动时钟有三种,一种是行时钟,一种是列时钟,还有一个点时钟, VSYNC低电平期间需要扫描完一列数据, HSYNC低电平期间要写完一个点的数据,vclk负责一个点的每一位数据写入,实际上就是说,如果有a列,b行,一个点需c个VCLK时钟,那么扫描完成需要的中vclk为a*b*c(近似,中间还有一些延时时间)

可以将这个过程看作是1602的刷新过程, VSYNC为低选择一列, HSYNC为低选择一行,然后写入显示数据还需要一个数据时钟,写完之后指针自动增长,中间的等待时间是设备响应时间,在TFT上叫做同步时间,用于时钟的同步,防止时钟混乱

那么现在就有这些参数需要设置

VBPD: VSYNC与VCLK的开始同步时间

VSPW: VHYNC脉冲的高电平宽度

LINEVAL LCD面板的垂直尺寸:

VFPD: VSYNC与VCLK的结束同步时间

HBPD: HSYNC与VCLK的开始同步时间

HFPD: HSYNC与VCLK的结束同步时间

HOZVAL: 决定了LCD面板的水平尺寸

HSPW: HSYNC脉冲的高电平宽度

配置这些参数一般都依靠显示器的数据手册进行配置,我使用群创4.3寸屏幕,数据手册上显示

也就是说,确定一个DCLK时间,剩下的都可以确定了.(配置之前注意IO口功能配置GPIOC和D)

根据这张表,驱动S3C2440的步骤分为以下几步

1.      设置DCLK频率,像素比以及信号输出

2.      确定VSYC的开始同步结束同步以及高电平宽度还有尺寸

3.      3.设置HSYC的开始同步结束同步以及高电平宽度还有尺寸

4.      设置HSPW时间

5.      对于输出的图像格式进行一些选择

6.      设置LCD显示缓冲区相关的数据

然后,CPU系统就会去自动刷新屏幕(使用缓冲区数据),而我们的读出写入都针对于缓冲区,再由显示器接口写入显示器

具体设置请查看程序:

Lcd.c

#include "tftlcd.h"

volatile static unsigned short LCD_BUFFER[SCR_YSIZE_TFT][SCR_XSIZE_TFT];	//定义显示缓存区

/**************************************************************
TFT LCD功能模块初始化
**************************************************************/
void LCDInit(void)
{
//配置引脚
rGPCUP = 0x00000000;
rGPCCON = 0xaaaa02a9; rGPDUP = 0x00000000;
rGPDCON= 0xaaaaaaaa; //Initialize VD[15:8] // TFT LCD panel,16bpp TFT,ENVID=off
rLCDCON1=(CLKVAL_TFT<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0;
rLCDCON2=(VBPD<<24)|(LINEVAL_TFT<<14)|(VFPD<<6)|(VSPW);
rLCDCON3=(HBPD<<19)|(HOZVAL_TFT<<8)|(HFPD);
rLCDCON4= HSPW;
rLCDCON5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (0<<7) | (0<<6) | (1<<3) |(BSWP<<1) | (HWSWP);
//16位输出格式565,VCLK下降沿取数据等 (看数据手册)这里指定目的地址
rLCDSADDR1=(((u32)LCD_BUFFER>>22)<<21)|M5D((u32)LCD_BUFFER>>1); //单扫描
rLCDSADDR2=M5D( ((u32)LCD_BUFFER+(SCR_XSIZE_TFT*LCD_YSIZE_TFT*2))>>1 );
//LCD_WIDTH×16/16;由于是选择的16位模式,
//如果是24位模式,每个像素4字节则为LCD_WIDTH×32/16
//(LCD_WIDTH在此为LCD_XSIZE_TFT)
rLCDSADDR3=(((SCR_XSIZE_TFT-LCD_XSIZE_TFT)/1)<<11)|(LCD_XSIZE_TFT/1); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt
rTCONSEL &= (~7) ; // Disable LPC3600 rTPAL=0; // 禁止临时调色板寄存器
} /**************************************************************
* LCD视频和控制信号输出或者停止,1开启视频输出
**************************************************************/
void LCDEnvidOnOff(int onoff)
{
if(onoff==1)
rLCDCON1|=1; // ENVID=ON
else
rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
} /**************************************************************
* TFT LCD 电源控制引脚使能
* pwren=1时,允许PWREN信号
* pwren=0时,禁止PWREN信号
* invpwre=1,PWREN信号极性反转
* invpwre=0,PWREN信号极性正常
**************************************************************/
void LCDPowerEnable(int invpwren,int pwren)
{
//GPG4 is setted as LCD_PWREN
rGPGUP |= (1<<4);//GPG4上拉电阻无效
rGPGCON |= (3<<8); //GPG4=LCD_PWREN
rGPGDAT |= 1<<4 ; //GPG4置1
//invpwren=pwren;
//Enable LCD POWER ENABLE Function
if(pwren)rLCDCON5 |= 1<<3;
else rLCDCON5 &= ~(1<<3);
if(invpwren) rLCDCON5 |= 1<<5;
else rLCDCON5 &= ~(1<<5);
} /**************************************************************
TFT LCD单个象素的显示数据输出
**************************************************************/
void LCDPutPixel(u32 x,u32 y, u32 color )
{
if ( (x < SCR_XSIZE_TFT) && (y < SCR_YSIZE_TFT) )
LCD_BUFFER[(y)][(x)] = color;
} /**************************************************************
TFT LCD全屏填充特定颜色单元或清屏
**************************************************************/
void LcdClearScr( u32 color)
{
unsigned int x,y ; for( y = 0 ; y < SCR_YSIZE_TFT ; y++ )
{
for( x = 0 ; x < SCR_XSIZE_TFT ; x++ )
{
LCD_BUFFER[y][x] = color ;
}
}
}
/**************************************************************
在LCD屏幕上指定坐标点画一个指定大小的图片
**************************************************************/
void LCDPaintBmp(u16 x0,u16 y0,u16 h,u16 l,const unsigned char bmp[])
{
int x,y;
u32 c;
int p = 0; for( y = y0 ; y < l ; y++ )
{
for( x = x0 ; x < h ; x++ )
{
c = bmp[p+1] | (bmp[p]<<8) ;
if ( ( (x0+x) < SCR_XSIZE_TFT) && ( (y0+y) < SCR_YSIZE_TFT) )
LCD_BUFFER[y0+y][x0+x] = c ;
p = p + 2 ;
}
}
} /**************************************************************
*
* LCD屏初始化
*
**************************************************************/
void LcdTFTInit(void)
{
LCDInit();
LCDPowerEnable(0, 1);
LCDEnvidOnOff(1); //turn on vedio
LcdClearScr( (0x00<<11) | (0x00<<5) | (0x00) ); //565格式 纯黑色
} //在指定区域内填充指定颜色
//区域大小:
// (xend-xsta)*(yend-ysta)
void LCDFill(u16 xstart,u16 ystart,u16 xend,u16 yend,u16 color)
{
u16 i,j;
for(i = xstart;i<=xend;i++)
{
for(j = ystart; j <= yend; j++)
{
LCDPutPixel(i,j,color);
}
}
} //画线
//x1,y1:起点坐标
//x2,y2:终点坐标
void LCDDrawLine(u16 xstart, u16 ystart, u16 xend, u16 yend,u16 color)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol; delta_x=xend-xstart; //计算坐标增量
delta_y=yend-ystart;
uRow=xstart;
uCol=ystart;
if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}
if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<=distance+1;t++ )//画线输出
{
LCDPutPixel(uRow,uCol,color);//画点
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
} //画矩形
void LCDDrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
{
LCDDrawLine(x1,y1,x2,y1,color);
LCDDrawLine(x1,y1,x1,y2,color);
LCDDrawLine(x1,y2,x2,y2,color);
LCDDrawLine(x2,y1,x2,y2,color);
} //在指定位置画一个指定大小的圆
//(x,y):中心点
//r :半径
void LCDDrawCircle(u16 x0,u16 y0,u8 r,u16 color)
{
int a,b;
int di;
a=0;b=r;
di=3-(r<<1); //判断下个点位置的标志
while(a<=b)
{
LCDPutPixel(x0-b,y0-a,color); //3
LCDPutPixel(x0+b,y0-a,color); //0
LCDPutPixel(x0-a,y0+b,color); //1
LCDPutPixel(x0-b,y0-a,color); //7
LCDPutPixel(x0-a,y0-b,color); //2
LCDPutPixel(x0+b,y0+a,color); //4
LCDPutPixel(x0+a,y0-b,color); //5
LCDPutPixel(x0+a,y0+b,color); //6
LCDPutPixel(x0-b,y0+a,color);
a++;
//使用Bresenham算法画圆
if(di<0)di +=4*a+6;
else
{
di+=10+4*(a-b);
b--;
}
LCDPutPixel(x0+a,y0+b,color);
}
}

Lcd.h

#ifndef __TFTLCD_H
#define __TFTLCD_H
#include "2440addr.h"
#include "def.h" //RGB5:6:5颜色定义
#define clWhite 0xFFFF //白色
#define clBlack 0x0000 //黑色
#define clDRed 0x8000 //暗红色,为全色的一半
#define clLRed 0xF800 //亮红色
#define clDMagenta 0x8010 //暗紫色
#define clLMagenta 0xF81F //亮紫色
#define clGreen 0x07E0 //绿色
#define clDBlue 0x0010 //暗蓝色
#define clLBlue 0x001F //亮蓝色
#define clDCyan 0x0410 //暗青色
#define clLCyan 0x07FF //亮青色
#define clDYellow 0x8400 //暗黄色
#define clLYellow 0xFFE0 //亮黄色
#define clDGray 0x8410 //暗灰色
#define clLGray 0xF79E //亮灰色
#define clLArgent 0xCE79 //亮银色 #define MVAL_USED (0) //0=each frame 1=rate by MVAL
#define INVVDEN (1) //0=normal 1=inverted
#define BSWP (0) //Byte swap control
#define HWSWP (1) //Half word swap control
#define PNRMODE (3) // 设置为TFT屏
#define BPPMODE (12) // 设置为16bpp模式 //TFT_SIZE
#define LCD_XSIZE_TFT (480)
#define LCD_YSIZE_TFT (272) #define SCR_XSIZE_TFT (480)
#define SCR_YSIZE_TFT (272) #define HOZVAL_TFT (LCD_XSIZE_TFT-1)
#define LINEVAL_TFT (LCD_YSIZE_TFT-1) //Timing parameter for 4.3' LCD 实际值-1的结果
#define VBPD (1) //垂直同步信号的后肩
#define VFPD (1) //垂直同步信号的前肩
#define VSPW (7) //垂直同步信号的脉宽 #define HBPD (1) //水平同步信号的后肩
#define HFPD (1) //水平同步信号的前肩
#define HSPW (40) //水平同步信号的脉宽 #define CLKVAL_TFT (2) //时钟分频因子,VCLK = HCLK/((CLKVAL_TFT+1)*2) #define M5D(n) ((n) & 0x1fffff) //用于设置显示缓存区时,取低21位地址 void LcdTFTInit(void);
void LCDFill(u16 xstart,u16 ystart,u16 xend,u16 yend,u16 color);
void LCDDrawLine(u16 xstart, u16 ystart, u16 xend, u16 yend,u16 color);
void LCDDrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);
void LCDDrawCircle(u16 x0,u16 y0,u8 r,u16 color); #endif

注意,触摸屏不打开cache 和打开cache的速度是不同的(一个要每次去sram取指写入数组,一个直接在内部cache中写入数据),但是打开了cache之后用到延时函数的的驱动可能会遭遇到延时时间大大缩短导致设备驱动不起来的情况(比如at24c02,写入读出太快,设备反应不过来,设备没反应,驱动包错)

S3C2440 TFTLCD驱动详解的更多相关文章

  1. S3C2440触摸屏驱动详解

    2440的触摸屏转换接口搭载在ADC接口之上,使用上比ADC接口多了一些花样,首先,触摸屏接口有几种转换模式 1. 普通转换模式 单转换模式是最合适的通用ADC转换.此模式可以通过设置ADCCON(A ...

  2. linux usb 驱动详解

    linux usb 驱动详解 USB 设备驱动代码通过urb和所有的 USB 设备通讯.urb用 struct urb 结构描述(include/linux/usb.h ). urb 以一种异步的方式 ...

  3. 25.Linux-Nor Flash驱动(详解)

    1.nor硬件介绍: 从原理图中我们能看到NOR FLASH有地址线,有数据线,它和我们的SDRAM接口相似,能直接读取数据,但是不能像SDRAM直接写入数据,需要有命令才行 1.1其中我们2440的 ...

  4. 16.Linux-LCD驱动(详解)

    在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构体: framebuffer_alloc(); 2) 设置fb_info 3) 设置硬件相关的操作 ...

  5. 使用VS2010编译MongoDB C++驱动详解

    最近为了解决IM消息记录的高速度写入.多文档类型支持的需求,决定使用MongoDB来解决. 考虑到MongoDB对VS版本要求较高,与我现有的VS版本不兼容,在leveldb.ssdb.redis.h ...

  6. 16.Linux-LCD驱动(详解)【转】

    转自:https://www.cnblogs.com/lifexy/p/7604011.html 在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构 ...

  7. 18.Llinux-触摸屏驱动(详解)

    本节的触摸屏驱动也是使用之前的输入子系统 1.先来回忆之前第12节分析的输入子系统 其中输入子系统层次如下图所示, 其中事件处理层的函数都是通过input_register_handler()函数注册 ...

  8. 18.Llinux-触摸屏驱动(详解)【转】

    转自:https://www.cnblogs.com/lifexy/p/7628889.html 本节的触摸屏驱动也是使用之前的输入子系统 1.先来回忆之前第12节分析的输入子系统 其中输入子系统层次 ...

  9. 13.Linux键盘驱动 (详解)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的 ...

随机推荐

  1. 在win7 64bit系统安装QC软件

    当本机系统不再QC软件支持的系统上,可以在setup右键选择兼容性选择能支持安装的系统, 在JBOSS页面,选择该服务器,用户名输入本机的用户名和密码,如果没有配置域输入计算机名. 如果没有装IIS, ...

  2. haxe 配置

    安装所有类库: 命令提示符 haxelib install 类库名 如:haxelib install openfl 配置安卓: 命令提示符 haxelib run openfl setup andr ...

  3. Class.forName() 初始化、Thread.currentThread().getContextClassLoader().getResourceAsStream

    Class.forName() 和 ClassLoader.loadClass()的区别? Class.forName() 和 Class.forName().NewInstance()的区别? Cl ...

  4. jquery_api事件(二)

    1.hover 一个模仿悬停事件的方法.它为频繁使用的任务提供了一种“保持在其中”的状态. 当鼠标移动到一个匹配的元素上面时,会触发指定的第一个函数.当鼠标移出这个元素时,会触发指定的第二个函数.而且 ...

  5. Python -- OOP高级 -- __slots__、@property

    __slots__属性可以设置 允许被设置的属性 class Student: __slots__ = ("name", "age") >>> ...

  6. Xshell无法连接虚拟机中的Ubuntu

    遇到问题: VAWare中安装了Ubuntu-Desktop,Xshell连接失败 解决办法: 首先确认虚拟Ubuntu可以正常联网 可能原因是没有安装openssh服务 sudo apt-get i ...

  7. 转:LoadRunner获取毫秒及字符串替换实现

    今天做一个性能测试,参数化要求创建用户名不可以重复,想来想不没有什么好的办法来避免用户名字的重复.所以就想用时间+随机数来实现,但是实现中遇到一个问题. 名字中不可以包含.这个特殊的字符的.所以要处理 ...

  8. Issue 5158: Modal dialog present (UnexpectedAlertOpen) issue in IE (Similar issue like 3360)

    https://code.google.com/p/selenium/issues/detail?id=5158   Reported by mailtopa...@gmail.com, Feb 13 ...

  9. C++:bitset类的使用

    #include <iostream> #include <bitset> using namespace std; int main() { //初始化一个bitmap , ...

  10. url拼凑示例(具体拼凑规则由服务器定)

    请求一页的所有数据: // http://127.0.0.1:8090/home?index=0&name=zhangsan&age=20 String url = HttpHelpe ...