S3C2410 下LCD 驱动程序移植及GUI 程序编写
- 格式:pdf
- 大小:449.03 KB
- 文档页数:16
基于ARM9处理器S3C2410的LCD显示系统设计,ARM处理器,S3C2410,
TFT-LCD,显示控制
引言S3C2410是三星公司生产的基于ARM920T内核的RISC微处理器,其主频可达203MHz[1],适用于信息家电、PDA、手持设备、移动终端等领域,本文介绍了基于S3C2410的显示系统的硬件电路及驱动软件设计方法。
TFT-LCD模块的时序要求本显示模块选用的LQ080V3DG01是Sharp公司的TFT-LCD器件,该器件的分辨率为640×480,控制时序图如图1所示,时间参数如表1所列[2]。
引言
S3C2410是三星公司生产的基于ARM920T内核的RISC微处理器,其主频可达203MHz[1],适用于信息家电、PDA、手持设备、移动终端等领域,本文介绍了基于S3C2410的显示系统的硬件电路及驱动软件设计方法。
TFT-LCD模块的时序要求
本显示模块选用的LQ080V3DG01是Sharp公司的TFT-LCD器件,该器件的分辨率为640×480,控制时序图如图1所示,时间参数如表1所列[2]。
S3c2410 Linux下LCD驱动详解一实验内容简要描述1.实验目的学会驱动程序的编写方法,配置S3C2410的LCD驱动,以及在LCD屏上显示包括bmp和jpeg两种格式的图片2.实验内容(1)分析S3c2410实验箱LCD以及LCD控制器的硬件原理,据此找出相应的硬件设置参数,参考xcale实验箱关于lcd的设置,完成s3c2410实验箱LCD的设置(2)在LCD上显示一张BMP图片或JPEG图片3.实验条件(软硬件环境)PC机、S3C2410开发板、PXA255开发板二实验原理1. S3C2410内置LCD控制器分析1.1 S3C2410 LCD控制器一块LCD屏显示图像,不但需要LCD驱动器,还需要有相应的LCD控制器。
通常LCD 驱动器会以COF/COG的形式与LCD 玻璃基板制作在一起,而LCD控制器则由外部电路来实现。
而S3C2410内部已经集成了LCD控制器,因此可以很方便地去控制各种类型的LCD屏,例如:STN和TFT屏。
S3C2410 LCD控制器的特性如下:(1)STN屏支持3种扫描方式:4bit单扫、4位双扫和8位单扫支持单色、4级灰度和16级灰度屏支持256色和4096色彩色STN屏(CSTN)支持分辩率为640*480、320*240、160*160以及其它规格的多种LCD(2)TFT屏支持单色、4级灰度、256色的调色板显示模式支持64K和16M色非调色板显示模式支持分辩率为640*480,320*240及其它多种规格的LCD对于控制TFT屏来说,除了要给它送视频资料(VD[23:0])以外,还有以下一些信号是必不可少的,分别是:VSYNC(VFRAME):帧同步信号HSYNC(VLINE):行同步信号VCLK :像数时钟信号VDEN(VM):数据有效标志信号由于本项目所用的S3C2410上的LCD是TFT屏,并且TFT屏将是今后应用的主流,因此接下来,重点围绕TFT屏的控制来进行。
Linux的LCD驱动源码分析及移植Linux的LCD驱动源码分析及移植(三部曲)第一部分:基于ARM9处理器的linux-2.6.32.2操作系统内核移植手记part5.1(LCD驱动源码分析及移植之platform device)1.与LCD控制器硬件相关的寄存器内容请参照三星S3C2440A技术手册中的第15章。
2. LCD Controller的平台设备定义如下(文件位于linux/arch/arm/plat-s3c24xx/devs.c):1./* LCD Controller */2.3.static struct resource s3c_lcd_resource[] = {4. [0] = {5. .start = S3C24XX_PA_LCD,6. .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,7. .flags = IORESOURCE_MEM,8. },9. [1] = {10. .start = IRQ_LCD,11. .end = IRQ_LCD,12. .flags = IORESOURCE_IRQ,13. }14.15.};16.17.static u64 s3c_device_lcd_dmamask = 0xffffffffUL;18.19.struct platform_device s3c_device_lcd = {20. .name = "s3c2410-lcd",21. .id = -1,22. .num_resources = ARRAY_SIZE(s3c_lcd_resource),23. .resource = s3c_lcd_resource,24. .dev = {25. .dma_mask = &s3c_device_lcd_dmamask,26. .coherent_dma_mask = 0xffffffffUL27. }28.};29.30.EXPORT_SYMBOL(s3c_device_lcd);平台设备的结构体定义为s3c_device_lcd,该设备在平台总线中的名字取为s3c2410-lcd,该平台设备申请的两个板级资源为以S3C24XX_PA_LCD为起始的IORESOURCE_MEM资源和一个定义为IRQ_LCD的IORESOURCE_IRQ资源。
ARM S3C2410驱动TFT-LCD的研究技术分类:嵌入式系统 | 2008-03-07来源:电子开发网 | 作者:张义磊介绍了S3C2410的LCD控制器的数据和控制管脚,并给出了LCD的控制流程和TFT-LCD 的控制器设置规则。
参照TFT-LCD CJM10C0101的逻辑要求和时序要求设计了其驱动电路,设置了各主要LCD寄存器。
开发了CJM10C0101在嵌入式LINUX下的显示驱动程序,并在CJM10C0101上显示了清晰稳定的画面。
实验表明这套装置通用性好,能驱动大部分的TFT-LCD;可移植性强,经过少许修改即可应用在其他嵌入式系统中。
它是S3C2410驱动TFT-LCD的一套较佳的解决方案。
1 引言随着科技的发展,ARM在社会各个方面的应用越来越广。
S3C2410是三星公司生产的基于ARM920T内核的RISC微处理器,主频可达203MHz,适用于信息家电、SmartPhone、Tablet、手持设备、移动终端等领域。
其中,集成的LCD控制器具有通用性,可与大多数的LCD显示模块接口。
CJM10C0101是一种用非晶硅TFT作为开关器件的有源矩阵液晶显示器,该模块包括TFT-LCD显示屏!驱动电路和背光源,其接口为TTL电平。
分辨率为640×480像素,用18bit 数据信号能显示262144色。
6点视角是最佳视角。
在以三星ARM芯片S3C2410为核心,USB、UART、LCD、TOUCHPANEL等作为输入输出设备,FLASH和SDRAM作存储器,加上固化在FLASH里面的嵌入式LINUX组成的嵌入式系统中,我们致力于使此系统用本国生产的TFT-LCD作显示输出,因此研究设计了驱动CJM10C0101型26.4cm(10.4in)TFTLCD的硬件适配电路与嵌入式LINUX下的显示驱动程序。
2 S3C2410 LCD控制器介绍2.1 管脚S3C2410 LCD控制器用于传输视频数据和产生必要的控制信号,像VFRAME、VLINE、VCLK、VM等等。
S3C2410触摸屏驱动程序原理图本文介绍了基于三星S3C2410X微处理器,采用SPI接口与ADS7843触摸屏控制器芯片完成触摸屏模块的设计。
具体包括在嵌入式Linux操作系统中的软件驱动开发,采用内核定时器的下半部机制进行了触摸屏硬件中断程序设计,采用16个时钟周期的坐标转换时序,实现触摸点数据采集的方法,给出了坐标采集的流程。
设计完成的触摸屏驱动程序在博创公司教学实验设备UP-NETARM2410-S平台上运行效果良好。
引言随着信息家电和通讯设备的普及,作为与用户交互的终端媒介,触摸屏在生活中得到广泛的应用。
如何在系统中集成触摸屏模块以及在嵌入式操作系统中实现其驱动程序,都成为嵌入式系统设计者需要考虑的问题。
本文主要介绍在三星S3C2410X微处理器的硬件平台上进行基于嵌入式Linux的触摸屏驱动程序设计。
硬件实现方案SPI接口是Motorola推出的一种同步串行接口,采用全双工、四线通信系统,S3C2410X是三星推出的自带触摸屏接口的ARM920T内核芯片,ADS7843为Burr-Brown生产的一款性能优异的触摸屏控制器。
本文采用SPI接口的触摸屏控制器ADS7843外接四线电阻式触摸屏,这种方式最显著的特点是响应速度更快、灵敏度更高,微处理器与触摸屏控制器间的通讯时间大大减少,提高了微处理器的效率。
ADS7843与S3C2410的硬件连接如图1所示,鉴于ADS7843差分工作模式的优点,在硬件电路中将其配置为差分模式。
图1触摸屏输入系统示意图嵌入式Linux系统下的驱动程序设备驱动程序是Linux内核的重要组成部分,控制了操作系统和硬件设备之间的交互。
Linux 的设备管理是和文件系统紧密结合的,各种设备都以文件的形式存放在/dev目录下,成为设备文件。
应用程序可以打开、关闭、读写这些设备文件,对设备的操作就像操作普通的数据文件一样简便。
为开发便利、提高效率,本设计采用可安装模块方式开发调试触摸屏驱动程序。
Kernel内核实验指导实验环境:宿主机:RHEL4(Linux vm-dev 2.6.9-42.ELsmp)目标机:博创经典S2410平台交叉编译器:arm-linux-gcc V3.4.1本次实验目录下存放着已经修改好的博创经典2410平台的内核源码包,将该源码包拷贝到宿主机LINUX系统中,解压至本次实验目录,配置编译生成内核uImage文件烧写到ARM设备中。
一、配置、编译内核1、建立kernel实验目录:[root@vm-dev ~]# mkdir kernel2、进入该实验目录,将kernel源码解压至该目录下:[root@vm-dev ~]# cd kernel/[root@vm-dev kernel]# lslinux-2.6.24.4.tar.bz2[root@vm-dev kernel]# tar -xjvf linux-2.6.24.4.tar.bz2[root@vm-dev kernel]# lslinux-2.6.24.4 linux-2.6.24.4.tar.bz23、进入解压后的目录linux-2.6.24.4,运行make menuconfig对内核进行配置:[root@vm-dev kernel]# cd linux-2.6.24.4[root@vm-dev linux-2.6.24.4]# make menuconfig3.1 配置系统硬件处理器:-> System Type-> S3C2410 Machines3.2 配置LCD驱动:-> Device Drivers-> Graphics support-> Support for frame buffer devices (FB [=y])配置系统启动LOGO:-> Device Drivers-> Graphics support-> Bootup logo (LOGO [=y])3.3 配置网卡驱动:-> Device Drivers-> Network device support (NETDEVICES [=y])-> Ethernet (10 or 100Mbit) (NET_ETHERNET [=y])3.4 配置文件系统支持:-> File systems-> Miscellaneous filesystemsNFS文件系统支持:-> File systems-> Network File Systems (NETWORK_FILESYSTEMS [=y])这样,内核的配置基本上就做好了。
LCD驱动程序之代码编写实现LCD驱动程序编写前⾯通过对linux内核中LCD的驱动框架进⾏了分析,弄清楚了内核中LCD的驱动框架,通过分析知道内核中已经在fbmem.c⽂件中注册了LCD这⼀类设备的字符设备驱动,向上实现了上层通⽤的访问接⼝,向下给驱动设计者预留了fb_info注册接⼝。
现在基于我们的开发板平台(JZ2240),编写适配于⾃⼰硬件的驱动程序从前⾯分析可以知道,编写LCD驱动需要驱动的编写者去完成以下内容(可参考内核中s3c2410fb.c):1)分配⼀个fb_info结构体2)根据使⽤LCD硬件特征,设置fb_info结构体的⼀些参数3)配置硬件相关操作4)注册fb_info结构体下⾯我们就开始按照这些步骤,完成LCD驱动程序的编写1、fb_info结构体介绍fb_info结构体是LCD驱动程序中最核⼼的数据结构,应⽤程序通过fbmem.c⽂件中注册的设备访问⼊⼝,找到打开设备⽂件的fb_info结构体,最终访问到硬件,fb_info结构体声明如下:struct fb_info {int node;int flags;struct fb_var_screeninfo var; /* Current var */struct fb_fix_screeninfo fix; /* Current fix */struct fb_monspecs monspecs; /* Current Monitor specs */struct work_struct queue; /* Framebuffer event queue */struct fb_pixmap pixmap; /* Image hardware mapper */struct fb_pixmap sprite; /* Cursor hardware mapper */struct fb_cmap cmap; /* Current cmap */struct list_head modelist; /* mode list */struct fb_videomode *mode; /* current mode */#ifdef CONFIG_FB_BACKLIGHT/* assigned backlight device *//* set before framebuffer registration,remove after unregister */struct backlight_device *bl_dev;/* Backlight level curve */struct mutex bl_curve_mutex;u8 bl_curve[FB_BACKLIGHT_LEVELS];#endif#ifdef CONFIG_FB_DEFERRED_IOstruct delayed_work deferred_work;struct fb_deferred_io *fbdefio;#endifstruct fb_ops *fbops;struct device *device; /* This is the parent */struct device *dev; /* This is this fb device */int class_flag; /* private sysfs flags */#ifdef CONFIG_FB_TILEBLITTINGstruct fb_tile_ops *tileops; /* Tile Blitting */#endifchar __iomem *screen_base; /* Virtual address */unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */void *pseudo_palette; /* Fake palette of 16 colors */#define FBINFO_STATE_RUNNING 0#define FBINFO_STATE_SUSPENDED 1u32 state; /* Hardware state i.e suspend */void *fbcon_par; /* fbcon use-only private area *//* From here on everything is device dependent */void *par;};可以看到fb_info的结构体⽐较复杂,它的肯定是为了抽象出所有LCD硬件⽽设计的,但我们不需要去了解每⼀个成员变量的功能和使⽤⽅法。
24402410LCD显示屏驱动程序u-boot早就支持framebuffer了,不光显示图片,还可以把控制台重定向到lcd上,只是24x0部分缺代码罢了,需要填充一个结构体,可以从openmoko那里copy过来。
不过如果只是为了显示一张图片的话……初始化lcd控制器的代码随便放哪里运行都可以的吧!2440&2410 LCD显示屏驱动程序#include "config.h"// GPB1/TOUT1 for Backlight control(PWM)#define GPB1_TO_OUT() (rGPBUP &= 0xfffd, rGPBCON &= 0xfffffff3, rGPBCON |= 0x00000004)#define GPB1_TO_1() (rGPBDAT |= 0x0002)#define GPB1_TO_0() (rGPBDAT &= 0xfffd)//extern void Uart_Printf(char *f, ...) ;extern unsigned char __CHS[];extern unsigned char __VGA[];//volatile staticunsigned short LCD_BUFFER[SCR_YSIZE_TFT][SCR_XSIZE_TFT];static void Lcd_PowerEnable(int invpwren,int pwren);static void Lcd_Init(void){rGPCUP = 0x00000000;rGPCCON = 0xaaaa02a9;// rGPDUP=0xffffffff; // Disable Pull-up registerrGPDUP = 0x00000000;rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]rLCDCON1=(CLKVAL_TFT << 8)|(MVAL_USED << 7)|(3 <<5 )|(12 << 1)|0;// TFT LCD panel,16bpp TFT,ENVID=offrLCDCON2=(VBPD << 24)|(LINEVAL_TFT << 14)|(VFPD << 6)|(VSPW); rLCDCON3=(HBPD << 19)|(HOZVAL_TFT << 8)|(HFPD);rLCDCON4=(MVAL << 8)|(HSPW);#if(LCD_TYPE == PT035)rLCDCON5 = (1 << 11) | (1 << 10) | (0 << 9) | (0 << 8) | (1 << 7) | (1 << 6)| (1 << 3) |(BSWP << 1) | (HWSWP);#elif(LCD_TYPE == WD_F3224)rLCDCON5 = (1 << 11) | (1 << 10) | (0 << 9) | (0 << 8) | (0 << 7) | (0 << 6)| (1 << 3) |(0 << 1) | (HWSWP);#elif(LCD_TYPE == TX11D)rLCDCON5 = (1 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (0 << 7) | (0<< 6)| (1 << 3) | (1 << 2) | (BSWP << 1) | (HWSWP);#endifrLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|M5D((U32)L CD_BUFFER>>1);rLCDSADDR2=M5D( ((U32)LCD_BUFFER+(SCR_XSIZE_TFT * LCD_YSIZE_TFT * 2)) >> 1 );rLCDSADDR3=(((SCR_XSIZE_TFT - LCD_XSIZE_TFT) / 1) << 11)|(LCD_XSIZE_TFT / 1);rLCDINTMSK|=(3); // MASK LCD Sub InterruptrTCONSEL &= (~7) ; // Disable LPC3480rTPAL=0; // Disable Temp Palette}static void Lcd_EnvidOnOff(int onoff){if(onoff == 1)rLCDCON1 |= 1; // ENVID=ONelserLCDCON1 = rLCDCON1 & 0x3fffe; // ENVID Off}static void Lcd_PowerEnable(int invpwren,int pwren){//GPG4 is setted as LCD_PWRENrGPGUP = rGPGUP & ( ~(1 << 4)) |(1 << 4); // Pull-up disable rGPGCON = rGPGCON & ( ~(3 << 8)) |(3 << 8); //GPG4=LCD_PWREN rGPGDAT = rGPGDAT | (1 << 4) ;// invpwren=pwren;//Enable LCD POWER ENABLE FunctionrLCDCON5 = rLCDCON5 & ( ~(1 << 3)) |(pwren << 3); // PWRENrLCDCON5 = rLCDCON5 & ( ~(1 << 5)) |(invpwren << 5); // INVPWREN}static void Lcd_MoveViewPort(int vx, int vy){U32 addr;SET_IF();#if (LCD_XSIZE_TFT < 32)while((rLCDCON1 >> 18) <= 1); // if x<32#elsewhile((rLCDCON1 >> 18) == 0); // if x>32#endifaddr = (U32)LCD_BUFFER + (vx * 2) + vy * (SCR_XSIZE_TFT * 2);rLCDSADDR1 = ( (addr >> 22) << 21 ) | M5D(addr >> 1);rLCDSADDR2 = M5D(((addr + (SCR_XSIZE_TFT * LCD_YSIZE_TFT * 2)) >> 1)); CLR_IF();}static void MoveViewPort(void){int vx=0,vy=0,vd=1;Uart_Printf("\n*Move the LCD view windos:\n");Uart_Printf(" press 8 is up\n");Uart_Printf(" press 2 is down\n");Uart_Printf(" press 4 is left\n");Uart_Printf(" press 6 is right\n");Uart_Printf(" press Enter to exit!\n");while(1){switch( Uart_GetKey() ){case '8':if(vy>=vd)vy-=vd;Uart_Printf("vx==,vy==\n",vx,vy);Lcd_MoveViewPort(vx,vy);break;case '4':if(vx>=vd)vx-=vd;Uart_Printf("vx==,vy==\n",vx,vy);Lcd_MoveViewPort(vx,vy);break;case '6':if(vx<=(SCR_XSIZE_TFT - LCD_XSIZE_TFT -vd))vx += vd;Uart_Printf("vx==,vy==\n",vx,vy);Lcd_MoveViewPort(vx,vy);break;case '2':if(vy<=(SCR_YSIZE_TFT - LCD_YSIZE_TFT -vd))vy += vd;Uart_Printf("vx==,vy==\n",vx,vy);Lcd_MoveViewPort(vx,vy);break;case '\r':return;default:break;}//Uart_Printf("vx==,vy==\n",vx,vy);//Lcd_MoveViewPort(vx,vy);}}void PutPixel(U32 x,U32 y, U16 c ){if ( (x < SCR_XSIZE_TFT) && (y < SCR_YSIZE_TFT) ) LCD_BUFFER[(y)][(x)] = c;}void GUI_Point(U32 x,U32 y, U16 c ){if ( (x < SCR_XSIZE_TFT) && (y < SCR_YSIZE_TFT) ) LCD_BUFFER[(y)][(x)] = c;}void Lcd_ClearScr( U16 c){unsigned int x,y ;for( y = 0 ; y < SCR_YSIZE_TFT ; y++ ){for( x = 0 ; x < SCR_XSIZE_TFT ; x++ ){LCD_BUFFER[y][x] = c ;}}}void Glib_Line(int x1,int y1,int x2,int y2,int color) { int dx,dy,e;dx = x2 -x1;dy = y2 -y1;if(dx >= 0){if(dy >= 0) // dy>=0{if(dx>=dy) // 1/8 octant{e=dy-dx/2;while(x1<=x2){PutPixel(x1,y1,color); if(e>0){y1+=1;e-=dx;} x1+=1; e+=dy;}}else // 2/8 octant{e=dx-dy/2;while(y1<=y2){PutPixel(x1,y1,color); if(e>0){x1+=1;e-=dy;} y1+=1; e+=dx;}}}else // dy<0{dy=-dy; // dy=abs(dy)if(dx>=dy) // 8/8 octant {e=dy-dx/2;while(x1<=x2){PutPixel(x1,y1,color); if(e>0){y1-=1;e-=dx;} x1+=1; e+=dy;}}else // 7/8 octant{e=dx-dy/2;while(y1>=y2){PutPixel(x1,y1,color); if(e>0){x1+=1;e-=dy;} y1-=1; e+=dx;}}}else //dx<0{dx=-dx; //dx=abs(dx)if(dy >= 0) // dy>=0 {if(dx>=dy) // 4/8 octant {e=dy-dx/2;while(x1>=x2){PutPixel(x1,y1,color); if(e>0){y1+=1;e-=dx;} x1-=1; e+=dy;}}else // 3/8 octant{e=dx-dy/2;while(y1<=y2){PutPixel(x1,y1,color); if(e>0){x1-=1;e-=dy;} y1+=1; e+=dx;}}}else // dy<0{dy=-dy; // dy=abs(dy)if(dx>=dy) // 5/8 octant {e=dy-dx/2;while(x1>=x2){PutPixel(x1,y1,color); if(e>0){y1-=1;e-=dx;} x1-=1; e+=dy;}}else // 6/8 octante=dx-dy/2;while(y1>=y2){PutPixel(x1,y1,color);if(e>0){x1-=1;e-=dy;}y1-=1;e+=dx;}}}}}void Glib_Rectangle(int x1,int y1,int x2,int y2,int color){Glib_Line(x1,y1,x2,y1,color);Glib_Line(x2,y1,x2,y2,color);Glib_Line(x1,y2,x2,y2,color);Glib_Line(x1,y1,x1,y2,color);}void Glib_FilledRectangle(int x1,int y1,int x2,int y2,int color) { int i;for(i=y1;i<=y2;i++)Glib_Line(x1,i,x2,i,color);}void Paint_Bmp(int x0,int y0,int h,int l,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 ;}}#if 1void Lcd_PutASCII(unsigned int x,unsigned int y,unsigned char ch,unsigned int c,unsigned int bk_c,unsigned int st) {unsigned short int i,j;unsigned char *pZK,mask,buf;pZK = &__VGA[ch*16];for( i = 0 ; i < 16 ; i++ ){mask = 0x80;buf = pZK[i];for( j = 0 ; j < 8 ; j++ ){if( buf & mask ){PutPixel(x+j,y+i,c);}else{if( !st ){PutPixel(x+j,y+i,bk_c);}}mask = mask >> 1;}}}void Lcd_PutHZ(unsigned int x,unsigned int y,unsigned short int QW,unsigned int c,unsigned int bk_c,unsigned int st) {unsigned short int i,j;unsigned char *pZK,mask,buf;pZK = &__CHS[ ( ( (QW >> 8) - 1 )*94 + (QW & 0x00FF)- 1 )*32 ]; for( i = 0 ; i < 16 ; i++ ){//左mask = 0x80;buf = pZK[i*2];for( j = 0 ; j < 8 ; j++ ){if( buf & mask ){PutPixel(x+j,y+i,c);}else{if( !st ){PutPixel(x+j,y+i,bk_c);}}mask = mask >> 1;}//右mask = 0x80;buf = pZK[i*2 + 1];for( j = 0 ; j < 8 ; j++ ){if( buf & mask ){PutPixel(x+j + 8,y+i,c);}else{if( !st ){PutPixel(x+j + 8,y+i,bk_c);}}mask = mask >> 1;}}}//----------------------void Lcd_printf(unsigned int x,unsigned int y,unsigned int c,unsigned int bk_c,unsigned int st,char *fmt,...){char __LCD_Printf_Buf[256];va_list ap;unsigned char *pStr = (unsigned char *)__LCD_Printf_Buf;unsigned int i = 0;va_start(ap,fmt);vsprintf(__LCD_Printf_Buf,fmt,ap);va_end(ap);while(*pStr != 0 ){switch(*pStr){case '\n' :{break;}default:{if( *pStr > 0xA0 & *(pStr+1) > 0xA0 ) //中文输出{Lcd_PutHZ( x , y , (*pStr - 0xA0)*0x0100 + *(pStr+1) - 0xA0 , c , bk_c , st);pStr++;i++;x += 16;}else //英文输出{Lcd_PutASCII( x , y , *pStr , c , bk_c , st );x += 8;}break;}}pStr++;i++;if( i > 256 ) break;}}#endifvoid Lcd_Display(void){Lcd_Init();Lcd_PowerEnable(0, 1);Lcd_EnvidOnOff(1);Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) ); #if((LCD_TYPE == PT035)||(LCD_TYPE == WD_F3224)) Paint_Bmp(0, 0, 320, 240, phone);#elif(LCD_TYPE == TX11D)Paint_Bmp(0, 0, 480, 272, LCD43_ucos);#endif}。
LCD驱动的移植及其GUI仿真如何进行,LCD数模转换现实原理及其源代码LCD字模显示程序如何设计?系统中显示部分的子程序与字模数据结构互相关联,这里将ASCII字符显示子程序和单独显示汉字字模的子程序列出来,根据这两个子程序也可以看出显示部分的显示程序实现原理。
在这个子程序中,x指的是汉字行,只能是0~3共4行;y指的是半角字符列,只能是0~15共16列,因而可以在屏幕任何一个半角字符位置上显示一个ASCII半角字符。
在处理汉字时是将汉字当作两个半角字符来处理的,显示时将一个汉字分左上、左下、右上、右下4个部分顺序显示出来,从下面的显示汉字字模子程序中可以看出这一点。
从程序中可以看出,当j=0时写的是第工个汉字的左上和左下,然后在j的循环过程中依次显示的是第一个汉字的右上、右下,第二个汉字的左上、左下,第二个汉字的右上、右下。
实际上LCD的起始页,表示起始显示的8行,也就是表示一个半角字符的上半部分。
这就是显示部分汉字的显示过程。
S3C2410 LCD 驱动程序移植及GUI程序编写:1. 为了不让大家觉枯燥,让朋友们更好的理解,我以一个实例来叙述S3C2410 下一个驱动程序的编写(本文的初始化源码以华恒公司提供的s3c2410fb.c 为基础)及简单的GUI程序的编写。
2. 拿到一块LCD,首先要将LCD的各个控制线与S3C2410 的LCD控制信号相接,当然,电源也一定要接入了,否则不亮可别找我。
另外需要注意以下几点:1)背光:对于大部分的彩色LCD一定要接背光,我们才能看到屏上的内容;2)控制信号:不同的LCD 厂商对于控制信号有不同的叫法,S3C2410 芯片手册也给出了一个信号的多个名称(图一),这就要看你们硬件工程师的功底了,图一S3C2410 手册上给出的控制信号的名称及解释这里我做一个简单的介绍:VFRAME:LCD 控制器和LCD 驱动器之间的帧同步信号。
该信号告诉LCD屏的新的一帧开始了。
2410 移植LCD 驱动主机:ubuntu 8.10 x86_64交叉编译器:/usr/local/ar m/3.3.2/bin/ar m-linux-内核:2.6.22.6LCD:SUMSANG 的L TV350QV_FOE 3.5 寸 240x320一点LCD 的知识:LCDTFT LCD 电信号部件组成:主要由背光电路和显示电路组成。
背光电路: 3.5 寸TFT LCD 背光,大都采用白光LED 作为背光源,一般由 6 个串连的白光 LED 组成(如下图),驱动电压大概20V 左右,20m A 电流左右,是一个耗电量很大的部件。
对于电池供电系统,大都采用升压型DC/DC 进行驱动,很多厂家都有推出专门针对串连白光 LED 的驱动器。
显示电路:显示电路一般由Timing Controller、Sourc e Driver、Gate Driver 组成。
有的IC 把 Timing Controller 和Sourc e Driver 集成在一起了,也有的 IC 把三个部分都集成了。
这三部分电路一般都集成在TFT LCD 模组里面了,也有的 TFT LCD 把 Tim ing Controller IC 放到外面了(如SHARP 的一些 LCD)。
SAMSUNG L TV350QV 的DRIVE R IC 是S6F2002,S6F2002 集成了Tim ing Controller、Sourc e Driver、Gate Driver 部分和电源管理部分,164RGB X 240 驱动能力,所以对于 320 X 240 QVGA 的分辨率,需要两片S6F2002。
两片S6F2002,一片作为主控制器,一片作为从控制器,正是由于LVT350QV 是有两片DRIVE R IC 驱动的缘故,如果上电时序配合不好,很容易出现显示异常(一半显示不正常,一半显示正常)。
更多的内容见http://bbs.21ic.c om/upfiles/img/200686154229590.pdf这个LTV350QV 比较特殊的是,它的初始化需要通过 spi 总线写S6F2002 内部的寄存器,有人说,LTV350QV 比较麻烦的一点是还必须要进行 SPI 设置,但这也是它比较灵活的一面。
S3C2410下LCD驱动程序移植及GUI程序编写Write by llg 著作权所有:刘利国如转载请告知作者 laoliu@ 并注明出处 1.为了不让大家觉枯燥,让朋友们更好的理解,我以一个实例来叙述S3C2410下一个驱动程序的编写(本文的初始化源码以华恒公司提供的s3c2410fb.c为基础)及简单的GUI 程序的编写。
2.拿到一块LCD,首先要将LCD的各个控制线与S3C2410的LCD控制信号相接,当然,电源也一定要接入了,否则不亮可别找我。
另外需要注意以下几点:1)背光:对于大部分的彩色LCD一定要接背光,我们才能看到屏上的内容;2)控制信号:不同的LCD厂商对于控制信号有不同的叫法,S3C2410芯片手册也给出了一个信号的多个名称(图一),这就要看你们硬件工程师的功底了,图一 S3C2410手册上给出的控制信号的名称及解释这里我做一个简单的介绍:¾VFRAME:LCD控制器和LCD驱动器之间的帧同步信号。
该信号告诉LCD 屏的新的一帧开始了。
LCD控制器在一个完整帧显示完成后立即插入一个VFRAME信号,开始新一帧的显示;¾VLINE:LCD控制器和LCD驱动器之间的线同步脉冲信号,该信号用于LCD 驱动器将水平线(行)移位寄存器的内容传送给LCD屏显示。
LCD控制器在整个水平线(整行)数据移入LCD驱动器后,插入一个VLINE信号;¾VCLK:LCD控制器和LCD驱动器之间的像素时钟信号,由LCD控制器送出的数据在VCLK的上升沿处送出,在VCLK的下降沿处被LCD驱动器采样;¾VM:LCD驱动器的AC信号。
VM信号被LCD驱动器用于改变行和列的电压极性,从而控制像素点的显示或熄灭。
VM信号可以与每个帧同步,也可以与可变数量的VLINE信号同步。
3)数据线:也就是我们说的RGB信号线,S3C2410芯片手册上都有详细的说明,由于篇幅关系,在此不一一摘录,不过需要与硬件工程是配合的是他采用了哪种接线方法,24位16位或其它。
对于16位TFT屏又有两种方式,在写驱动前你要清楚是5:6:5还是5:5:5:I,这些与驱动的编写都有关系4)要注意一下LCD的电源电压,对于手持设备来说一般都为5V或3.3V,或同时支持5V和3.3V,如果LCD的需要的电源电压是5V,那就要注意了,S3C2410的逻辑输出电压只有3.3V,此时一定要让你们的硬件工程师帮忙把S3C2410的逻辑输出电压提高到5V,否则你可能能将屏点亮,但显示的图像要等到太阳从西边出来的那一天才能正常,呵呵,我可吃过苦头的哦!5)3.3V逻辑电压转变成5V逻辑电压电路图(此图由华恒公司提供)6)最后还有一个问题,有些LCD屏还需要一颗伴侣芯片,就是S3C2410手册中的那颗LPC3600。
这可能在LCD的手册中都有论述吧,我没有遇到过这样的屏,所以也不是很清楚。
那么是不是所有的屏与S3C2410相接都需要那个讨厌的家伙呢?这是好多人(包括我)在最开始都会有的疑问,不过现在的大部分LCD屏应该都不需要这个讨厌的家伙了,屏的控制信号直接与S3C2410的控制信号相接就可以了,至少我还没有遇到过。
7)还得提醒大家一下,S3C2410到LCD屏的连线千万千万别超过0.5米,否则会给你带来麻烦,我也是吃过苦头的,LCD屏上面的部分显示任何信息都是正确的,而只有屏的底部会有时正确有时错误,折腾了好一阵,才知道是连线太长的缘故!3.好了,在硬件工程师的帮助下,硬件接好了,那就该我们做软件的干活了,编写驱动吧1)让我们首先看一下RGB数据结构的定义在s3c2410fb.c中找到如下信息这是对16位色的RGB颜色进行定义,R:G:B:I = 5:6:5:0,即我们常说的565显示方式。
呵呵,为了让有些朋友更好的理解,我多罗嗦几句,我们随便写一个16位数据的颜色数据(为了分析的方便,我把它写成二进制)RGB = 10101101 10111001根据上面的结构定义我们来分析一下RGB各是多少(因为没有透明色,我们不去分析)a)blue: {offset: 0, length: 5} 偏移量为0,长度为5,我们从那个RGB中提取出来便是“11001”b)green:{offset: 5, length: 6} 偏移量为5,长度为6,我们从那个RGB中提取出来便是101 101c)red: {offset: 11, length: 5 } 偏移量为11,长度为5,我们从那个RGB中提取出来便是10101d)我们得到了一个RGB值为13:45:200,就是这个颜色e)那么反过来,有了RGB的值我们该如何,因为RGB的有效位数都不足一个字节(8位),那我们只能忍痛割爱了,舍弃掉低位数据,代码如下记住,这段代码在GUI程序中是有用的2)对于8位色(256色)的数据结构定义这是原程序中给出的定义,我感觉有些错误,我认为应该为R:G:B = 3:3:2因为没有亲自去调适,所以没有什么发言权,希望做过这方面的朋友给我一个答案。
3)对于CSTN屏,一般都能达到12位色(4096色)的,S3C2410这颗芯片也是支持的,但是在软件方面要做的工作比较大,因为从原有的代码,我们找不到任何12位色显示的迹象,另外Linux本身好像也不支持12位色的,如果你要作的事情比较简单,那你就自己写代码吧。
我在此给出12位色的数据结构定义但是要完成12位色CSTN屏驱动程序的编写还有一些工作要做,稍后我会适当的向大家介绍。
4)接着看下面的代码,其中要修改的部分已经用绿色标出,下面分别进行介绍。
a)颜色位数bpp:16如果你的LCD屏是TFT的,那一般都可以达到16位色或24位色,这也要看硬件怎么连接了,根据情况进行设置即可;如果你的LCD屏是CSTN的,按照常规LCD手册的介绍,一般都可以支持到8位色(256色),而实际的CSTN屏的显示效果都可以达到12位色(4096色),那可有很大的区别的,如果你要选择便宜的屏又要丰富的颜色,那就费点劲,完成12位色的驱动。
b)LCD屏的宽度和高度xres: 240yres: 320这个就不用多说了,你的屏的分辨率是多少就设置成多少呗。
c)寄存器的设置,这些也不困难。
下面就让我们一起一口一口的将S3C2410的LCD寄存器统统吃掉!¾首先介绍一下我这块屏,这是日立的一块TFT屏,大小为640X240,可以支持到16位色。
¾与驱动有关的一张表图二 LCD屏资料有了这些信息,让我们看一下LCD寄存器的设置。
¾LCD控制器1LINECNT ---这是一个只读的数据,我们当然没有必要理它 CLKV AL --- 这可是一个很有用的参数,其实没必要管它后面的计算,我们可以通过实际的测试来得出一个有效的值,对于320x240的屏一般设置为7就可以了,而对于640x480的屏,该值可以小一点。
对于后面的计算公式及注释(STN: CLKVAL >= 2,TFT:CLKVAL >= 0),我不知道该如何去理解,因为在实际的应用中我点了一块640X240的CSTN屏,当我的CLKVAL = 1时才达到了一个最佳的效果,这似乎与说明书相违背,我也解释不清为什么?!PNRMODE --- 这个应该不用多做解释,大家一看都明白了,对于TFT屏,只能设置成11,而对于CSTN屏,可能需要根据实际屏的信息去设置,我遇到的屏都设置成10,即8bit单扫描模式。
对于4bit单扫描、4bit双扫描、8bit单扫描的说明在s3c2410的手册中有详细的介绍,大家可以去参考一下。
BPPMODE --- 这个参数更不用多说了吧,就是设置屏的颜色位数喽。
这些参数的设置都很简单,我给出我这块屏的定义:同时,我也给出一块CSTN屏的寄存器参数信息¾LCD控制器2对于TFT屏必须要填,至于什么意思怎么翻译,相信大家都比我的水平强,自己翻译吧。
我只说明从LCD中如何将这个值“扣”出来。
很容易,看一下图二 LCD屏资料,对比一下得出如下信息:LCD2_VBPD:Vertical vack proch 典型值为7LCD2_VFPD:Vertical front porch 典型值为4LCD2_VSPW:Vsync Valid width 典型值为2关于LINEV AL在程序的后面将会提到,此处不必理会。
经过分析,我们知道了如何设置LCD2:对于STN(CSTN)屏,这个寄存器的设置最简单,将VBPD、VFPD、VSPW都设置成Zero就可以了。
即¾LCD控制器3对于TFT屏,很容易将HBPD和HFPD找出来,如下LCD3_HBPD:Horizontal back porch 典型值为37LCD3_HFBD:Horizontal back porch 典型值为32对于HOZV AL同样会在后面提到,此处暂时不管经过分析,我们知道了如何设置LCD3:对于(STN)CSTN屏,我没有很好的理解WDLY和LINEBLANK的真正涵义,通过改变这两个参数的值,我也没有得到特别明显的差异,我一般设置为:¾LCD控制器4对于TFT屏,需要设置HSPW的值,这个在LCD手册上也很容易得到LCD4_HSPW:Hsync Valid width 典型值为5至于MV AL,我不知道是什么意思,有什么作用,我从来不动它,只取它最初的那个值13经过分析,我们知道了如何设置LCD4:对于STN(CSTN)屏,像WDLY一样,我通常不改变,因为改变了没有发现有什么作用,这是我驱动中的代码,好几块屏都一样的:¾LCD控制器5这个寄存器的看起来比较复杂,但是无外乎这几类:只读信息:VSTATUS和HSTATUS只读的东东,设置它也没用,不必理会。
TFT屏的颜色信息:BPP24BL、FRM565TFT屏的颜色信息,这个我们在LCD的硬件连接时已经提到了,根据具体的接线方式,设置信息。
控制信号的极性TFT/STN屏控制信号的极性:INVVCLK、INVVLINE、INVVFRAME、INVVD、INVPWREN、PWRENTFT屏特有的控制信号的极性:INVVDEN、INVLEND、ENLEND这些信息主要是使S3C2410的信号输出极性与LCD屏的输入极性的问题,需要根据具体的硬件进行设置,较为常见的是vline/hsync 、VFRAME/VSYNC脉冲的极性。
颜色信息的字节交换控制位:BSWP、HWSWP这两位用来控制字节交换和半字交换,主要用来大小头的问题,如果输出到屏上的汉字左右互换了,或者输出到屏上的图花屏了,可以更改这个选项。
具体涵义在S3C2410芯片手册上有详细的说明。