分类: LINUX
2008-05-06 14:20:26
基于S
下TFT液晶的驱动设计
张新健 指导教师:刘超英
请要转载的朋友注明出处,谢谢!
|
摘 要 实现了以S
关键词 S
1引言
随着现代计算机的大量普及,各类智能电脑也越来越多的显现在我们的现实生活中。LCD液晶作为重要的人机界面非常广泛的使用在各种嵌入式设备中,而linux操作系统由于其非常强的可移植性和稳定性同样也被广大的嵌入式设备开发商所采用。本设计就是基于最新的2.6内核的linux系统的底层驱动编写,研究linux下的TFT-LCD驱动(属字符设备驱动)的结构、移植、编写、加载与卸载、以及用户层的接口设计等技术。其中硬件使用三星公司开发的ARM9核嵌入式处理器——S
2 硬件实现
2.1 TFT LCD显示器原理
LCD(liquid crystal display),是一种数字显示技术,可以通过液晶和彩色过滤器过滤光源,并在平面面板上产生图像。常见的液晶显示器按物理结构分为一下四种:
l 扭曲向列型(TN)
l 超扭曲向列型(STN)
l 双层超扭曲向列型(DSTN)
l 薄膜晶体管型(TFT)
本设计采用TFT型液晶显示器。TFT-LCD是一种广泛拥有电视、笔记本电脑、监视器、手机等产品的有源矩阵液晶显示器件。TFT将点阵像素分割成红、绿、蓝三个子像素,并在其对应位置的器件内表面设置R、G、B 三个微型滤色膜,此时液晶显示器件只作为一个光阀,控制每个子像素光阀,就可以控制滤色膜透过光的通断;控制光阀的灰度等级就可以控制相应滤色膜透过光的多少;利用R、G、B这三个子像素透过的不同光量,便可以混合加色实现极为丰富的彩色。如果R、G、B这三个子像素均可实现人眼对灰度分辨能力64级灰度驱动,就可以实现有64x64x64约26万种彩色的“真彩色”。
TFT的主要特点是在每个像素配置一个半导体开关器件,由于每个像素都可以通过点脉冲直接控制,使得每个节点相对独立,并可以连续控制。TFT-LCD具有屏幕反应速度快,对比度和亮度都较高,屏幕可视角度大,色彩丰富、分辨率高等特点,是目前最好的LCD彩色显示设备之一。其原理见图1:
图1 TFT液晶原理
对比度:300:1
亮度:
外观尺寸:76.9*63.9(mm)
厚度:3.2(mm)
显示颜色:16.7兆色
Back light:six LEDs serial type
接口方式:24bit RGB
显示面积:70.08(H)mm×52.56(V)mm
图2 液晶尺寸参数及引脚说明
图3 液晶屏与S
2.2三星嵌入式处理器:S
S
ARM920T 核由ARM9TDMI,存储管理单元(MMU)和高速缓存三部分组成。其中MMU 可以管理虚拟内存,高速缓存由独立的16KB 地址和16KB 数据高速Cache 组成ARM920T 有两个协处理器:CP14 和CP15。CP14 用于调试控制,CP15 用于存储系统控制以及测试控制。(其内部结构见图4)
S
l 1 个LCD 控制器
l SDRAM 控制器。
l 3 个通道的UART。
l 4 个通道的DMA。
l 4 个具有PWM 功能的计时器和一个内部时钟。
l 8 通道的10 位ADC。
l 触摸屏接口。
l IIS 总线接口。
l 2 个USB 主机接口,1 个USB 设备接口。
l 2 个SPI 接口。
l SD 接口和MMC 卡接口。
l 看门狗计数器。
l 117 个通用I/O 口和24 位外部中断源。
l 8 通道10 位AD 控制器。
图4 S
LCD控制器的功能是产生显示驱动信号,驱动LCD显示器。用户只需要通过读写一系列的寄存器,完成配制和显示控制。S
l 支持单色、4级灰度、256色的调色板显示模式。
l 支持64K和
l 支持分辨率为640*480,320*240及其他多种规格的LCD。
S
REGBANK是LCD控制器的寄存器组,用来对LCD控制器的各项参数进行设置。而LCDCDMA则是LCD控制器专用的DMA信道,负责将视频资料从系统总线(System Bus)上取来,通过VIDPRCS从VD[23:0]发送给LCD屏。同时TIMEGEN和LPC3600负责产生LCD屏所需要的控制时序(如VSYNC,HSYNC,VCLK,VDEN),然后从VIDEO MUX送给LCD屏。
图5 S
通常使用的LCD控制管脚的定义如下:
VCLK:像素时钟信号;
VD [23:0]:LCD像素输出端口;
VM/VDEN/TP: LCD驱动器的AC偏置信号(STN)/数据使能信号(TFT)/SEC TFT源驱动器数据加载脉冲信号复用端口。
S
表1 S
2.3 S
对于控制TFT屏来说,除了要给它送视频资料(VD[23:0])以外,还有以下一些信号是必不可少的,分别是:
VCLK(像素时钟信号)
VDEN(数据使能信号)
VSYNC(垂直同步信号)
HSYNC(水平同步信号)
LEND(行结束信号)
LCD_PWREN(液晶屏使能信号)。
VCLK信号依赖于LCDCON1寄存器中CLKVAL和S
l VCLK(Hz)=HCLK/[(CLKVAL+1)x2]
VSYNC和HSYNC的产生依赖于LCDCON2/3寄存器及HOZVAL和LINEVAL的配置,其中:
l HOZVAL=水平显示尺寸-1
l LINEVAL=垂直显示尺寸-1
一般情况下,帧频率就是VSYNC信号的频率,它与LCDCON1和LCDCON2/3/4寄存器的VSYNC、VB2PD、VFPD、LINEVAL、HSYNC、HBPD、HFPD、HOZVAL和CLKVAL都有关系。大多数LCD驱动器都需要与显示器相匹配的帧频率,帧频率计算公式如下:
l FrameRate=1{[(VSPW+1)+(VBPD+1)+(LINEVAL+1)+(VFPD+1)]×[(HSPW+1)+ (HBPD+1)+(HFPD+1)+(HOZVAL+1)]×[2×(CLKVAL+1)/(HCLK)]}
以下图6为东华WXHAT35-TG2#001,的时序要求:
图6东华WXHAT35-TG2#001,的时序要求
依照液晶屏时序设置linux系统的相关驱动文件参数如下:
1)添加头文件
#include
2)添加初始化s
/* LCD driver info */
/* Configuration for 320*240东华WXHAT35-TG2#001*/
struct pxafb_mach_info S
.pixclock = 270000,
.xres = 320,
.yres = 240,
.bpp = 16,
.hsync_len = 29, //LCD_HSPW
.left_margin = 19, //LCD_HFPD
.right_margin = 37, //LCD_HBPD
.vsync_len = 2, //LCD_VSPW
.upper_margin = 11, //LCD_VFPD
.lower_margin = 14, //LCD_VBPD
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.cmap_greyscale = 0,
.cmap_inverse = 0,
.cmap_static = 0,
.reg = {
.lcdcon1 = (7<<8)|(0<<7)|(3<<5)|(12<<1),
.lcdcon2 = (14<<24) | (239<<14) | (11<<6) | (2),
.lcdcon3 = (37<<19) | (319<<8) | (19),
.lcdcon4 = (13<<8) | (29),
.lcdcon5 = (1<<11) | (1<<10) | (1<<9) | (1<<8) | (0<<7) | (1<<5) | (1<<3) |(0<<1) | (1),
}
};
3 linux系统下驱动的软件实现
3.1 嵌入式linux系统典型构成
嵌入式Linux(Embedded Linux)是指对Linux经过裁剪小型化后,可固化在存储器或单片机中,应用于特定嵌入式场合的专用Linux操作系统。嵌入式Linux的开发和研究已经成为目前操作系统领域的一个热点。嵌入式Linux系统的典型构成见图7。
图7嵌入式Linux系统的典型构成
3.2 linux设备驱动简介
1)设备驱动的任务包括:
对设备初始化和释放
把数据从内核传送到硬件和从硬件读取数据
读取应用程序传送给设备文件的数据和回送应用程序请求的数据
检测和处理设备出现的错误
2)linux系统下设备类型分类:
字符设备(char device)。
块设备(block device)。
网络设备(Network interfaces)
3)Linux下LCD设备驱动的实现方法:
像普通字符设备进行驱动编写
基于linux framebuffer 设备进行驱动编写
4)嵌入式linux的驱动程序所起的作用见下图8
图8 驱动程序在嵌入式linux系统中的作用
5)嵌入式linux设备驱动程序分三大部分
l 自动配置和初始化:检查硬件设备能否正常工作,进行状态初始化工作。
l I/O端口请求:这部分需要进行系统调用才能完成,系统从用户态变成内核态,然后进行各种I/O操作。
l 中断服务:在嵌入式linux中,中断信号由嵌入式linux系统接收,然后选择相应的中断服务程序。
3.2 linux Framebuffer设备驱动
此次设计linux TFT-LCD驱动就是基于帧缓冲设备编写。帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。
linux framebuffer设备是标准字符设备,主设备号为29,次设备号则从0到31。帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux下还可支持多个帧缓冲设备,最多可达32 个,分别为/dev/fb0到/dev/fb31,而/dev/fb则为当前缺省的帧缓冲设备,通常指向/dev/fb0。此次设计为嵌入式系统,支持一个显示设备就够了。
Framebuffer设备在很大程度上依靠了下面的3个数据结构,在fb.h中声明.
Struct fb_var_screeninfo
Struct fb_fix_screeninfo
Struct fb_info
第1个结构是用来描述图形卡的特性的,通常是被用户设置的。第2个结构定义了图形卡的硬件特性,是不能改变的,用户选定了LCD控制器和显示器后,那么它的硬件特性也就定下来了。第3个结构定义了当前图形卡framebuffer设备的独立状态,一个图形卡可能有两个framebuffer,在这种情况下,就需要两个fb_info结构,这个结构是惟一内核空间可见的。
3.3 framebuffer驱动程序的实现
应用程序通过内核对framebuffer的控制主要有下面三种方式:
1)读/写/dev/fb:相当于读/写屏幕缓冲区
2)映射(map)操作:通过映射操作,可将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图。
3)I/O控制:对应帧缓冲设备,设备文件的ioctl操作可读取设置显示设备及屏幕的参数,如分辨率、显示颜色数、屏幕大小等等。Ioctl的操作是由底层的驱动程序来完成的。
因此,Framebuffer驱动要完成的工作已经很少了,只需分配显存的大小,初始化LCD控制寄存器、设置修改硬件设备相应的var信息和fix信息。图10反映了应用程序如何写帧缓冲设备来显示图形的全过程。
图9 驱动程序实现框图
帧缓冲设备提供给用户空间的file_operations结构体有fbmem.c中的file_operations提供,而特定帧缓冲设备fb_info结构体的注册、注销、以及其中成员的维护,尤其是fb_ops中成员函数的实现则由对应的xxxfb.c文件实现,fb_ops中的成员函数最终会操作LCD控制器硬件寄存器。其程序结构间图9:
图10帧缓冲设备驱动的程序结构
具体要编写相关平台的驱动文件为:s
1) s
l struct pxafb_lcd_reg
l struct pxafb_info
l struct pxafb_mach_info
2) s
l static struct fb_ops pxafb_ops{}
主要函数: static int pxafb_setcolreg //设置颜色表函数
static int pxafb_check_var //检查可变参数
static int pxafb_set_par //设置可变参数
static int pxafb_blank //空白显示设定
l static struct device_driver pxafb_driver{}
主要函数:int __init pxafb_probe //LCD设备探测函数,此函数调用前面定义的函数,完成LCD硬件的初始化、fb_info参数的填充、申请缓冲区并注册缓冲设备。
l 除以上结构体及其成员函数还有如下主要函数:
int __devinit s
static int pxafb_freq_transition //LCD时钟参数修改函数,使其匹配CPU时钟改变
static inline unsigned int get_pcd //取得像素时钟
static inline void __pxafb_backlight_power//设定LCD背光电源
static inline void __pxafb_lcd_power //设定LCD电源
static void pxafb_setup_gpio //挂起io端口
static void pxafb_enable_controller //使能LCD控制器
static void pxafb_disable_controller //使停LCD控制器
4 linux设备驱动的移植
在完成了嵌入式linux驱动程序编写测试工作以后,下一步就是将编写好的驱动程序加载到系统内核,完成驱动硬件的工作。通常有以下两种方法。
1)驱动程序的模块加载
采用模块加载方式的驱动程序将会以模块形式存储在文件系统里,需要时动态载入内核即可。这样使得驱动程序按需加载,不用时节省内存,并且驱动程序相对独立于内核,升级灵活。具体实现方法见下图10:
图11 驱动程序的模块加载模式
2)驱动程序直接编译入内核
采用这种方式编译的驱动程序在内核启动时就已经在内存中,运行时不需要再自己加载驱动,可以保留专用的存储器空间。具体实现方法见图11:
图12 驱动程序编译进内核的加载方式
本次设计的LCD驱动的加载就是直接编译进内核的。具体实现如下:
l 将LCD驱动文件s
l 更改该目录下的Kconfig,增加如下代码:
l 在该目录下的Makefile中添加如下代码:
obj-$(CONFIG_FB_S
l 进入源码目录,执行make menuconfig后,选择“Graphics support”项,选中我们要加载进内核的“s
l 保存内核改动后,使用make zImage将内核重新打包编译成映像文件。编译完成后的映像文件就可以用于开发板的下载了。
5 设计结果
本设计的主要目的是通过对S
参考文献:
【1】宋宝华。Linux设备驱动开发详解。北京:人民邮电出版社,2008。
【2】孙纪坤,张小全。嵌入式linux系统开发技术详解—基于ARM。北京:人民邮电出版社,2006。
【3】李俊。嵌入式linux设备驱动开发详解。北京:人民邮电出版社,2008。
【4】孙天泽,袁文菊。嵌入式设计及linux驱动开发指南—基于ARM9处理器(第2版)。北京:电子工业出版社,2007。
【5】张崙。32位嵌入式系统硬件设计与调试。北京:机械工业出版社,2006。
【6】著 ,, 译。Linux设备驱动程序(第三版)。北京:中国电力出版社,2006。
【7】许庆丰。嵌入式Linux下彩色LCD驱动的设计与实现。2002年12月。
【8】刘利国。S
【9】seasea。2410 lcd(ltv350)驱动在
【10】雷鸿,熊文龙,杨单。基于Framebuffer的LCD驱动程序的实现。2006年2月。