LCD驱动编写小结
LCD驱动的学习
LCD驱动的学习简介:LCD是基于液晶的。
LCD(liquid crystal display)按驱动⽅式分类可以分为静态驱动,简单矩阵驱动,主动矩阵驱动。
其中,简单矩阵⼜可以分为扭转向列型(TN)和超转向列型(STN),⽽主动矩阵驱动则以TFT(⽤的最多)为主。
TN型液晶驱动:是LCD中最基本的,他只能将⼊射光旋转90度,视⾓只有30度。
STN型驱动液晶:可以讲⼊射光旋转180度⾄270度,也改善了视⾓。
TFT解决了上述两种液晶屏的缺陷,属于⽐较常⽤的。
⼀块lcd屏显⽰图像不但需要lcd驱动器,还需要lcd控制器。
很多主芯⽚cpu继承了lcd控制器。
其显⽰原理为:作为帧同步信号的vsync,每发出⼀个脉冲,就意味着⼀幅图像开始传输。
作为⾏同步信号的hsync,每发出⼀个信号,代表新的⼀⾏图像资料开始发送。
图像为从左向右,从上向下显⽰。
⼀个完整的时序图如下:下⾯是lcd的技术参数:1. 可视⾯积2. 可视⾓度3. 点距4. ⾊彩度5. 对⽐值6. 亮度值7. 响应时间显存:Framebuffer(帧缓冲)从本质上讲是图形设备的硬件抽象。
对开发者⽽⾔,framebuffer是⼀块显⽰缓存,往显⽰缓存中陷⼊特定格式的数据就意味着向屏幕中输出内容。
通过不断地向framebuffer中写数据,显⽰控制器就⾃动的从framebuffer中读数据并显⽰出来。
在嵌⼊式⼀般没有专门的芯⽚做显存,⼀般是从内存中分⼀部分做显存。
Framebuffer其实就是显存。
帧缓冲设备对应的设备⽂件是/dev/fb*,如果系统中有多个显⽰卡,linux下还可⽀持多个帧缓冲设备,最多可达32个。
帧缓冲设备的主设备号为29,次设备号是0到31.下⾯是使⽤帧缓冲设备⽂件的演⽰。
帧缓冲设备编程:整个编程的系统架构如下:可以看出,我们实现帧缓冲设备主要需要完成两个任务:1. 实现⼀个fb_info结构体,这其中包括可变参数,固定参数,操作列表等。
实验9LCD显示驱动开发实验
1 / 2
1. 实验目的
通过实验学会Linux 下对IIC 的操作方法;
通过实验掌握在Linux 下驱动和应用程序的编写方法
2. 实验内容
在Linux 操作系统下编写应用程序实现将数据写入EEPROM 。
3. 主要仪器设备
一台装有Ubuntu 系统的PC 机(宿主机),至少要有一个串口;
目标板(或开发板),这里指英培特eduk4-s3c2410试验平台;
一根串口线,用于宿主机与开发板通信;
其他嵌入式软件包。
4. 操作方法和实验步骤
4.1 编译应用程序
1. 将$SIMPLEDIR/9.1-lcd_test 目录下的test.bin 拷贝到tftp 目录下,并使用串口和tftp 传输至实验箱/tmp 路径下。
2. 将test.bin 复制到/dev/fb/0下。
cp /tmp/test.bin /dev/fb/0
3. 复制完成后,将看到如图4-1所示的效果图。
图4-1
效果图
5.实验结果和分析
6.讨论和心得
友情提示:方案范本是经验性极强的领域,本范文无法思考和涵盖全面,供参考!最好找专业人士起草或审核后使用。
LCD驱动程序之代码编写
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硬件⽽设计的,但我们不需要去了解每⼀个成员变量的功能和使⽤⽅法。
基于uCOSⅡ的LCD驱动编写
天津电子信息职业技术学院课程设计课题名称基于uCOSⅡ的LCD驱动编写姓名王浩学号35班级电信S10-1专业电子信息工程成绩完成日期2012-06-01基于uCOSII的LCD驱动编写摘要LCD是嵌入式操作系统的重要组成部分,是系统和用户之间进行交互和信息交换的媒介,它实现信息的内部形式与人类可以接受形式之间的转换。
用户可以只通过LCD监测系统内部运行状态,然后作出相应的处理。
因而具有良好的人机界面的嵌入式操作系统能过很好的完成系统开发、生产生活的需要。
S3C44B0X 中具有内置的LCD 控制器,它能将显示缓存(在SDRAM存储器中)中的LCD 图像数据传输到外部的LCD驱动电路上的逻辑功能。
它支持单色、4级、16级灰度LCD显示,以及256彩色LCD显示。
在显示灰度时,它采用时间抖动算法(time-based dithering algorithm)和帧率控制 (Frame Rate Control)方法,在显示彩色时,它采用RGB的格式,即RED、GREEN、BLUE,三色混合调色。
通过软件编程,可以实现233或332的RGB调色的格式。
对于不同尺寸的LCD显示器,它们会有不同的垂直和水平象素点、不同的数据宽度、不同的接口时间及刷新率,通过对LCD 控制器中的相应寄存器写入不同的值,来配置不同的LCD 显示板。
LCD能够正常工作得益于软硬件的协同工作,S3C44B0X集成了LCD的控制器,即不带驱动电路的LCD显示模块,驱动程序需要根据用户需要来自行添加。
u C / O S 是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统,在具体应用中稳定可靠,并且支持uIP TCP/IP协议栈、ucGUI等,可扩展性强,功能强大。
因此,在uC/OS II下写的LCD驱动具有较好的实时性和稳定性,功能强大。
关键词:嵌入式系统;LCD显示;驱动电路;目录一、系统设计 (4)1.课题目标及总体方案 (4)2.LCD驱动程序组成 (4)3.UCOSII操作系统下添加LCD驱动程序 (5)4.应用程序 (5)二、实验结果测试 (6)三、总结 (7)四、心得体会 (8)五、参考文献 (9)六、附录 (9)一、系统设计1.课题目标及总体方案首先学习了解LCD的驱动程序,然后在移植好的UCOSII项目中添加LCD的驱动程序, 最后能够在uCOSII下,编写LCD应用任务的简单编程实例,来检验LCD驱动程序的完好度。
LCD驱动工作原理 ,基于51单片机LCD底层时序程序该如何编写?
LCD驱动工作原理,基于51单片机LCD底层时序程序该如何编写?LED驱动原理方式解析:(1)被动矩阵LCD技术高信息密度显示技术中首先商品化的是被动矩阵显示技术,它得名于控制液晶单元的开和关的简单设计。
被动矩阵液晶显示的驱动方式是由垂直与水平方向的电极所构成的,且将单独的液晶单元夹在彼此垂直的电极中间。
因此,任何一组电极的驱动就会在特定的单元中引起电流通过。
被动矩阵显示画面的原理是用输入的信号依次去驱动每一排的电极,于是当某一排被选定的时候,列向上的电极将被触发用于打开位于排和列交叉上的那些像素。
这种方法比较简单,而且对液晶屏幕成本的增加也不多。
不过其存在的缺点是:如果有太大的电流通过某个单元,附近的单元都会受到影响,会引起虚影;如果电流太小,单元的开和关就会变得迟缓,会降低对比度和丢失移动画面的细节。
早期的被动矩阵板依赖于扭转向列的设计。
其上层和下层的偏光板的偏振光方向呈90,因此中间的液晶以90进行扭转。
这样制造的液晶板对比度很低,响应时间也很慢。
这种方式运用在低信息量显示时效果很好,但不适合计算机显示。
超扭转向列(Super Twisted NemaTIc)方法是通过改变液晶材料的化学成分,使液晶分子发生不止一次的扭转,使光线扭转达到180到270,这样便可大大地改善画面的显示品质。
20波纪80年代初期,STN技术一度非常流行,至今它还在便携式电子设备如PDA、移动电话中使用。
虽然STN技术提高了显示的对比度,但它会引起光线的色彩偏差,尤其是在屏幕偏离主轴的位置上。
这就是为什么早期的笔记本计算机屏幕总是偏蓝和偏黄的原因。
双层超扭曲向列型显示技术(DSTN)具有两层扭转方向相对的LCD层,第二层使得第一层遗留的色偏问题得以解决。
当然它的制造工艺比前两种方式要复杂得多。
后来人们发现了比DSTN更简单易行的方法,就是在底层和顶层的外表面加上补偿膜,来改善STN技术中所产生的特定波段光线的散射和反射现象,这就是补偿膜超扭转向列(Film-compensated STN,FSTN)显示技术。
S3C2410 LCD驱动学习心得-3
2.3.2 实现消息的分派fbmem.c实现了对系统全部FrameBuffer设备的统一管理。
当用户尝试使用一个特定的FrameBuffer时,fbmem.c怎么知道该调用那个特定的设备驱动呢?我们知道,Linux是通过主设备号和次设备号,对设备进行唯一标识。
不同的FrameBuffer 设备向fbmem.c注册时,程序分配给它们的主设备号是一样的,而次设备号是不一样的。
于是我们就可以通过用户指明的次设备号,来觉得具体该调用哪一个FrameBuffer驱动。
下面通过分析fbmem.c的fb_open()函数来说明。
(注:一般我们写FrameBuffer驱动不需要实现open函数,这里只是说明函数流程。
)static int fb_open(struct inode *inode, struct file *file){int fbidx = iminor(inode);struct fb_info *info;int res;/* 得到真正驱动的函数指针*/if (!(info = registered_fb[fbidx])) return -ENODEV;if (info->fbops->fb_open) {res = info->fbops->fb_open(info,1); //调用驱动的open()if (res) module_put(info->fbops->owner);}return res;}当用户打开一个FrameBuffer设备的时,将调用这里的fb_open()函数。
传进来的inode就是欲打开设备的设备号,包括主设备和次设备号。
fb_open函数首先通过iminor()函数取得次设备号,然后查全局数组registered_fb得到设备的fb_info信息,而这里面存放了设备的操作函数集fb_ops。
这样,我们就可以调用具体驱动的fb_open() 函数,实现open的操作。
S3C2410 LCD驱动学习心得-4
3. BMP和JPEG图形显示程序3.1 在LCD上显示BMP或JPEG图片的主流程图首先,在程序开始前。
要在nfs/dev目录下创建LCD的设备结点,设备名fb0,设备类型为字符设备,主设备号为29,次设备号为0。
命令如下:mknod fb0 c 29 0在LCD上显示图象的主流程图如图3.1所示。
程序一开始要调用open函数打开设备,然后调用ioctl获取设备相关信息,接下来就是读取图形文件数据,把图象的RGB值映射到显存中,这部分是图象显示的核心。
对于JPEG格式的图片,要先经过JPEG解码才能得到RGB 数据,本项目中直接才用现成的JPEG库进行解码。
对于bmp格式的图片,则可以直接从文件里面提取其RGB数据。
要从一个bmp文件里面把图片数据阵列提取出来,首先必须知道bmp文件的格式。
下面来详细介绍bmp文件的格式。
图3.13.2 bmp位图格式分析位图文件可看成由四个部分组成:位图文件头、位图信息头、彩色表和定义位图的字节阵列。
如图3.2所示。
图3.2文件头中各个段的地址及其内容如图3.3。
图3.3位图文件头数据结构包含BMP图象文件的类型,显示内容等信息。
它的数据结构如下定义:Typedef struct{int bfType;//表明位图文件的类型,必须为BMlong bfSize;//表明位图文件的大小,以字节为单位int bfReserved1;//属于保留字,必须为本0int bfReserved2;//也是保留字,必须为本0long bfOffBits;//位图阵列的起始位置,以字节为单位} BITMAPFILEHEADER;图3.4 位图文件头的数据结构(2)信息头中各个段的地址及其内容如图3.5所示。
图3.5位图信息头的数据结构包含了有关BMP图象的宽,高,压缩方法等信息,它的C语言数据结构如图3.6所示。
Typedef struct {long biSize;//指出本数据结构所需要的字节数long biWidth;//以象素为单位,给出BMP图象的宽度long biHeight;//以象素为单位,给出BMP图象的高度int biPlanes;//输出设备的位平面数,必须置为1int biBitCount;//给出每个象素的位数long biCompress;//给出位图的压缩类型long biSizeImage;//给出图象字节数的多少long biXPelsPerMeter;//图像的水平分辨率long biYPelsPerMeter;//图象的垂直分辨率long biClrUsed;//调色板中图象实际使用的颜色素数long biClrImportant;//给出重要颜色的索引值} BITMAPINFOHEADER;图3.6 BITMAPINFOHEADER数据结构(3)对于象素小于或等于16位的图片,都有一个颜色表用来给图象数据阵列提供颜色索引,其中的每块数据都以B、G、R的顺序排列,还有一个是reserved保留位。
LCD的驱动控制实验报告
LCD的驱动控制实验一、实验目的1.了解LCD 基本概念与原理。
2.理解LCD 的驱动控制。
3.熟悉用总线方式驱动LCD 模块。
4.熟悉用ARM 内置的LCD 控制器驱动LCD。
二、实验内容学习LCD 显示器的基本原理,理解其驱动控制方法。
掌握两种LCD 驱动方式的基本原理和方法。
并用编程实现用ARM 内置的LCD 控制器来驱动LCD。
三、预备知识1.用ARM SDT 2.5 或ADS1.2 集成开发环境,编写和调试程序的基本过程。
2.ARM 应用程序的框架结构。
四、实验设备及工具硬件:ARM 嵌入式开发平台、用于ARM7TDMI 的JTAG 仿真器、PC 机Pentium100 以上。
软件:PC 机操作系统win98、Win2000 或WinXP、ARM SDT 2.51 或ADS1.2 集成开发环境、仿真器驱动程序、超级终端通讯程序五、实验原理及说明1.LCD(Liquid Crystal Display)原理液晶得名于其物理特性:它的分子晶体,以液态存在而非固态。
这些晶体分子的液体特性使得它具有两种非常有用的特点:1、如果让电流通过液晶层,这些分子将会以电流的流向方向进行排列,如果没有电流,它们将会彼此平行排列。
2、如果提供了带有细小沟槽的外层,将液晶倒入后,液晶分子会顺着槽排列,并且内层与外层以同样的方式进行排列。
液晶的第三个特性是很神奇的:液晶层能使光线发生扭转。
液晶层表现的有些类似偏光器,这就意味着它能够过滤除了那些从特殊方向射入之外的所有光线。
此外,如果液晶层发生了扭转,光线将会随之扭转,以不同的方向从另外一个面中射出。
液晶的这些特点使得它可以被用来当作一种开关——即可以阻碍光线,也可以允许光线通过。
液晶单元的底层是由细小的脊构成的,这些脊的作用是让分子呈平行排列。
上表面也是如此,在这两侧之间的分子平行排列,不过当上下两个表面之间呈一定的角度时,液晶随着两个不同方向的表面进行排列,就会发生扭曲。
单片机实验——LCD的驱动控制及触屏驱动实验
单片机实验——LCD的驱动控制及触屏驱动实验浙江大学城市学院实验报告课程名称:嵌入式操作系统实验实验名称:LCD的驱动控制及触屏驱动实验学生姓名:黄丽平专业:电科1201 学号:31202417同组学生姓名:范易宵31202425 郭琪琛31202428指导老师:朱胜成绩:一、实验目的1.了解LCD基本概念与原理。
2.理解LCD的驱动控制。
3.熟悉用总线方式驱动LCD模块。
4.熟悉用ARM内置的LCD控制器驱动LCD。
5.了解触屏基本概念与原理。
6.理解触摸屏与LCD的密切配合。
7.编程实现对触摸屏的控制。
二、实验内容学习LCD显示器的基本原理,理解其驱动控制方法。
掌握两种LCD驱动方式的基本原理和方法。
并用编程实现;1.用总线方式直接驱动带有驱动模块的LCD。
2.用ARM内置的LCD控制器驱动LCD。
3.学习触摸屏的基本原理,理解对触摸屏进行输出的标定、与LCD显示器配合的过程。
三、实验设备1.硬件:ARM嵌入式开发平台、用于ARM7TDMI的JTAG仿真器、PC机Pentium100以上。
2.软件:PC操作系统WIN2000或WINXP、ADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序。
四、实验步骤1.新建工程,将“LCD的驱动控制实验”中的文件添加到工程中,这些是启动时所需要的文件。
2.修改程序,使其实现以下功能:(1)将LCD分为三块,分别显示三种颜色(2)将LCD分为四块田字型,分别显示四种颜色(3)设计清屏程序(4)显示圆环(5)显示正弦函数(6)创意设计3.修改组合程序,实现以下功能:(1)使坐标原点改为左下角(2)改变分辨率(3)在触摸屏上单击,以单击位置为原点画一个圆(4)在触摸屏上点两次,以第一次点为圆心,两点间距离为半径画圆分三块程序:#include "44b.h"#include"uhal.h"#include "option.h"#include"def.h"#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting extern U32 LCDBuffer[240][320];int main(void){int i,j,k;U32 jcolor;ARMTargetInit(); //开发版初始化LCD_Init(); //LCD初始化for (i=0;i<3;i++){ switch (i){ case 0: jcolor=0x000000e0;break;case 1: jcolor=0x0000d0e0;break;case 2: jcolor=0x00e000e0;break;}for (k=0;k<240;k++)for (j=i*107;j<i*107+107;j++)< p=""> LCDBuffer[k][j]=jcolor;}//jcolor=0x000000ff;//for (i=0;i<240;i++)// {if (i==80||i==160)// jcolor<<=8;//for (j=288;j<320;j++)// LCDBuffer[i][j]=jcolor;// }LCD_Refresh() ;while(1);return 0;}分四块主程序:int main(void){int i,j,k;U32 jcolor;ARMTargetInit(); //开发版初始化LCD_Init(); //LCD初始化//jcolor=0x000000ff;for (i=0;i<240;i++){if(i<=120){for(j=0;j<160;j++)LCDBuffer[i][j]=0x0000000e0;for(j=160;j<320;j++)LCDBuffer[i][j]=0x000e000e0;}if(i>=120){for(j=0;j<160;j++)LCDBuffer[i][j]=0x000e0e0e0;for(j=160;j<320;j++)LCDBuffer[i][j]=0x00000d0e0;}}LCD_Refresh() ;while(1);return 0;}清屏程序:int i,j,k;void LCD_change(u32 a){for (k=0;k<240;k++){ for (j=0;j<320;j++)LCDBuffer[k][j]=a;}}圆环程序:void LCD_yuan(int x,int y,int r0,int r1,u32 color){for (k=0;k<240;k++){ for (j=0;j<320;j++)if(sqrt((j-x)*(j-x)+(k-y)*(k-y))<=r1&&sqrt((j-x)*(j-x)+(k-y)*(k-y))>=r0){LCDBuffer[k][j]=color;}}LCD_Refresh() ;}正弦函数程序(未完成):void LCD_sin(u32 color){for (k=0;k<240;k++){ for (j=0;j<320;j++)if(20*sin(j*100)<=(k-120)){LCDBuffer[k][j]=color;}}LCD_Refresh() ;}单击画圆程序:void LCD_yuan(int r0,u32 color){int x;int y;int i,j,k;U32 mode;for(;;){mode=TchScr_GetOSXY(&x, &y);if(mode==TCHSCR_ACTION_CLICK) {for (k=0;k<240;k++){for (j=0;j<320;j++)if(sqrt((j-x)*(j-x)+(k-y)*(k-y))<=r0) {LCDBuffer[k][j]=color;}}LCD_Refresh();}Delay(10000);}}点两个点画圆程序:void LCD_yuan2(u32 color){int x1,x2,y1,y2,x,y;int i,j,k;U32 mode1,mode2;for(;;){mode1=TchScr_GetOSXY(&x, &y); x1=x;y1=y;Delay(3);mode2=TchScr_GetOSXY(&x, &y);x2=x;y2=y;if(mode1==TCHSCR_ACTION_CLICK&&mode2==TCHSCR_ ACTION_CLICK) {for (k=0;k<240;k++){for (j=0;j<320;j++)if(sqrt((j-x1)*(j-x1)+(k-y1)*(k-y1))<=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))){LCDBuffer[k][j]=color;}}LCD_Refresh();</i*107+107;j++)<>。
lcd驱动原理
lcd驱动原理LCD驱动原理。
液晶显示屏(LCD)是一种常见的显示设备,广泛应用于电子产品中,如手机、电视、电脑等。
而LCD的驱动原理则是其正常工作的基础,下面将对LCD的驱动原理进行详细介绍。
首先,LCD的驱动原理是基于液晶分子的排列和光透过的原理。
液晶分子在不同电场作用下会产生不同的排列状态,从而影响光的透过程度,进而实现显示效果。
这种原理是基于液晶分子的电光效应和扭曲效应,通过控制电场的强弱和方向来调节液晶分子的排列状态,从而控制光的透过程度,实现显示效果。
其次,LCD的驱动原理涉及到液晶显示屏的控制器和驱动电路。
控制器是负责接收外部信号并对显示内容进行处理的芯片,而驱动电路则是负责向液晶显示屏施加电场,控制液晶分子排列状态的电路。
控制器和驱动电路共同协作,通过对液晶分子的排列状态进行精准控制,实现对显示内容的精准呈现。
此外,LCD的驱动原理还涉及到显示数据的传输和刷新。
显示数据需要通过控制器传输到液晶显示屏,并在一定的频率下进行刷新,以保持显示内容的稳定和连续。
传输和刷新过程需要考虑到数据的稳定性和实时性,以确保显示效果的流畅和清晰。
最后,LCD的驱动原理还涉及到对显示效果的调节和优化。
通过对电场的调节和对显示数据的处理,可以实现对显示效果的亮度、对比度、色彩等方面的调节和优化,以满足不同场景和用户的需求。
综上所述,LCD的驱动原理是基于液晶分子的排列和光透过的原理,涉及到液晶显示屏的控制器和驱动电路、显示数据的传输和刷新,以及对显示效果的调节和优化。
了解LCD的驱动原理有助于我们更好地理解液晶显示屏的工作原理,为相关电子产品的设计和应用提供指导和参考。
LCD驱动实验报告
实验序号:6实验项目名称:LCD驱动实验
学 号
姓 名
专业、班
实验地点
指导教师
实验时间
一、实验目的
1.了解LCD基本概念与原理。
2.了解Linux下LCD的Framebuffer结构原理
3.了解用总线方式驱动LCD模块。
4.熟悉用ARM内置的LCD控制器驱动LCD。
二、实验设备(环境)及要求
硬件:UP-TECHPXA270-S嵌入式开发板、PC机Pentumn500以上,硬盘10G以上。
软件:PC机操作系统REDHAT NUX 9.0+MINICOM+ARM-LINUX开发环境
三、实验内容与步骤
1打开一个命令终端,并切换到内核目录树的最顶层(linux-2.6.9)运行make menuconfigMake menuconfig->Graphics support,修改为M,即编译成模块,保存退出后,make zImage编译成内核镜像
五、实验总结
在设计过程中,通过本次实验,我了解LCD显示器的结构特点,了解S3C2410的LCD驱动模块工作原理,掌握用简单LCD驱动程序设计等,与同学分工设计,和同学们相互探讨,相互学习,相互监督。学会了合作。课程设计是我们专业课程知识综合应用的实践训练,从事职业工作前一个必不少的过程.在这次设计过程中,体现出设计ARM驱动程序的能力以及综合运用知识的能力,体会了学以致用、突出自己劳动成果的喜悦心情,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。
2把/up-techpxa270/exp/kernel/linux-2.6.9/drivers/video目录下的几个关于lcd的文件拷贝到我们自己建立的工作目录下(/up-techpxa270/exp/drivers/lcd)
6410 I80LCD屏驱动的编写
6410的I80LCD屛驱动的编写陆定斌在嵌入式的主流 LCD屏中主要支持两大类的硬件接口,一种是常见的RGB接口,另外一种是MCU接口.后面因为最早是针对单片机的领域在使用,因此得名.后在中低端手机大量使用,其主要特点是价格便宜的。
MCU-LCD接口的标准术语是Interface 80,因此在很多文档中用I80 来指MCU-LCD屏。
MCU-LCD屏它与RGB-LCD屏主要区别在于显存的位置.RGB-LCD的显存是由系统内存充当的,因此其大小只受限于系统内存的大小,这样 RGB-LCD可以做出较大尺寸,象现在4.3"只能算入门级,而MID中7",10"的屏都开始大量使用.而MCU-LCD的设计之初只要考虑单片机的内存较小,因此都是把显存内置在LCD模块内部.然后软件通过专门显示命令来更新显存,因此MCU屏往往不能做得很大.同时显示更新速度也比RGB- LCD慢。
量示数据传输模式也有差别。
RGB屏只需显存组织好数据。
启动显示后。
LCD-DMA会自动把显存通过RGB接口送到LCM。
而MCU屏则需要发送画点的命令来修改MCU内部RAM。
(即不能直接MCU屏RAM)所以RGB显示速度明显比MCU快,而且播放视频方面,MCU-LCD也比较慢.S3C6410 即支持RGB-LCD屏,也支持MCU-LCD屏.而对MCU-LCD屏的显示模块的显存显示,它除了支持传统的绘制命令,也支持一种特有的类似RGB-LCD屏的显示模式。
即显示数据仍然在系统内存中组织,显示时通过DMA传输到显示器控制器,由硬件来产生绘制命令。
相对纯软件绘制模式,这种方法速度更快。
MCU-LCD管脚分析---------------------------------------------------------------------两种屏通过管脚直接就可以看出来的。
RGB屏管脚主要分为两类控制脚是VSYNC/HSYNC/VDEN/VCLK S3C6410最高支持24个数据脚,数据脚是 VD[23-0];MCU接口标准名称是 I80 Interface.MCU管脚的控制脚有5个∙CS 片选信号∙ RS (置1为写数据,置0为写命令)∙/WR (为0表示写数据)∙/RD (为0表示读数据)∙RESET 复位LCD(用固定命令系列 0 1 0来复位)数据脚一般是18个,即DB[17:0],这样表示大部MCU最高支持18bpp。
实验8LCD屏幕驱动实验
LCD屏幕实验
一、实验目的
使用STM32的LTDC功能驱动一块7寸液晶屏幕,并实现相应显示功能二、实验内容
(1)配置LTDC控制器,驱动7寸液晶屏幕。
(2)利用lcd.c中提供的绘图函数进行界面绘制
1) 实现一个电子时钟表盘,表盘要有外框,刻度;
2) 实现时针、分针、秒针的指针的转动;
三、预备知识
(1)STM32F429IGT6芯片手册;
(2)基本的C语言知识;
(3)LCD驱动相关知识。
四、实验设备及工具
硬件:STM32F429开发板、7寸液晶屏、PC机
软件:MDK、ST-Link
五、实验步骤
(1)参照实验指导书,配置LCD屏幕;
(2)实现电子时钟;
六、思考题
(1)为什么要对上一时刻的绘制的指针进行消影?。
Linux驱动之LCD驱动编写
Linux驱动之LCD驱动编写在这篇博客中已经分析了编写LCD驱动的步骤,接下来就按照这个步骤来字尝试字节编写LCD驱动。
⽤的LCD屏幕为tft 屏,每个像素点为16bit。
对应与红绿蓝分别为565。
1、分配⼀个fb_info结构2、设置fb_info结构3、硬件相关的操作,配置LCD时钟、配置IO端⼝、配置LCD寄存器。
4、最终注册fbinfo结构到registered_fb数组要理解LCD的⼯作原理,需要了解LCD的时钟,在TFT的LCD中有如下的时钟。
这个⼏个时钟数据在配置LCD寄存器时都说需要设置的。
1、VCLK:两个像素之间的时钟,即两个像素隔多长时间才能显⽰下⼀个像素2、HSYNC:⽔平同步时钟,即第⼀⾏像素点显⽰完成之后隔多长时间才能开始下⼀⾏的显⽰3、VSYNC:垂直⽅向的同步时钟,也叫帧同步信号,即⼀帧数据显⽰完成之后(⼀帧数据表⽰⼀个屏幕显⽰完成,即⼀个显存的数据全部取完),过多长下⼀帧数据才开始显⽰本节需要⽤到的函数:void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp); //分配DMA缓存区给显存//返回值为:申请到的DMA缓冲区的虚拟地址,若为NULL,表⽰分配失败,则需要使⽤dma_free_writecombine()释放内存,避免内存泄漏//参数如下://*dev:指针,这⾥填0,表⽰这个申请的缓冲区⾥没有内容//size:分配的地址⼤⼩(字节单位)//*handle:申请到的物理起始地址//gfp:分配出来的内存参数,标志定义在<linux/gfp.h>,常⽤标志如下://GFP_ATOMIC ⽤来从中断处理和进程上下⽂之外的其他代码中分配内存. 从不睡眠.//GFP_KERNEL 内核内存的正常分配. 可能睡眠.//GFP_USER ⽤来为⽤户空间页来分配内存; 它可能睡眠.分配⼀段DMA缓存区,分配出来的内存会禁⽌cache缓存(因为DMA传输不需要CPU)它和 dma_alloc_coherent ()函数相似,不过 dma_alloc_coherent ()函数是分配出来的内存会禁⽌cache缓存以及禁⽌写⼊缓冲区dma_free_writecombine(dev,size,cpu_addr,handle); //释放缓存//cpu_addr:虚拟地址,//handle:物理地址释放DMA缓冲区, dev和size参数和上⾯的⼀样struct fb_info *framebuffer_alloc(size_t size, struct device *dev); //申请⼀个fb_info结构体,//size:额外的内存,//*dev:指针, 这⾥填0,表⽰这个申请的结构体⾥没有内容int register_framebuffer(struct fb_info *fb_info);//向内核中注册fb_info结构体,若内存不够,注册失败会返回负数int unregister_framebuffer(struct fb_info *fb_info) ;//注销内核中fb_info结构体本节需要⽤到的结构体:fb_info结构体如下:struct fb_info {... ...struct fb_var_screeninfo var; //可变的参数struct fb_fix_screeninfo fix; //固定的参数... ...struct fb_ops *fbops; //操作函数... ...char __iomem *screen_base; //显存虚拟起始地址unsigned long screen_size; //显存虚拟地址长度void *pseudo_palette;//假的16⾊调⾊板,⾥⾯存放了16⾊的数据,可以通过8bpp数据来找到调⾊板⾥⾯的16⾊颜⾊索引值,模拟出16⾊颜⾊来,节省内存,不需要的话就指向⼀个不⽤的数组即可 ... ...};其中操作函数fb_info-> fbops 结构体写法如下:static struct fb_ops s3c_lcdfb_ops = {.owner = THIS_MODULE,.fb_setcolreg = my_lcdfb_setcolreg,//设置调⾊板fb_info-> pseudo_palette,⾃⼰构造该函数.fb_fillrect = cfb_fillrect, //填充矩形,⽤/drivers/video/ cfbfillrect.c⾥的函数即可.fb_copyarea = cfb_copyarea, //复制数据, ⽤/drivers/video/cfbcopyarea.c⾥的函数即可.fb_imageblit = cfb_imageblit, //绘画图形, ⽤/drivers/video/imageblit.c⾥的函数即可};固定的参数fb_info-> fix 结构体如下:struct fb_fix_screeninfo {char id[16]; //id名字unsigned long smem_start; //framebuffer物理起始地址__u32 smem_len; //framebuffer长度,字节为单位__u32 type; //lcd类型,默认值0即可__u32 type_aux; //附加类型,为0__u32 visual; //画⾯设置,常⽤参数如下// FB_VISUAL_MONO01 0 单⾊,0:⽩⾊,1:⿊⾊// FB_VISUAL_MONO10 1 单⾊,1:⽩⾊,0:⿊⾊// FB_VISUAL_TRUECOLOR 2 真彩(TFT:真彩)// FB_VISUAL_PSEUDOCOLOR 3 伪彩// FB_VISUAL_DIRECTCOLOR 4 直彩 __u16 xpanstep; /*如果没有硬件panning就赋值为0 */ __u16 ypanstep; /*如果没有硬件panning就赋值为0 */ __u16 ywrapstep; /*如果没有硬件ywrap就赋值为0 */ __u32 line_length; /*⼀⾏的字节数 ,例:(RGB565)240*320,那么这⾥就等于240*16/8 */ /*以下成员都可以不需要*/ unsigned long mmio_start; /*内存映射IO的起始地址,⽤于应⽤层直接访问寄存器,可以不需要*/__u32 mmio_len; /* 内存映射IO的长度,可以不需要*/__u32 accel;__u16 reserved[3];};可变的参数fb_info-> var 结构体如下:structfb_var_screeninfo{ __u32xres; /*可见屏幕⼀⾏有多少个像素点*/__u32 yres; /*可见屏幕⼀列有多少个像素点*/__u32 xres_virtual; /*虚拟屏幕⼀⾏有多少个像素点 */__u32 yres_virtual; /*虚拟屏幕⼀列有多少个像素点*/__u32 xoffset; /*虚拟到可见屏幕之间的⾏偏移,若可见和虚拟的分辨率⼀样,就直接设为0*/ __u32 yoffset; /*虚拟到可见屏幕之间的列偏移*/__u32 bits_per_pixel; /*每个像素的位数即BPP,⽐如:RGB565则填⼊16*/__u32 grayscale; /*⾮0时,指的是灰度,真彩直接填0即可*/struct fb_bitfield red; //fb缓存的R位域, fb_bitfield结构体成员如下://__u32 offset; 区域偏移值,⽐如RGB565中的R,就在第11位//__u32 length; 区域长度,⽐如RGB565的R,共有5位//__u32 msb_right; msb_right ==0,表⽰数据左边最⼤, msb_right!=0,表⽰数据右边最⼤struct fb_bitfield green; /*fb缓存的G位域*/struct fb_bitfield blue; /*fb缓存的B位域*/ /*以下参数都可以不填,默认为0*/struct fb_bitfield transp; /*透明度,不需要填0即可*/__u32nonstd; /* != 0表⽰⾮标准像素格式*/__u32 activate; /*设为0即可*/__u32height; /*外设⾼度(单位mm),⼀般不需要填*/__u32width; /*外设宽度(单位mm),⼀般不需要填*/__u32 accel_flags; /*过时的参数,不需要填*//* 除了pixclock本⾝外,其他的都以像素时钟为单位*/__u32pixclock; /*像素时钟(⽪秒)*/__u32 left_margin; /*⾏切换,从同步到绘图之间的延迟*/__u32right_margin; /*⾏切换,从绘图到同步之间的延迟*/__u32upper_margin; /*帧切换,从同步到绘图之间的延迟*/__u32lower_margin; /*帧切换,从绘图到同步之间的延迟*/__u32hsync_len; /*⽔平同步的长度*/__u32 vsync_len; /*垂直同步的长度*/__u32 sync;__u32 vmode;__u32 rotate;__u32reserved[5]; /*保留*/}1.写驱动程序:(驱动设置:参考⾃带的LCD平台驱动drivers/video/s3c2410fb.c )1.1 步骤如下:在驱动init⼊⼝函数中:1)分配⼀个fb_info结构体2)设置fb_info 2.1)设置固定的参数fb_info-> fix 2.2) 设置可变的参数fb_info-> var 2.3) 设置操作函数fb_info-> fbops 2.4) 设置fb_info 其它的成员3)设置硬件相关的操作 3.1)配置LCD引脚 3.2)根据LCD⼿册设置LCD控制器 3.3)分配显存(framebuffer),把地址告诉LCD控制器和fb_info4)开启LCD,并注册fb_info: register_framebuffer() 4.1) 直接在init函数中开启LCD(后⾯讲到电源管理,再来优化) 控制LCDCON5允许PWREN信号, 然后控制LCDCON1输出PWREN信号, 输出GPB0⾼电平来开背光, 4.2) 注册fb_info在驱动exit出⼝函数中:1)卸载内核中的fb_info2) 控制LCDCON1关闭PWREN信号,关背光,iounmap注销地址3)释放DMA缓存地址dma_free_writecombine()4)释放注册的fb_info1.2 具体代码如下:#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <asm/io.h> //含有iomap函数iounmap函数#include <asm/uaccess.h>//含有copy_from_user函数#include <linux/device.h>//含有类相关的处理函数#include <linux/fb.h> //含有fb_info结构体定义//#include <asm/dma-mapping.h> //含有dma_free_writecombine宏定义#include <linux/dma-mapping.h> //含有dma_free_writecombine宏定义#include <linux/platform_device.h>//含有平台设备总线模型相关变量#include <linux/mm.h>#include <linux/slab.h>//#include <linux/module.h>//#include <linux/kernel.h>//#include <linux/errno.h>//#include <linux/string.h>//#include <linux/mm.h>//#include <linux/slab.h>//#include <linux/delay.h>//#include <linux/fb.h>//#include <linux/init.h>//#include <linux/dma-mapping.h>//#include <linux/interrupt.h>//#include <linux/workqueue.h>//#include <linux/wait.h>//#include <linux/platform_device.h>//#include <linux/clk.h>//#include <asm/io.h>//#include <asm/uaccess.h>//#include <asm/div64.h>//#include <asm/mach/map.h>//#include <asm/arch/regs-lcd.h>//#include <asm/arch/regs-gpio.h>//#include <asm/arch/fb.h>/*lcd控制寄存器放在⼀个结构体⾥⾯*/struct lcd_regs {unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;unsigned long lcdsaddr1;unsigned long lcdsaddr2;unsigned long lcdsaddr3;unsigned long redlut;unsigned long greenlut;unsigned long bluelut;unsigned long reserved[9];unsigned long dithmode;unsigned long tpal;unsigned long lcdintpnd;unsigned long lcdsrcpnd;unsigned long lcdintmsk;unsigned long lpcsel;};static struct fb_info *s3c_mylcdfb_info;//fb_info结构体static volatile unsigned long *gpbcon;//GPB0⽤于lcd背光的控制static volatile unsigned long *gpbdat;//GPB0⽤于lcd背光的控制static volatile unsigned long *gpccon;static volatile unsigned long *gpdcon;static volatile unsigned long *gpgcon;//GPG4⽤于lcd电源static volatile struct lcd_regs* lcd_regs;//lcd寄存器static u32 pseudo_palette[16]; //调⾊板内存/* from pxafb.c */static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf){chan &= 0xffff; //取出16bit的数据chan >>= 16 - bf->length; //return chan << bf->offset;}static int s3c_mylcdfb_setcolreg(unsigned int regno, unsigned int red,unsigned int green, unsigned int blue,unsigned int transp, struct fb_info *info){unsigned int val;if (regno > 16)return1;/* ⽤red,green,blue三原⾊构造出val */val = chan_to_field(red, &info->var.red);val |= chan_to_field(green, &info->var.green);val |= chan_to_field(blue, &info->var.blue);//((u32 *)(info->pseudo_palette))[regno] = val;pseudo_palette[regno] = val;return0;}static struct fb_ops s3c_mylcdfb_ops = { //操作函数结构体.owner = THIS_MODULE,.fb_setcolreg = s3c_mylcdfb_setcolreg,//待会设置,这个是调⾊板,如果使⽤⼩于16bit的像素需要⽤到 .fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,};static int lcd_drv_init(void){/*1、分配⼀个fb_info*/s3c_mylcdfb_info = framebuffer_alloc(0,NULL);//size为额外分配的⼤⼩,这⾥不需要,所以设为0if(s3c_mylcdfb_info==NULL){printk("unframebuffer_alloc\n");return1;}/*2、设置*//*2.1 设置固定的参数*/strcpy(s3c_mylcdfb_info->fix.id, "mylcd");//名字//s3c_mylcdfb_info->fix.smem_start = ;//显存的物理起始地址,后⾯设置s3c_mylcdfb_info->fix.smem_len = 480*272*16/8;//单位为字节,每个像素点占⽤16bit :565,显存的⼤⼩ s3c_mylcdfb_info->fix.type = FB_TYPE_PACKED_PIXELS;//LCD类型,填充像素的类型 tft//s3c_mylcdfb_info->fix.type_aux= //附加的LCD类型,不需要设置s3c_mylcdfb_info->fix.visual = FB_VISUAL_TRUECOLOR;//视觉类型,选择真彩⾊s3c_mylcdfb_info->fix.line_length = 480*16/8; //⼀⾏的长度,单位为字节// s3c_mylcdfb_info->fix.mmio_start = //控制lcd的寄存器的物理地址// s3c_mylcdfb_info->fix.mmio_len = //控制lcd的寄存器的⼤⼩/*2.2 设置可变的参数*/s3c_mylcdfb_info->var.xres = 480;//x⽅向的分辨率s3c_mylcdfb_info->var.yres = 272;//y⽅向的分辨率s3c_mylcdfb_info->var.xres_virtual = 480;//x⽅向的虚拟分辨率s3c_mylcdfb_info->var.yres_virtual = 272;//y⽅向的虚拟分辨率s3c_mylcdfb_info->var.bits_per_pixel = 16;//每个像素的⼤⼩,单位为bits3c_mylcdfb_info->var.grayscale = 0;//灰度值s3c_mylcdfb_info->var.red.length = 5;//红⾊像素占⽤的长度,单位bits3c_mylcdfb_info->var.green.length = 6;//绿⾊像素占⽤的长度,单位bits3c_mylcdfb_info->var.blue.length = 5;//蓝⾊像素占⽤的长度,单位bits3c_mylcdfb_info->var.red.offset= 11;//红⾊像素在16bit中的偏移值s3c_mylcdfb_info->var.green.offset= 6;//绿⾊像素在16bit中的偏移值s3c_mylcdfb_info->var.blue.offset=0;//蓝⾊像素在16bit中的偏移值s3c_mylcdfb_info->var.red.msb_right= 0;//低位在前还是⾼位在前,⼀般⾼位在前,也就是⼩端模式s3c_mylcdfb_info->var.green.msb_right= 0;s3c_mylcdfb_info->var.blue.msb_right=0;s3c_mylcdfb_info->var.activate = FB_ACTIVATE_NOW;//使⽤默认参数,显存⽴刻⽣效/*2.3 设置操作函数*/s3c_mylcdfb_info->fbops = &s3c_mylcdfb_ops;/*2.4 其它的⼀些设置 */s3c_mylcdfb_info->pseudo_palette = pseudo_palette;//调⾊板的地址//s3c_mylcdfb_info->screen_base = ;//显存的虚拟基地址s3c_mylcdfb_info->screen_size = 480*272*16/8;//单位为字节,每个像素点占⽤16bit :565,显存的⼤⼩/*3、硬件相关的操作 *//*3.1、配置GPIO⽤于LCD*/gpbcon = ioremap(0x56000010, 8);//将实际的寄存器地址转换为虚拟地址gpccon = ioremap(0x56000020 , 4);gpdcon = ioremap(0x56000030 , 4);gpgcon = ioremap(0x56000060 , 4);gpbdat = gpbcon + 1;*gpccon = 0xaaaaaaaa; /* GPIO管脚⽤于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND */*gpdcon = 0xaaaaaaaa; /* GPIO管脚⽤于VD[23:8] */*gpbcon &= ~(3); /* GPB0设置为输出引脚 */*gpbcon |= 1;*gpbdat &= ~1; /* 输出低电平关闭LCD背光 */*gpgcon |= (3<<8); /* GPG4⽤作LCD_PWREN 电源*//*3.2、根据LCD⼿册设置LCD控制器,⽐如VCLK的频率等 */lcd_regs = ioremap(0X4D000000 , sizeof(struct lcd_regs));/** bit[17:8] : VCLK = HCLK / [(CLKVAL+1) x 2]* 10M = 100M/[(CLKVAL+1) x 2]* CLKVAL = 4** bit[6:5] :PNRMODE = 11显⽰模式,选择TFT模式** bit[4:1] :BPPMODE = 1100;像素=16bit 565** bit[0] :ENVID = 0;先关闭LCD控制器*/lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0c<<1);///** [31:24] : VBPD = 帧同步信号发出后,过多长时间开始显⽰数据,单位为⾏,理解为1⾏的时间* 看LCD⼿册tvb = VBPD + 1 = 2;所以VBPD = 1** [23:14]:LINEVAL + 1= 272;,所以LINEVAL = 271;垂直⽅向尺⼨,多少⾏** [13:6]:VFPD = ⼀帧的数据传输完成之后,过多长时间开始下⼀帧数据的帧同步信号,单位为⾏,理解为1⾏的时间 * 看LCD⼿册tvf = VFPD + 1 = 2;所以VFPD = 1** [5:0]:VSPW = 帧同步信号的脉冲宽度,单位为⾏* 看LCD⼿册tvp = VSPW + 1 =10;所以VSPW = 9*/lcd_regs->lcdcon2 = (1<<24) | (271<<14) | (1<<6) | (9<<0);/** [25:19]:HBPD = ⾏同步信号发出后,经过多少个VCLK,才发送像素的数据,单位为VCLK* 看LCD⼿册thb = HBPD + 1 = 2;所以HBPD=1** [18:8]:HOZVAL + 1 = 480,所以 HOZVAL = 479;⽔平⽅向尺⼨,多少列**[7:0]:HFPD = ⼀⾏的像素数据传输完成之后,经过多长时间,才能发送下⼀个⾏同步信号,单位为VCLK*看LCD⼿册thf = HFPD + 1 = 2;所以HFPD = 1;*/lcd_regs->lcdcon3 = (1<<19) | (479<<8) | (1<<0);/** [7:0]:HSPW = ⾏同步信号的脉冲宽度,单位为VCLK* 看LCD⼿册thp = HSPW + 1 = 41;所以HSPW = 40**/lcd_regs->lcdcon4 = (40<<0);/** [11] :FRM565 = 1;16位模式的格式 R:G:B = 5:6:5* [10] :INVVCLK = 0;VCLK在哪个边沿取数据 = 0表⽰下降沿取数据* [9] :INVVLINE = 1;⾏同步信号是否需要反转= 1需要反转* [8] :INVVFRAME = 1;帧同步信号是否需要反转= 1需要反转* [7] :INVVD = 0; 数据是否需要反转* [6] :INVVDEN = 0; 数据使能信号是否需要反转* [5] :INVPWREN = 0;电源使能信号是否需要反转* [4] :INVLEND = 0;⾏结束信号是否需要反转* [3] :PWREN = 0;电源使能信号,先不使能* [2] :ENLEND = 1;//⾏结束信号先使能* [1:0] :BSWP 、HWSWP = 0 1;字节内部不需要交换,字节间需要交换*/lcd_regs->lcdcon5= (1<<11) | (3<<8) | (1<<2) | (1<<0);/*3.3、显存和调⾊板设置 *//**利⽤dma_alloc_writecombine分配⼀块连续的显存*/s3c_mylcdfb_info->screen_base = dma_alloc_writecombine(NULL,s3c_mylcdfb_info->screen_size,(&(s3c_mylcdfb_info->fix.smem_start)),GFP_KERNEL);//返回虚拟地址if(s3c_mylcdfb_info->screen_base==NULL) //如果显存分配失败,直接返回{printk("undma_alloc_writecombine\n");return1;}/**将显存的地址告诉LCD控制器(物理地址)*/lcd_regs->lcdsaddr1 = (s3c_mylcdfb_info->fix.smem_start >> 1) & (~(3<<30));//起始地址lcd_regs->lcdsaddr2 = ((s3c_mylcdfb_info->fix.smem_start + s3c_mylcdfb_info->screen_size) >> 1) & 0x1fffff;//结束地址lcd_regs->lcdsaddr3 = (480*16/16); /* ⼀⾏的长度(单位: 2字节) *///s3c_lcd->fix.smem_start = xxx; /* 显存的物理地址 *//* 启动LCD */lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD本⾝电源 */*gpbdat |= 1; /* 输出⾼电平, 使能背光 *//*4、注册LCD*/register_framebuffer(s3c_mylcdfb_info);printk("register_framebuffer\n");return0;}static void lcd_drv_exit(void){unregister_framebuffer(s3c_mylcdfb_info);lcd_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD本⾝ */*gpbdat &= ~1; /* 关闭背光 */dma_free_writecombine(NULL, s3c_mylcdfb_info->fix.smem_len, s3c_mylcdfb_info->screen_base, s3c_mylcdfb_info->fix.smem_start);iounmap(lcd_regs);iounmap(gpbcon);iounmap(gpccon);iounmap(gpdcon);iounmap(gpgcon);framebuffer_release(s3c_mylcdfb_info);}module_init(lcd_drv_init);module_exit(lcd_drv_exit);MODULE_LICENSE("GPL");2.重新编译内核,去掉默认的LCDmake menuconfig ,进⼊menu菜单重新设置内核参数:进⼊Device Drivers-> Graphics support:<M> S3C2410 LCD framebuffer support //将⾃带的LCD驱动设为模块, 不编进内核中然后make uImage 编译内核make modules 编译模块为什么要编译模块?因为LCD驱动相关的⽂件也没有编进内核,⽽fb_ops⾥的成员fb_fillrect(), fb_copyarea(), fb_imageblit()⽤的都是drivers/video下⾯的3个⽂件,所以需要这3个的.ko模块,如下图所⽰:3.挂载驱动将编译好的LCD驱动模块和drivers/video⾥的3个.ko模块放⼊nfs⽂件系统⽬录中然后烧写内核, 先装载3个/drivers/video下编译好的模块,再来装载LCD驱动模块挂载LCD驱动后, 如下图,可以通过 ls -l /dev/fb* 命令查看已挂载的LCD设备节点:4.测试运⾏测试有两种:echo hello> /dev/tty1 // LCD上便显⽰hello字段cat Makefile>/dev/tty1 // LCD上便显⽰Makeflie⽂件的内容4.1使⽤上节的键盘驱动在LCD终端打印命令⾏vi /etc/inittab //修改inittab, inittab:配置⽂件,⽤于启动init进程时,读取inittab添加->tty1::askfirst:-/bin/sh //将sh进程(命令⾏)输出到tty1⾥,也就是使LCD输出信息然后重启,insmod装载3个/drivers/video下编译好的模块,再来insmod装载LCD驱动模块,tty1设备便有了,就能看到提⽰信息:如下图,我们insmod上⼀节的键盘驱动后,按下enter键,便能在LCD终端上操作linux了从上图可以看到按下enter键,它就启动了⼀个进程号772的-sh进程,如下图发现这个-sh的描述符都指向了tty1:以上内容转载⾃。
LCD的驱动控制实验
本实验参数设置
single
scan LCD 分辨率:640×480 TFT 16 BPP (Bits Per Pixel) mode
RGB 5:6:5 一级缓冲大小 16bit×(640×480) 二级缓冲大小 24bit×(640×480)
建立两个一级缓冲,一个二级缓冲:
与ARM自带LCD驱动器有关的寄存 器
LCDSADDR1
Frame buffer start address 1 register LCDSADDR2 Frame buffer start address 2 register LCDSADDR3 Virtual screen address set
LCDSADDR2
LCDBASEL
These bits indicate A[21:1] of the end address of the LCD frame buffer.
程序流程
初始化实验开发板 初始化LCD 修改二级显存
刷新LCD屏幕
待机
LCD初始化程序流程
设置GPIO(GPC,GPD) 关闭LCD输出 设置LCD控制寄存器(LCDCON1-5)
Le bits indicate A[30:22] of the bank location for the video buffer in the system memory. LCDBASEU These bits indicate A[21:1] of the start address of the LCD frame buffer.
实验原理
Frame
Buffer通常是在内存空间中由连续 的字节组成.显示器操作:从左到右逐点象素 扫描,从上到下逐行扫描.这使得显示屏上的 象素同Frame Buffer中的内存空间建立了 一对一映射.
lcd 驱动方式和原理
LCD(Liquid Crystal Display,液晶显示器)驱动方式是指用于控制LCD显示像素的电流或电压的方法。
LCD的工作原理是通过改变液晶分子的排列状态来调节光的透过率,从而实现图像显示。
以下是几种常见的LCD驱动方式和原理:1. 静态驱动方式(Static Driven Method):静态驱动方式是最简单的驱动方式之一。
每一个液晶像素点由一个独立的驱动电路控制,通过施加不同的电压或电场来改变液晶的取向,从而实现显示效果。
静态驱动方式适用于小尺寸的LCD,但对于大尺寸LCD来说,由于需要大量的驱动电路,使得整体结构复杂,成本较高。
2. 动态驱动方式(Dynamic Driven Method):动态驱动方式采用行列交替驱动的方法。
将液晶显示屏分割成若干行和列,通过周期性地切换不同的行和列的驱动电压,来逐行、逐列地更新显示内容。
这种方式可以减少所需的驱动电路数量,降低成本,并适用于大尺寸的液晶显示屏。
3. 时序控制驱动方式(Timing Control Driven Method):时序控制驱动方式通过控制驱动信号的时序来控制液晶的状态和显示内容。
时序控制驱动方式广泛应用于各种尺寸的液晶显示器,可以实现高分辨率、高刷新率和多种显示模式。
4. 被动矩阵驱动方式(Passive Matrix Driven Method):被动矩阵驱动方式是一种简单且低成本的驱动方法。
它通过将液晶像素点排列成行列交错的结构,使用行和列上的电极来控制每个像素点的状态。
然而,被动矩阵驱动方式在显示质量、响应速度和观看角度方面存在一定的限制。
5. 主动矩阵驱动方式(Active Matrix Driven Method):主动矩阵驱动方式采用了TFT(Thin-Film Transistor,薄膜晶体管)技术,每个像素点都有一个对应的TFT,通过控制这些TFT 的导通和截止来改变液晶的取向,从而实现高品质的显示效果。
基于uCOSⅡ的LCD驱动编写
天津电子信息职业技术学院课程设计课题名称基于uCOSⅡ的LCD驱动编写姓名王浩学号35班级电信S10-1专业电子信息工程成绩完成日期2012-06-01基于uCOSII的LCD驱动编写摘要LCD是嵌入式操作系统的重要组成部分,是系统和用户之间进行交互和信息交换的媒介,它实现信息的内部形式与人类可以接受形式之间的转换。
用户可以只通过LCD监测系统内部运行状态,然后作出相应的处理。
因而具有良好的人机界面的嵌入式操作系统能过很好的完成系统开发、生产生活的需要。
S3C44B0X 中具有内置的LCD 控制器,它能将显示缓存(在SDRAM存储器中)中的LCD 图像数据传输到外部的LCD驱动电路上的逻辑功能。
它支持单色、4级、16级灰度LCD显示,以及256彩色LCD显示。
在显示灰度时,它采用时间抖动算法(time-based dithering algorithm)和帧率控制 (Frame Rate Control)方法,在显示彩色时,它采用RGB的格式,即RED、GREEN、BLUE,三色混合调色。
通过软件编程,可以实现233或332的RGB调色的格式。
对于不同尺寸的LCD显示器,它们会有不同的垂直和水平象素点、不同的数据宽度、不同的接口时间及刷新率,通过对LCD 控制器中的相应寄存器写入不同的值,来配置不同的LCD 显示板。
LCD能够正常工作得益于软硬件的协同工作,S3C44B0X集成了LCD的控制器,即不带驱动电路的LCD显示模块,驱动程序需要根据用户需要来自行添加。
u C / O S 是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统,在具体应用中稳定可靠,并且支持uIP TCP/IP协议栈、ucGUI等,可扩展性强,功能强大。
因此,在uC/OS II下写的LCD驱动具有较好的实时性和稳定性,功能强大。
关键词:嵌入式系统;LCD显示;驱动电路;目录一、系统设计 (4)1.课题目标及总体方案 (4)2.LCD驱动程序组成 (4)3.UCOSII操作系统下添加LCD驱动程序 (5)4.应用程序 (5)二、实验结果测试 (6)三、总结 (7)四、心得体会 (8)五、参考文献 (9)六、附录 (9)一、系统设计1.课题目标及总体方案首先学习了解LCD的驱动程序,然后在移植好的UCOSII项目中添加LCD的驱动程序, 最后能够在uCOSII下,编写LCD应用任务的简单编程实例,来检验LCD驱动程序的完好度。
LCD驱动方式及显示原理
LCD驱动方式及显示原理LCD (Liquid Crystal Display)是一种平板显示器技术,广泛应用于电子设备的显示屏上。
LCD驱动方式及显示原理是如何实现LCD屏幕的像素控制和图像显示的关键。
下面将详细介绍LCD驱动方式及显示原理。
1.LCD驱动方式:(1)数字式驱动数字式驱动是最常用的驱动方式,通过数字信号来对LCD显示器的像素进行控制。
-静态驱动:使用固定的电压,例如使用一个稳定的电压源,用于控制LCD屏幕的每个像素。
-动态驱动:分类为1/240、1/480、1/960、1/1200等等格式。
它在特定的时钟频率下,快速切换电压,使液晶分子在两种状态之间变化。
(2)模拟式驱动模拟式驱动是通过模拟信号来控制LCD显示器的像素。
它通常用于LCD屏幕上像素点较少的低分辨率显示设备。
-逐行驱动:按照行顺序逐个驱动LCD的所有像素点。
-平面驱动:将整个屏幕划分为很多平面,并且同时驱动每个平面的像素。
2.LCD显示原理:LCD显示原理涉及到电光效应和液晶分子的操控。
(1)电光效应当电压施加在液晶材料上时,其分子将发生旋转或重新排列,从而改变透过的光的方向,从而改变液晶材料的透过性。
液晶显示屏架构中的液晶分子通常被安排成两个平行的玻璃衬底之间的夹层。
当无电压施加在液晶分子上时,它们会形成同心圆状。
而当电压施加在液晶分子上时,它们会改变形状,通常是旋转成平行或垂直的状态。
(2)液晶分子的操控液晶显示屏的构造中包含两片玻璃衬底,每个衬底上都有一个导电层。
当电压施加在导电层上时,它会在液晶分子中产生电场。
根据电场的大小和方向,液晶分子将旋转或重新排列,改变透光的方向,并实现对光的控制。
3.LCD驱动流程:(1)数据输入:控制器将图像数据(RGB值)传输到LCD驱动电路。
(2)数据解码:LCD驱动电路将输入的图像数据转换为液晶分子可理解的电信号。
(3)电场操控:通过电信号操控液晶分子的排列,将其使之平行或垂直。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.3 数据线:也就是我们说的RGB信号线,不过需要与硬件工程是配合的是他采用了哪种接线方法,24位16位或其它。对于16位TFT屏又有两种方式,在写驱动前你要清楚是5:6:5还是5:5:5:I,这些与驱动的编写都有关系
3.14 LCD 控制器 2,对于 TFT 屏必须要填
看一下图二 LCD屏资料,对比一下得出如下信息:
LCD2_VBPD:
Vertical back po
LCD2_VFPD:
Vertical front porc
LCD2_VSPW:
Vsync Valid width
关于LINEVAL在程序的后面将
c) red: {offset: 11, length: 5 } 偏移量为11,长度为5,我们从那个RGB中提取出来便是 10101
d) 我们得到了一个RGB值为21:45:25,就是这个颜色
e) 那么反过来,有了RGB的值我们该如何,因为RGB的有效位数都不足一个字节(8位),那我们只能忍痛割爱了,舍弃掉低位数据,代码如下:
LCD驱动编写小结
3.1 背光:对于大部分的彩色LCD一定要接背光,我们才能看到屏上的内容;
3.2 控制信号:不同的LCD厂商对于控制信号有不同的叫法,
VFRAME:LCD控制器和LCD驱动器之间的帧同步信号。该信号告诉LCD屏的新的一帧开始了。LCD控制器在一个完整帧显示完成后立即插入一个VFRAME信号,开始新一帧的显示;
3.24 有了上面的基础我们就可以很好的理解这个语句了:
即FrameBuffer的大小=LCD屏的宽度 * LCD屏的高度 * 每像素的位数 / 每字节的位数
例如,一个320*240的黑白平,FrameBuffer的大小为
320 * 240 * 1 / 8 = 9600 (字节)
而一个320 * 240的16位色LCD的FrameBuffer的大小则为
3.8 好了,在硬件工程师的帮助下,硬件接好了,那就该我们做软件的干活了,编写驱动吧
3.9 让我们首先看一下RGB数据结构的定义
static struct lcd_rgb ***_lcd_rgb_16 = {
red: //-- offset:11 length:5
green: //-- offset:5 length:6
3.20. GUI程序的编写
3.21 其实要在LCD上显示图像,说白了就是把数据(包含颜色)写到FrameBuffer中对应的位置就可以了用mmap函数使用户空间的一段地址关联到设备内存(FrameBuffer)上。无论何时,只要程序在分配的地址范围内进行读取或者写入,实际上就是对设备的访问,使用 mmap 可以既快速又简单地访问显示卡的内存。对于象这样的性能要求比较严格的应用来说,直接访问能给我们提供很大不同。
否则你的LCD可能没有任何显示哦(对于TFT屏不需要这个语句)
3.19. 驱动写好了,重新Make,下载就可以了。如果一切顺利,在TFT屏或256色的CSTN屏上会有一个漂亮的小蜻蜓(应该是蜻蜓吧)出现。注意,并不是蜻蜓出现了就代表你的驱动OK了,还要用GUI程序做进一步的测试,因为某一个或几个参数虽然不正确,但是仍然能够看到小蜻蜓的,但显示图形的时候就有问题了。另外,在驱动CSTN到12位色的时候,我们在屏上看不到小蜻蜓(我的N块CSTN屏上都没见到小蜻蜓),我想,可能是armLinux本身不支持12位色显示,或者我们某些地方没搞对的原因吧,但这不代表你的驱动有问题,用GUI程序写FrameBuffer,看看能否的到正确的结果。
blue: //-- offset:0 length:5
transp: //-- offset:0 length:0
};
3.10 这是对16位色的RGB颜色进行定义,R:G:B:I = 5:6:5:0,即我们常说的565显示方式。
3.11 随便写一个16位数据的颜色数据(为了分析的方便,我把它写成二进制)
经过分析,我们知道了如何设置LCD2:
3.15 LCD 控制器 3
对于 TFT 屏,很容易将 HBPD 和 HFPD 找出来,如下
porch 典型值为 37
porch 典型值为 32
此处暂时不管
LCD3_HBPD:
Horizontal back
LCD3_HFBD:
Horizontal back
3.23 另外,我还想多啰嗦两句,FrameBuffer的像素点与LCD屏上的像素点的对应关系 ,深入了解一下对程序的理解可能会更清楚一点。我们知道黑白(2色)颜色用0和1就可以表示了,也就是1位数据就可以了,那1个字节就可以表示8位数据,假如这个字节是10101010,FrameBuffer的偏移地址为0,则在LCD屏上便会显示出4个黑点,黑点中间会有4个白点出现(假如1是黑色);对于4色则用00、01、10、11就可以表示出四种颜色,即用两位数据可以表示一位数据,那同样是10101010,则对应于LCD屏上则显示的是颜色值为10,长度为4(8/2)的一条直线;同理,对于8位色(256色),则8位数据才能表示出一个点的颜色值,10101010在LCD屏上就只能显示为颜色值为10101010的点了。
这两个寄存器的设置比较重要,在此我给出12位色CSTN屏和16位色TFT的设置代码:
g.RGB Loopup Table Register
这三个寄存器的在驱动256色CSTN屏的时候需要使用,我在别的芯片上使用过,因为这颗芯片支持12位色,所以没有去调试,我给出两组可能的值:
S3C44B0上的
与驱动有关的一张表,
3.13 看一下LCD寄存器1的设置。
LINECNT --- 这是一个只读的数据,我们当然没有必要理它
CLKVAL --- 这可是一个很有用的参数,其实没必要管它后面的计算,我们可以通过实际的测试来得出一个有效的值,对于PNRMODE --- 这个应该不用多做解释,大家一看都明白了,对于TFT屏,只能设置成11,而对于CSTN屏,可能需要根据实际屏的信息去设置,我遇到的屏都设置成10,即8bit单扫描模式。对于4bit单扫描、4bit双扫描、8bit单扫描的BPPMODE --- 这个参数更不用多说了吧,就是设置屏的颜色位数喽。
d.颜色信息的字节交换控制位:BSWP、HWSWP
这两位用来控制字节交换和半字交换,主要用来大小头的问题,如果
输出到屏上的汉字左右互换了,或者输出到屏上的图花屏了,可以更改这个选项。
e.我的这块TFT的信息设置如下:lcdcon5,一块 CSTN 屏的信息:lcdcon5
f.FrameBuffer 起始寄存器 2 和 FrameBuffer 起始寄存器 3
3.6 最后还有一个问题,有些LCD屏还需要一颗伴侣芯片,就是S3C2410手册中的那颗LPC3600。这可能在LCD的手册中都有论述吧,我没有遇到过这样的屏,所以也不是很清楚,不过现在的大部分LCD屏应该都不需要这个讨厌的家伙了
3.7 还得提醒大家一下,S3C2410到LCD屏的连线千万千万别超过0.5米,否则会给你带来麻烦,我也是吃过苦头的,LCD屏上面的部分显示任何信息都是正确的,而只有屏的底部会有时正确有时错误,折腾了好一阵,才知道是连线太长的缘故!
VLINE:LCD控制器和LCD驱动器之间的线同步脉冲信号,该信号用于LCD驱动器将水平线(行)移位寄存器的内容传送给LCD屏显示。LCD控制器在整个水平线(整行)数据移入LCD驱动器后,插入一个VLINE信号;
VCLK:LCD控制器和LCD驱动器之间的像素时钟信号,由LCD控制器送出的数据在VCLK的上升沿处送出,在VCLK的下降沿处被LCD驱动器采样;
对于HOZVAL同样会在后面提到,
经过分析,我们知道了如何设置LCD3:
3.16 LCD 控制器 4
对
_HSPW:
典型值为 5意思,有什么作用,我从来不动它,只取它最初的那个值13
经过分析,我们知道了如 何设置 LCD4:
r = R & 0xF8;
g = G & 0xFC;
b = B & 0xF8;
high = r | (g<<5);
low = (g<<3) | (b>>3);
color= (high << 8) | low;
记住,这段代码在GUI程序中是有用的
3.12 很重要的:
a)颜色位数,bpp:16如果你的LCD屏是TFT的,那一般都可以达到16位色或24位色,这也要看硬件怎么连接了,根据情况进行设置即可;
3.25 TFT屏16位色的画点函数
3.26 5) TFT屏16位色下显示24色位图函数
320 * 240 * 16 / 8 = 153600(字节
RGB = 10101101 10111001 根据上面的结构定义我们来分析一下RGB各是多少(因为没有透明色,我们不去分析)
a) blue: {offset: 0, length: 5} 偏移量为0,长度为5,我们从那个RGB中提取出来便是 “11001”
b) green:{offset: 5, length: 6} 偏移量为5,长度为6,我们从那个RGB中提取出来便是101 101
3.4 要注意一下LCD的电源电压,对于手持设备来说一般都为5V或3.3V,如果LCD的需要的电源电压是5v,那就要注意,电压只有3.3V的电压需要提高到5V,否则你可能能将屏点亮,但显示的图像要等到太阳从西边出来的那一天才能正常,呵呵,我可吃过苦头的哦!