LCD电子广告屏

时间:2019-05-14 04:49:02下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《LCD电子广告屏》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《LCD电子广告屏》。

第一篇:LCD电子广告屏

LCD电子广告屏设计

一、设计目的为了进一步巩固学习的理论知识,增强学生对所学知识的实际应用能力和运用所学的知识解决实际问题的能力,开始为期两周的课程设计。通过设计使学生在巩固所学知识的基础之上具有初步的单片机系统设计与应用能力。

1、通过本设计,使学生综合运用《单片机技术原理与应用》、《DSP原理与 用》《C语言程序设计》以及《数字电路》、《模拟电路》等课程的内容,为以后从事电子产品设计、软件编程、系统控制等工作奠定一定的基础。

2、学会使用KEIL C和PROTEUS等软件,用C语言或汇编语言编写一个较完 整的实用程序,并仿真运行,保证设计的正确性。

3、了解单片机接口应用开发的全过程:分析需求、设计原理图、选用元器 件、布线、编程、调试、撰写报告等。

二.设计内容

1、设计要求

单片机控制的LCD 1602的电子广告牌

用单片机控制字符型LCD 1602显示字符信息“Hello everyone!”和“Welcome to Harbin”。字符信息“Hello everyone!”、“Welcome to Harbin”分别从LCD 1602右侧第一行、第一行滚动移入,然后再从左侧滚动移出,循环显示。

2、设计思路

液晶模块用命令控制显示由模块本身已经给出,AVR、LCD 的VSS、VDD、VEE 不需连接,默认VSS=0V、VDD=5V、VEE=-5V、GND=0V,液晶模块与单片机的连接不采用添加多个与非门的方式,而采用更直接、清晰的方式,使WR、RD直接与LCD的R/W、RS相连,使能端与P3^5相连,由软件给出下降沿。

3、功能说明

1)给LCD写命令、送数据等均需要进行选中寄存器、发送命令或数据代码、使能端有效等过程,若逐一写出会使程序混乱冗长,因此将写命令、写数据、初始化等分别封装在子函数中,方便随时调用。

2)为实现滚动显示,使用命令打开整体显示移动。

3)显示字母只需将相应的ASCII代码发送给LCM即可,将需要显示的字符直 接设为数组中的元素,显示时逐一写入液晶。

4)若数组中只有相应的字符,显示的末尾会出现预料之外的字符,因此加入足 够的空格避免这种现象发生。

5)为实现循环不断显示的功能,只需将函数整体放入while(1)中即可,但应注 意下一次循环开始前将DDRAM的地址回复为第一行。

四.实验原理图

三、硬件电路元件介绍

1、AT89C51单片机:

AT89C51是一种低电压、高性能CMOS 8位微处理器,它自带4K字节闪存可编程可擦除只读存储器(FPEROM—Flash Programmable and Erasable Read Only Memory),俗称单片机。单片机的可擦除只读存储器可以反复擦除1000次。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多功能8位CPU和闪存存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。AT89C系列单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。它的部分引脚功能介绍如下。

P0口:P0口为一个8位漏级开路双向I/O口。当P1口的管脚第一次写1时,被定义为高阻输入。P0口能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

P1口:P1口是一个内部提供上拉电阻的8位双向I/O口。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。

P2口:P2口为一个内部上拉电阻的8位双向I/O口,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

P3口:P3口管脚是8个带内部上拉电阻的双向I/O口。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输出,由于外部下拉为低电平,它将输出电流。

RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

2、液晶模块

液晶模块简单点说就是屏+背光板+PCB板+铁框。

电力终端、仪器仪表等的显示部件就是液晶模块,其地位相当于CRT中的显像管。

其它部分包括电源电路,信号处理电路等,当然还有外壳什么的。

模块主要分为屏和背光灯组件。两部分被组装在一起,但工作的时候是相互独立的(即电路不相关)。

液晶显示的原理是背光灯组件发出均匀的面光,光通过液晶屏传到我们的眼睛里。屏的作用就是按像素对这些光进行处理,以显示图像。

3、排阻

排阻,是一排电阻的简称,就是若干个参数完全相同的电阻,它们的一个引脚都连到一起,作为公共引脚,其余引脚正常引出。内存在处理、传输数据时会产生大小不一的工作电流。而在内存颗粒走线的必经之处安装一排电阻,则能够帮助内存起到稳压作用,让内存工作更稳定。从而提升内存的稳定性,增强内存使用寿命。

四、软件部分的程序流程图

五、源程序清单

C语言程序: #include

#define uchar unsigned char #define uint unsigned int #define LCDPORT P0 uchar code tab[]=“Hello everyone!”;

uchar code tab1[]=“Welcome to Harbin ”;//字符后面加若干个空格,防止滚动显示时出现不该出现的字符

sbit LCDE=P3^5;sbit LCDRW=P3^6;sbit LCDRS=P3^7;

void WriteCMD(uchar);

//定义写命令函数

void init();

//定义初始化函数

void WriteData(uchar);

//定义写数据函数

void Delay();

//定义延迟函数

五、源程序清单

C语言程序:

#include

#define uchar unsigned char #define uint unsigned int

#define LCDPORT P0 uchar code tab[]=“Hello everyone!

”;

uchar code tab1[]=“Welcome to Harbin

”;//字符后面加若干个空格,防止滚动显示时出现不该出现的字符

sbit LCDE=P3^5;sbit LCDRW=P3^6;sbit LCDRS=P3^7;void WriteCMD(uchar);

//定义写命令函数

void init();

//定义初始化函数

void WriteData(uchar);

//定义写数据函数

void Delay();

//定义延迟函数 void mydelay(int);

void main()

{ uint i;

//定义无符号整形变量

init();

//液晶模块的初始化

while(1)

//使之一直进行滚动显示程序,不断循环

{ for(i=0;i<32;i++){

WriteData(tab[i]);

//显示第一行字符

mydelay(50);

//每显示一个字符后停留一会,越过液晶的“忙”状态

}

mydelay(50);

WriteCMD(0x01);

//清屏,准备进行下一行显示

WriteCMD(0x80+0x40+15);//改变DDRAM的地址,更改为第二行末尾,从此处开始进入字符

for(i=0;i<33;i++)

//开始输入第二行字符

{ WriteData(tab1[i]);

mydelay(50);

}

mydelay(50);

WriteCMD(0x01);

WriteCMD(0x80+15);

//DDRAM的地址改回第一行,准备 进入下一次循环,显示重新开始

} }

void Delay()

{

uint uiCount;

for(uiCount=0;uiCount<250;uiCount++);}

void WriteCMD(uchar Command)

//写命令函数,用于修改液晶的状态 寄存器

{ Delay();

//先延时,越过液晶“忙”状态

LCDE=1;

//使能端先置1

LCDRS=0;

//设置RS为0,打开指令寄存器

LCDRW=0;

//设置为写寄存器状态

LCDPORT=Command;

//输出命令

LCDE=0;

//使能端由1变0,出现下降沿有效,执行命令

}

void WriteData(uchar dat)

//写数据函数,用于提供液晶的显示 的字符

{

Delay();

LCDE=1;

//把LCD改为写入数据状态 LCDRS=1;

LCDRW=0;

LCDPORT=dat;

//再输出数据

LCDE=0;

//使能端有效,显示数据 }

void init()

//初始化程序,模块化使程序更清晰

{

LCDRW=0;

LCDE=0;

WriteCMD(0x38);

//设置双行显示、8位数据接口

WriteCMD(0x0c);

//设置整体显示开、光标关、字符不闪烁

WriteCMD(0x07);

//设置为增量方式,整体显示移动开

WriteCMD(0x01);

//清屏

WriteCMD(0x80+15);

//设置字符进入屏幕的初始位置 } void mydelay(int x){

int i,j;

for(i=x;i>0;i--)

for(j=255;j>0;j--);}

六、仿真调试

1、软件调试

借助 Keil 和 Proteus进行单片机系统软硬件的开发、运行、仿真。由

Keil 软件集成文件管理编译环境,编译 C 语言源程序,下载、运行、调试,连接和定位目标文件和库,创建 HEX 文件,调试目标程序。利用Proteus 完成硬件设计仿真平台,实现硬件原理图的连接,并将hex文件与89c51同频,下载运行,仿真实现。

2、仿真调试

在将电路按原理图连接好之后,通过89c51将由Keil产生的hex文件下载到单片机内。运行调试,观察液晶模块上字幕的显示,符合实验设计要求。

3、难点与解决思路

设计过程中遇到程序设计问题,网上找到视频教程学习程序的编写,以及查阅C语言课本得以解决。调试过程中发现液晶不显示,电路高低电平不符合规律现象,通过检查和改变线路部分连接解决了问题。

七、课设体会

过本次实验我们认识到了单片机的应用,并掌握了单片机的构造成分,液晶模块的应用领域。而通过自己的实际动手操作,实际查书找资料提高了自己的动手实践能力和知识的储备和应用能力,认识自己的不足并加以改正,增加字自己的成就感,为以后的工作和学习打好坚实的基础。

七、参考文献

【1】《单片机原理及应用》

主编

李建忠

【2】高锋《单片微型计算机原理与接口技术》

科学出版社

【3】朱清慧、张凤蕊、翟天嵩、王志奎

《Proteus教程——电子线路设计、制板与仿真》,清华大学出版社出版

【4】李全钊、迟荣强,《单片机原理及接口技术》,高等教育出版社出版

【5】李学礼,《基于Proteus的80C51单片机实例教程》,电子工业出版社出版

【6】周向红,《51系列单片机应用与实践教程》,北京航空航天大学出版社出版 【7】《单片机应用及技术》,电子工业出版社

【8】Proteus

入门教程

第二篇:小议LCD显示器优缺点

小议LCD显示器优缺点

LCD显示器发展至今,它有许多优缺点的,下面给大家分析一下LCD显示器它的优缺点问题。

液晶显示器的优势

传统CRT显示器发展了几十年,其技术结构原理限制了它的进一步发展。真空阴极射线管固有的几个重大缺点导致CRT显示器越来越难适应消费者对显示器要求的进一步提高,这时候,平板显示器件异军突起,其中最有可能取代CRT显示器在PC显示终端垄断的地位就是液晶显示器。

液晶显示器显示原理与CRT显示器迥然不同。相对CRT显示器来说,液晶显示器天生有拥有以下绝对优势:

1、零辐射,低耗能,散热小。液晶显示器的显示原理是通过扭转液晶像素中的液晶分子偏转角度来背景光而实现还原画面的,其不存在象CRT那样内部具有超高压元器件,不至于出现由于高压导致的x射线超标。而且机器结构电路简单,模块化以及芯片的高集成化足以把电路工作时候产生的电磁辐射降到最低。这样的设计直接降低了电路的功耗,发热量也非常小。液晶显示器虽然在工作时候可能产生轻微的电磁辐射,但是很容易通过屏蔽电路解决。而CRT显示器由于考虑到散热,不得以在屏蔽罩上钻孔导致辐射的泄露。

2、纤薄轻巧。正是液晶显示器的出现,才令手提电脑的发明成为可能。同样,桌式液晶显示器虽然在体积以及重量上要比手提电脑的都要大一些,但是,相对那又笨又重的CRT显示器来说就是小巫见大巫了。以15英寸的显示器比较,CRT显示器的深度一般接近50厘米,而大白鲨最新推出的液晶显示器NF-1500MA的深度却不到5厘米!随着消费观点以及居住环境的改变,人们对家用电器产品的体积以及重量要求越来越高。液晶显示器以其纤薄轻巧的天生优势成为最有可能打破CRT显示器垄断地位的显示器件。

3、精确还原图像。液晶显示器采用的是直接数码寻址的显示方式,它能够将显卡输出的视频信号经过AD转换之后,根据信号电平中的“地址”信号,直接将视频信号一一对应的在屏幕上的液晶像素上显示出来。而CRT显示器是靠偏转线圈产生电磁场来控制电子束在屏幕上周期性的扫描来达到显示图像的目的的。由于电子束的运动轨迹容易受到环境磁场或者地磁的影响,无法做到电子束在屏幕上的绝对定位。所以CRT显示器容易出现画面的几何失真,线性失真等无法根本消除的现象。而液晶显示器则不存在这一可能。液晶显示器可以把画面完美的在屏幕上呈现出来,而不会出现任何的几何失真,线性失真。

4、显示字符锐利。画面稳定不闪烁。液晶显示独特的显示原理决定了其屏幕上各个像素发光均匀,而且红绿蓝三基色像素紧密排列,视频信号直接送到像素背后的以驱动像素发光,因此不会出现传统的CRT显示器固有的会聚以及聚焦不良的弊病。所以,液晶显示器上的文本显示效果与传统的CRT显示器相比有着天渊之别。液晶显示器的字体非常锐利,完全没有CRT显示器显示文本时候出现的字体模糊,字体泛色等现象。而且,由于液晶显示器在通电之后就一直在发光,背光灯工作在高频下,显示画面稳定而不闪烁,有利于长时间的使用电脑。而CRT显示器是靠电子束重复撞击到荧光粉来达到发光的,这样会导致亮度周期性闪烁。长时间使用之后容易造成人眼的不适。

5、屏幕调节方便。液晶显示器的直接寻址显示方式,使得液晶显示器的屏幕调节不需要太多的几何调节和线性调节以及显示内容的位置调节。液晶显示器的可以很方便的通过芯片计算后自动把屏幕调节到最佳位置,这个步骤你只需要按一下“Auto”键就可以完成。省却了CRT显示器那而烦琐的调节。你只需要手动调节一下屏幕的亮度和对比度就可以使机器工作在最佳状态了。

液晶显示器的具有这些天生优势,已经对CRT显示器构成足够的威胁,唯一的遗憾就是由于液晶显示器的制造成本所限,目前液晶显示器的价格还是相对偏高。

液晶显示器的缺点

现在市面上有很多低价的14、15英寸液晶显示器出售,许多商家也将液晶吹捧到天上去了,诚然,液晶有不少非常明显的有点,只是由于各种原因,目前出售的低价位液晶都只是属于液晶产品里面的“低端”,本身有不少先天的缺点,下面我们来详细分析一下到底这些液晶显示器有什么缺点。

1、价格

虽然说是低价位,但是何CRT比较起来,液晶显示器的价格在显示器家族中可谓“贵族价格”,仅仅是15寸就3000元,而同尺寸的纯平显示器也不过千元左右。专家分析液晶显示屏高居不下的主要原因是在制造过程中良品率很低,导致成本无法降低。目前,能够生产液晶屏的只有日本和台湾的部分厂商,技术没有完全扩散,尚未形成大规模生产的竞争态势,并且质量上也有很大差异。在国际市场上,不同品级之间的价差可达到数十到上百美元之多。

2、接口

液晶显示器的数字接口高处不胜寒。从理论上说,液晶显示器是纯数字设备,与电脑主机的连接也应该是采用数字式接口,采用数字接口的优点是不言而喻的。首先可以减少在模数转换过程中的信号损失和干扰;减少相应的转化电路和元件;其次不需要进行时钟频率、向量的调整。

但是目前市场上出售的低价液晶显示器,大部分都是采用模拟接口,存在着传输信号易受干扰、显示器内部需要加入模数转换电路、无法升级到数字接口等问题。并且,为了避免像素闪烁的出现,必须做到时钟频率、向量与模拟信号的完全一致。

此外,液晶显示器的数字接口尚未形成统一标准,带有数字输出的显示卡在市面上并不多见。这样一来,液晶显示器的关键性的优势却很难充分发挥。就目前而言,提前消费的结果就是花高价买个摆设。

3、可视角度小

早期的液晶显示器可视偏转角度只有90度,只能从正面观看,从侧面看就会出现较大的亮度和色彩失真。现在市面上的液晶显示器可视偏转角度一般在140度左右,对于个人使用来说是够了,但如果几个人同时观看,失真的问题就显现出来了。

4、相应时间过慢

响应时间是液晶显示器的一个特殊指标。液晶显示器的响应时间指的是显示器各像素点对输入信号反应的速度,响应时间短,则显示运动画面时就不会产生影像拖尾的现象。这一点在玩游戏、看快速动作的影像时十分重要。足够快的响应时间才能保证画面的连贯。目前,市面上一般的液晶显示器,响应时间与以前相比已经有了很大的突破,一般为40ms左右。但是仍旧无法满足对3D游戏和高质量DVD电影播放的要求。

5、亮度和对比度低

要打电筒吗?这句笑话说的是液晶显示器的亮度和对比度。由于液晶分子不

能自己发光,所以,液晶显示器需要靠外界光源辅助发光。一般来讲140流明每平方米才够。有些厂商的参数标准和实际标准还存在差距。这里要说明一下,就是一些小尺寸的液晶显示器以往主要应用于笔记本电脑当中,采用两灯调节,因此它们的亮度和对比度都不是很好。

6、维修问题

液晶“坏点”问题。液晶显示屏的材料一般采用玻璃,很容易破碎,再加上每一个像素都十分细小,常常会造成个别的像素坏掉的现象,俗称“坏点”,这是无法维修的,只有更换整个显示屏,而更换的价格往往十分昂贵。

一种新品的推出,自有它优越于陈品的特色。LCD显示器的优越之处就在于它的轻巧简便和环保护眼。但是由于现阶段的LCD产品同时存在着上述缺陷,尚不能满足消费者的所有需求。在这样的产品技术前提下,我们呼吁广大消费者,不要盲目跟随时尚风潮,而是要认清自己的需求和产品的特点,做出最为客观的、实用的选择。

网站:联系:0755-29491359 *** QQ:649539816

第三篇: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.1

3.2 bmp位图格式分析

位图文件可看成由四个部分组成:位图文件头、位图信息头、彩色表和定义位图的字节阵列。如图3.2所示。

图3.2 文件头中各个段的地址及其内容如图3.3。

图3.3 位图文件头数据结构包含BMP图象文件的类型,显示内容等信息。它的数据结构如下定义: Typedef struct {

int bfType;//表明位图文件的类型,必须为BM long bfSize;//表明位图文件的大小,以字节为单位 int bfReserved1;//属于保留字,必须为本0 int bfReserved2;//也是保留字,必须为本0 long 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;//输出设备的位平面数,必须置为1 int

biBitCount;//给出每个象素的位数 long biCompress;//给出位图的压缩类型 long biSizeImage;//给出图象字节数的多少 long biXPelsPerMeter;//图像的水平分辨率 long biYPelsPerMeter;//图象的垂直分辨率

long biClrUsed;//调色板中图象实际使用的颜色素数 long biClrImportant;//给出重要颜色的索引值 } BITMAPINFOHEADER;

图3.6 BITMAPINFOHEADER数据结构

(3)对于象素小于或等于16位的图片,都有一个颜色表用来给图象数据阵列提供颜色索引,其中的每块数据都以B、G、R的顺序排列,还有一个是reserved保留位。而在图形数据区域存放的是各个象素点的索引值。它的C语言结构如图3.7所示。

图3.7 颜色表数据结构(4)对于24位和32位的图片,没有彩色表,他在图象数据区里直接存放图片的RGB数据,其中的每个象素点的数据都以B、G、R的顺序排列。每个象素点的数据结构如图3.8所示。

图3.8 图象数据阵列的数据结构(5)由于图象数据阵列中的数据是从图片的最后一行开始往上存放的,因此在显示图象时,是从图象的左下角开始逐行扫描图象,即从左到右,从下到上。

(6)对S3C2410或PXA255开发板上的LCD来说,他们每个象素点所占的位数为16位,这16位按B:G:R=5:6:5的方式分,其中B在最高位,R在最低位。而从bmp图象得到的R、G、B数据则每个数据占8位,合起来一共24位,因此需要对该R、G、B数据进行移位组合成一个16位的数据。移位方法如下: b >>= 3;g >>= 2;r >>= 3;RGBValue =(r<<11 | g << 5 | b);基于以上分析,提取各种类型的bmp图象的流程如图3.9所示

图 3.9

本篇文章来源于 Linux公社网站(本篇文章来源于 Linux公社网站(

第四篇:S3C2410 LCD驱动学习心得-6

实验过程与结果 1.Linux 源代码的修改

首先修改arch/arm/mach-smdk2410.c文件,加入以下代码。static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {.regs = {

.lcdcon1 = S3C2410_LCDCON1_TFT16BPP |

S3C2410_LCDCON1_TFT |

S3C2410_LCDCON1_CLKVAL(7),.lcdcon2 = S3C2410_LCDCON2_VBPD(4)|

S3C2410_LCDCON2_LINEVAL(319)|

S3C2410_LCDCON2_VFPD(1)|

S3C2410_LCDCON2_VSPW(1),.lcdcon3 = S3C2410_LCDCON3_HBPD(26)|

S3C2410_LCDCON3_HOZVAL(239)|

S3C2410_LCDCON3_HFPD(30),.lcdcon4 = S3C2410_LCDCON4_HSPW(13)|

S3C2410_LCDCON4_MVAL(13),.lcdcon5 = S3C2410_LCDCON5_FRM565 |

S3C2410_LCDCON5_INVVLINE |

S3C2410_LCDCON5_INVVFRAME |

S3C2410_LCDCON5_PWREN |

S3C2410_LCDCON5_HWSWP, },.lpcsel =((0xCE6)& ~7)| 1<<4,.width = 240,.height = 320,.xres = {

.min = 240,.max = 240,.defval = 240,},.yres = {

.min = 320,.max = 320,.defval = 320,},.bpp = {

.min = 16,.max = 16,.defval = 16,}, };在函数smdk2410_machine_init()函数中加入LCD的初始化代码,见下 static void __init smdk2410_machine_init(void){ s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);smdk_machine_init();} 2.编译内核,产生zImage文件,放入tftp目录下。

3.在nfs的dev目录下建立FrameBuffer的设备节点,使用命令:

mknod fb0 c 29 0 4.启动开发板,加载内核和文件系统。5.编写LCD的应用程序,程序见附录。

6.采用arm-linux-gcc 编译应用程序,产生可执行文件,放入nfs目录中。7.在开发板上运行编译好的可执行文件,便可。

8.下图是BMP位图显示程序,在S3C2410上的运行结果。

实验心得体会

1. LCD驱动的主要问题是没有LCD屏的文档,我们找不到它的那些参数值,后来只能参照Linux源码里面的其他LCD屏的参数进行实验。

2. 在驱动差错的过程中,我们采用跟踪打印的方法进行调试。刚开始的时候,内核打印出一行找不到LCD设备。我们定位到输出这行提示的代码处,进行反向跟踪。发现传给函数的设备指针为空,于是往上排查,终于发现源代码中没有定义LCD的设备信息。于是驱动问题也就顺利解决了。

3. 原来一直以为,只要LCD驱动工作正常了,内核起来的时候,液晶屏会显示出Logo。当时搞了很久一直没有,还以为是驱动的问题。后来随便写了一个LCD应用程序,竟然能用。4. 在调试过程应用程序中发现,在读取文件头的时候,如果直接定义一个bitmapfileheader为它动态分配内存:

*bmph=(bitmapfileheader*)malloc(sizeof(bitmapfileheader));然后用fread((char*)bmph,sizeof(bitmapfileheader),1,f)把文件头一次性读出来,读出来的文件头是错误的,经过调试发现原因是bitmapfileheader这个结构体中的type属性原本应该占2字节,但是被编译器在分配内存的时候进行了内存对齐的优化,给他分配了4个字节的空间,造成读文件的错误。因此在编程中要特别注意内存对齐的影响。typedef struct { WORD

type;(被优化)DWORD bfsize;DWORD reserved;DWORD offbits;} bitmapfileheader;5. 在嵌入式应用程序的移植过程中,我们原来认为ARM和PC机大小尾顺序是不同的,因此在应用程序中,也对这个差别进行了处理。当时,在调试过程中发现,PC机程序可以直接移植到ARM上,不需要任何改动。但是我们的程序,的确存在会产生大小尾问题代码(在使用fread()读入时)。这究竟是为什么?有人说,ARM是可以设置大小尾顺序的。后来这个问题也没有深究下去。

参考文献

(1)嵌入式系统设计与应用开发:郑灵翔.北京:北京航天航空大学出版社 2006

本篇文章来源于 Linux公社网站(

第五篇:S3c2410 LCD驱动学习心得

S3c2410 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屏的控制来进行。

图1.1是S3C2410内部的LCD控制器的逻辑示意图:

图1.1 REGBANK 是LCD控制器的寄存器组,用来对LCD控制器的各项参数进行设置。而 LCDCDMA 则是LCD控制器专用的DMA信道,负责将视频资料从系统总线(System Bus)上取来,通过 VIDPRCS 从VD[23:0]发送给LCD屏。同时 TIMEGEN 和 LPC3600 负责产生 LCD屏所需要的控制时序,例如VSYNC、HSYNC、VCLK、VDEN,然后从 VIDEO MUX 送给LCD屏。

1.2 TFT屏时序分析

图1.2是TFT屏的典型时序。其中VSYNC是帧同步信号,VSYNC每发出1个脉冲,都意味着新的1屏视频资料开始发送。而HSYNC为行同步信号,每个HSYNC脉冲都表明新的1行视频资料开始发送。而VDEN则用来标明视频资料的有效,VCLK是用来锁存视频资料的像数时钟。

并且在帧同步以及行同步的头尾都必须留有回扫时间,例如对于VSYNC来说前回扫时间就是(VSPW+1)+(VBPD+1),后回扫时间就是(VFPD +1);HSYNC亦类同。这样的时序要求是当初CRT显示器由于电子枪偏转需要时间,但后来成了实际上的工业标准,乃至于后来出现的TFT屏为了在时序上于CRT兼容,也采用了这样的控制时序。

图1.2 S3C2410实验箱上的LCD是一款3.5寸TFT真彩LCD屏,分辩率为240*320,下图为该屏的时序要求。

图1.3 通过对比图1.2和图1.3,我们不难看出: VSPW+1=2-> VSPW=1 VBPD+1=2-> VBPD=1 LINVAL+1=320-> LINVAL=319 VFPD+1=3-> VFPD=2 HSPW+1=4-> HSPW=3 HBPD+1=7-> HBPW=6 HOZVAL+1=240-> HOZVAL=239 HFPD+1=31-> HFPD=30 以上各参数,除了LINVAL和HOZVAL直接和屏的分辩率有关,其它的参数在实际操作过程中应以上面的为参考,不应偏差太多。

1.3 LCD控制器主要寄存器功能详解

图1.4 LINECNT :当前行扫描计数器值,标明当前扫描到了多少行。

CLKVAL :决定VCLK的分频比。LCD控制器输出的VCLK是直接由系统总线(AHB)的工作频率HCLK直接分频得到的。做为240*320的TFT屏,应保证得出的VCLK在5~10MHz之间。MMODE :VM信号的触发模式(仅对STN屏有效,对TFT屏无意义)。

PNRMODE :选择当前的显示模式,对于TFT屏而言,应选择[11],即TFT LCD panel。BPPMODE :选择色彩模式,对于真彩显示而言,选择16bpp(64K色)即可满足要求。ENVID :使能LCD信号输出。

图1.5 VBPD,LINEVAL,VFPD,VSPW 的各项含义已经在前面的时序图中得到体现。

图1.6 HBPD,HOZVAL,HFPD 的各项含义已经在前面的时序图中得到体现。

图1.7 HSPW 的含义已经在前面的时序图中得到体现。MVAL 只对 STN屏有效,对TFT屏无意义。

HSPW 的含义已经在前面的时序图中得到体现,这里不再赘述。MVAL 只对 STN屏有效,对TFT屏无意义。

图1.8 VSTATUS :当前VSYNC信号扫描状态,指明当前VSYNC同步信号处于何种扫描阶段。HSTATUS :当前HSYNC信号扫描状态,指明当前HSYNC同步信号处于何种扫描阶段。

BPP24BL :设定24bpp显示模式时,视频资料在显示缓冲区中的排列顺序(即低位有效还是高位有效)。对于16bpp的64K色显示模式,该设置位无意义。

FRM565 :对于16bpp显示模式,有2中形式,一种是RGB=5:5:5:1,另一种是5:6:5。后一种模式最为常用,它的含义是表示64K种色彩的16bit RGB资料中,红色(R)占了5bit,绿色(G)占了6bit,兰色(B)占了5bit INVVCLK,INVLINE,INVFRAME,INVVD :通过前面的时序图,我们知道,CPU的LCD控制器输出的时序默认是正脉冲,而LCD需要VSYNC(VFRAME)、VLINE(HSYNC)均为负脉冲,因此 INVLINE 和 INVFRAME 必须设为“1 ”,即选择反相输出。INVVDEN,INVPWREN,INVLEND 的功能同前面的类似。

PWREN 为LCD电源使能控制。在CPU LCD控制器的输出信号中,有一个电源使能管脚LCD_PWREN,用来做为LCD屏电源的开关信号。

ENLEND 对普通的TFT屏无效,可以不考虑。

BSWP 和 HWSWP 为字节(Byte)或半字(Half-Word)交换使能。由于不同的GUI对FrameBuffer(显示缓冲区)的管理不同,必要时需要通过调整 BSWP 和 HWSWP 来适应GUI。2.Linux 驱动 2.1 FrameBuffer Linux是工作在保护模式下,所以用户态进程是无法像DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Lin仿显卡的功能,将显ux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。

在Linux系统下,FrameBuffer的主要的结构如图所示。Linux为了开发FrameBuffer程序的方便,使用了分层结构。fbmem.c处于Framebuffer设备驱动技术的中心位置。它为上层应用程序提供系统调用,也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己。

fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口,避免重复工作。下将介绍fbmem.c主要的一些数据结构。

2.2 数据结构

2.2.1 Linux FrameBuffer的数据结构

在FrameBuffer中,fb_info可以说是最重要的一个结构体,它是Linux为帧缓冲设备定义的驱动层接口。它不仅包含了底层函数,而且还有记录设备状态的数据。每个帧缓冲设备都与一个fb_info结构相对应。fb_info的主要成员如下 struct fb_info { int node;struct fb_var_screeninfo var;/* Current var */ struct fb_fix_screeninfo fix;/* Current fix */ struct fb_videomode *mode;/* current mode */

struct fb_ops *fbops;struct device *device;/* This is the parent */ struct device *dev;/* This is this fb device */

char __iomem *screen_base;/* Virtual address */ unsigned long screen_size;/* Amount of ioremapped VRAM or 0 */

………… };其中node成员域标示了特定的FrameBuffer,实际上也就是一个FrameBuffer设备的次设备号。fb_var_screeninfo结构体成员记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_var_screeninfo中的xres定义屏幕一行有多少个点, yres定义屏幕一列有多少个点, bits_per_pixel定义每个点用多少个字节表示。其他域见以下代码注释。struct fb_var_screeninfo { __u32 xres;/* visible resolution */ __u32 yres;__u32 xoffset;/* offset from virtual to visible */ __u32 yoffset;/* resolution */ __u32 bits_per_pixel;/* bits/pixel */ __u32 pixclock;/* pixel clock in ps(pico seconds)*/ __u32 left_margin;/* time from sync to picture */ __u32 right_margin;/* time from picture to sync */ __u32 hsync_len;/* length of horizontal sync */ __u32 vsync_len;/* length of vertical sync */ ………… };在fb_info结构体中,fb_fix_screeninfo中记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址,长度。当对帧缓冲设备进行映射操作的时候,就是从fb_fix_screeninfo中取得缓冲区物理地址的。struct fb_fix_screeninfo { char id[16];/* identification string eg “TT Builtin” */ unsigned long smem_start;/* Start of frame buffer mem(physical address)*/ __u32 smem_len;/* Length of frame buffer mem */ unsigned long mmio_start;/* Start of Mem Mapped I/O(physical address)*/ __u32 mmio_len;/* Length of Memory Mapped I/O */ ………… };fb_info还有一个很重要的域就是fb_ops。它是提供给底层设备驱动的一个接口。通常我们编写字符驱动的时候,要填写一个file_operations结构体,并使用register_chrdev()注册之,以告诉Linux如何操控驱动。当我们编写一个FrameBuffer的时候,就要依照Linux FrameBuffer编程的套路,填写fb_ops结构体。这个fb_ops也就相当于通常的file_operations结构体。struct fb_ops { int(*fb_open)(struct fb_info *info, int user);int(*fb_release)(struct fb_info *info, int user);ssize_t(*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);ssize_t(*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);int(*fb_set_par)(struct fb_info *info);int(*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);int(*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info)int(*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);…………… } 上面的结构体,根据函数的名字就可以看出它的作用,这里不在一一说明。下图给出了Linux FrameBuffer的总体结构,作为这一部分的总结。图2.2

2.2.2 S3C2410中LCD的数据结构

在S3C2410的LCD设备驱动中,定义了s3c2410fb_info来标识一个LCD设备,结构体如下: struct s3c2410fb_info { struct fb_info *fb;struct device *dev;struct s3c2410fb_mach_info *mach_info;struct s3c2410fb_hw regs;/* LCD Hardware Regs */ dma_addr_t map_dma;/* physical */ u_char * map_cpu;/* virtual */ u_int map_size;/* addresses of pieces placed in raw buffer */ u_char * screen_cpu;/* virtual address of buffer */ dma_addr_t screen_dma;/* physical address of buffer */ ………… };成员变量fb指向我们上面所说明的fb_info结构体,代表了一个FrameBuffer。dev则表示了这个LCD设备。map_dma,map_cpu,map_size这三个域向了开辟给LCD DMA使用的内存地址。screen_cpu,screen_dma指向了LCD控制器映射的内存地址。另外regs标识了LCD控制器的寄存器。struct s3c2410fb_hw { unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;};这个寄存器和硬件的寄存器一一对应,主要作为实际寄存器的映像,以便程序使用。这个s3c2410fb_info中还有一个s3c2410fb_mach_info成员域。它存放了和体系结构相关的一些信息,如时钟、LCD设备的GPIO口等等。这个结构体定义为 struct s3c2410fb_mach_info { unsigned char fixed_syncs;/* do not update sync/border */ int type;/* LCD types */ int width;/* Screen size */ int height;struct s3c2410fb_val xres;/* Screen info */ struct s3c2410fb_val yres;struct s3c2410fb_val bpp;struct s3c2410fb_hw regs;/* lcd configuration registers */ /* GPIOs */ unsigned long gpcup;unsigned long gpcup_mask;unsigned long gpccon;unsigned long gpccon_mask;………… };

图2.3 上图表示了S3C2410驱动的整体结构,反映了结构体之间的相互关系 2.3 主要代码结构以及关键代码分析 2.3.1 FrameBuffer驱动的统一管理

fbmem.c实现了Linux FrameBuffer的中间层,任何一个FrameBuffer驱动,在系统初始化时,必须向fbmem.c注册,即需要调用register_framebuffer()函数,在这个过程中,设备驱动的信息将会存放入名称为registered_fb数组中,这个数组定义为 struct fb_info *registered_fb[FB_MAX];int num_registered_fb;它是类型为fb_info的数组,另外num_register_fb则存放了注册过的设备数量。

我们分析一下register_framebuffer的代码。int register_framebuffer(struct fb_info *fb_info){ int i;struct fb_event event;struct fb_videomode mode;if(num_registered_fb == FB_MAX)return-ENXIO;/* 超过最大数量 */ num_registered_fb++;for(i = 0;i < FB_MAX;i++)if(!registered_fb[i])break;/* 找到空余的数组空间 */ fb_info->node = i;

fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), “fb%d”, i);/* 为设备建立设备节点 */ if(IS_ERR(fb_info->dev)){ ………… } else{ fb_init_device(fb_info);/* 初始化改设备 */ } ………… return 0;} 从上面的代码可知,当FrameBuffer驱动进行注册的时候,它将驱动的fb_info结构体记录到全局数组registered_fb中,并动态建立设备节点,进行设备的初始化。注意,这里建立的设备节点的次设备号就是该驱动信息在registered_fb存放的位置,即数组下标i。在完成注册之后,fbmem.c就记录了驱动的fb_info。这样我们就有可能实现fbmem.c对全部FrameBuffer驱动的统一处理。

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的操作。下面给出了一个LCD驱动的open()函数的调用流程图,用以说明上面的步骤。

图2.4

2.3.3 开发板S3C2410 LCD驱动的流程

(1)在mach-smdk2410.c中,定义了初始的LCD参数。注意这是个全局变量。static struct s3c2410fb_mach_info smdk2410_lcd_cfg = {.regs= {.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | S3C2410_LCDCON1_TFT| S3C2410_LCDCON1_CLKVAL(7),......},.width = 240,.height = 320,.xres = {.min = 240,.max= 240,.defval = 240},.bpp = {.min = 16,.max= 16,.defval = 16},......};(2)内核初始化时候调用s3c2410fb_probe函数。下面分析这个函数的做的工作。首先先动态分配s3c2410fb_info空间。

fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info),&pdev->dev);把域mach_info指向mach-smdk2410.c中的smdk2410_lcd_cfg。info->mach_info = pdev->dev.platform_data;设置fb_info域的fix,var,fops字段。

fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;fbinfo->fix.type_aux = 0;fbinfo->fix.xpanstep = 0;

fbinfo->var.nonstd = 0;fbinfo->var.activate = FB_ACTIVATE_NOW;fbinfo->var.height = mach_info->height;fbinfo->var.width = mach_info->width;

fbinfo->fbops = &s3c2410fb_ops;……

该函数调用s3c2410fb_map_video_memory()申请DMA内存,即显存。

fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, &fbi->map_dma, GFP_KERNEL);

fbi->map_size = fbi->fb->fix.smem_len;…….设置控制寄存器,设置硬件寄存器。

memcpy(&info->regs, &mach_info->regs,sizeof(info->regs));info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;……….调用函数s3c2410fb_init_registers(),把初始值写入寄存器。

writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);

(3)当用户调用mmap()映射内存的时候,Fbmem.c把刚才设置好的显存区域映射给用户。start = info->fix.smem_start;len = PAGE_ALIGN((start & ~PAGE_MASK)+ info->fix.smem_len);io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end-vma->vm_start,vma->vm_page_prot);

……

这样就完成了驱动初始化到用户调用的整个过程。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.1

3.2 bmp位图格式分析

位图文件可看成由四个部分组成:位图文件头、位图信息头、彩色表和定义位图的字节阵列。如图3.2所示。

图3.2 文件头中各个段的地址及其内容如图3.3。

图3.3 位图文件头数据结构包含BMP图象文件的类型,显示内容等信息。它的数据结构如下定义: Typedef struct {

int bfType;//表明位图文件的类型,必须为BM long bfSize;//表明位图文件的大小,以字节为单位 int bfReserved1;//属于保留字,必须为本0 int bfReserved2;//也是保留字,必须为本0 long 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;//输出设备的位平面数,必须置为1 int biBitCount;//给出每个象素的位数 long biCompress;//给出位图的压缩类型 long biSizeImage;//给出图象字节数的多少 long biXPelsPerMeter;//图像的水平分辨率 long biYPelsPerMeter;//图象的垂直分辨率 long biClrUsed;//调色板中图象实际使用的颜色素数 long biClrImportant;//给出重要颜色的索引值 } BITMAPINFOHEADER;

图3.6 BITMAPINFOHEADER数据结构

(3)对于象素小于或等于16位的图片,都有一个颜色表用来给图象数据阵列提供颜色索引,其中的每块数据都以B、G、R的顺序排列,还有一个是reserved保留位。而在图形数据区域存放的是各个象素点的索引值。它的C语言结构如图3.7所示。

图3.7 颜色表数据结构

(4)对于24位和32位的图片,没有彩色表,他在图象数据区里直接存放图片的RGB数据,其中的每个象素点的数据都以B、G、R的顺序排列。每个象素点的数据结构如图3.8所示。

图3.8 图象数据阵列的数据结构

(5)由于图象数据阵列中的数据是从图片的最后一行开始往上存放的,因此在显示图象时,是从图象的左下角开始逐行扫描图象,即从左到右,从下到上。

(6)对S3C2410或PXA255开发板上的LCD来说,他们每个象素点所占的位数为16位,这16位按B:G:R=5:6:5的方式分,其中B在最高位,R在最低位。而从bmp图象得到的R、G、B数据则每个数据占8位,合起来一共24位,因此需要对该R、G、B数据进行移位组合成一个16位的数据。移位方法如下:

b >>= 3;g >>= 2;r >>= 3;RGBValue =(r<<11 | g << 5 | b);基于以上分析,提取各种类型的bmp图象的流程如图3.9所示

图 3.9

3.3 实现显示任意大小的图片

开发板上的LCD屏的大小是固定的,S3C2410上的LCD为:240*320,PXA255上的为:640*480。比屏幕小的图片在屏上显示当然没问题,但是如果图片比屏幕大呢?这就要求我们通过某种算法对图片进行缩放。

缩放的基本思想是将图片分成若干个方块,对每个方块中的R、G、B数据进行取平均,得到一个新的R、G、B值,这个值就作为该方块在LCD屏幕上的映射。缩放的算法描述如下:

(1)、计算图片大小与LCD屏大小的比例,以及方块的大小。为了适应各种屏幕大小,这里并不直接给lcd_width和lcd_height赋值为240和320。而是调用标准的接口来获取有关屏幕的参数。具体如下:

// Get variable screen information if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)){ printf(“Error reading variable information.”);exit(3);} unsigned int lcd_width=vinfo.xres;unsigned int lcd_height=vinfo.yres;

计算比例:

widthScale=bmpi->width/lcd_width;heightScale=bmpi->height/lcd_height;本程序中方块的大小以如下的方式确定: unsigned int paneWidth= unsigned int paneHeight=;符号 代表向上取整。

(2)、从图片的左上角开始,以(i* widthScale,j* heightScale)位起始点,以宽paneWidth 高paneHeight为一个小方块,对该方块的R、G、B数值分别取平均,得到映射点的R、G、B值,把该点作为要在LCD上显示的第(i , j)点存储起来。这部分的程序如下: //-------------取平均--------for(i=0;ir=div_round(color_sum_r,paneHeight*paneWidth);RGBvalue_256->g=div_round(color_sum_g,paneHeight*paneWidth);RGBvalue_256->b=div_round(color_sum_b,paneHeight*paneWidth);} } 3.4 图片数据提取及显示的总流程

通过以上的分析,整个图片数据提取及显示的总流程如图3.10 所示。图 3.10 三 实验过程与结果 1.Linux 源代码的修改

首先修改arch/arm/mach-smdk2410.c文件,加入以下代码。static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {.regs = {.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | S3C2410_LCDCON1_TFT | S3C2410_LCDCON1_CLKVAL(7),.lcdcon2 = S3C2410_LCDCON2_VBPD(4)| S3C2410_LCDCON2_LINEVAL(319)| S3C2410_LCDCON2_VFPD(1)| S3C2410_LCDCON2_VSPW(1),.lcdcon3 = S3C2410_LCDCON3_HBPD(26)| S3C2410_LCDCON3_HOZVAL(239)| S3C2410_LCDCON3_HFPD(30),.lcdcon4 = S3C2410_LCDCON4_HSPW(13)| S3C2410_LCDCON4_MVAL(13),.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, },.lpcsel =((0xCE6)& ~7)| 1<<4,.width = 240,.height = 320,.xres = {.min = 240,.max = 240,.defval = 240, },.yres = {.min = 320,.max = 320,.defval = 320, },.bpp = {.min = 16,.max = 16,.defval = 16, }, };在函数smdk2410_machine_init()函数中加入LCD的初始化代码,见下 static void __init smdk2410_machine_init(void){ s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);smdk_machine_init();} 2.编译内核,产生zImage文件,放入tftp目录下。

3.在nfs的dev目录下建立FrameBuffer的设备节点,使用命令: mknod fb0 c 29 0 4.启动开发板,加载内核和文件系统。5.编写LCD的应用程序,程序见附录。

6.采用arm-linux-gcc 编译应用程序,产生可执行文件,放入nfs目录中。7.在开发板上运行编译好的可执行文件,便可。

8.下图是BMP位图显示程序,在S3C2410上的运行结果。

四 实验心得体会

1. LCD驱动的主要问题是没有LCD屏的文档,我们找不到它的那些参数值,后来只能参照Linux源码里面的其他LCD屏的参数进行实验。

2. 在驱动差错的过程中,我们采用跟踪打印的方法进行调试。刚开始的时候,内核打印出一行找不到LCD设备。我们定位到输出这行提示的代码处,进行反向跟踪。发现传给函数的设备指针为空,于是往上排查,终于发现源代码中没有定义LCD的设备信息。于是驱动问题也就顺利解决了。

3. 原来一直以为,只要LCD驱动工作正常了,内核起来的时候,液晶屏会显示出Logo。当时搞了很久一直没有,还以为是驱动的问题。后来随便写了一个LCD应用程序,竟然能用。

4. 在调试过程应用程序中发现,在读取文件头的时候,如果直接定义一个bitmapfileheader为它动态分配内存:

*bmph=(bitmapfileheader*)malloc(sizeof(bitmapfileheader));然后用fread((char*)bmph,sizeof(bitmapfileheader),1,f)把文件头一次性读出来,读出来的文件头是错误的,经过调试发现原因是bitmapfileheader这个结构体中的type属性原本应该占2字节,但是被编译器在分配内存的时候进行了内存对齐的优化,给他分配了4个字节的空间,造成读文件的错误。因此在编程中要特别注意内存对齐的影响。typedef struct { WORD type;(被优化)DWORD bfsize;DWORD reserved;DWORD offbits;} bitmapfileheader;5. 在嵌入式应用程序的移植过程中,我们原来认为ARM和PC机大小尾顺序是不同的,因此在应用程序中,也对这个差别进行了处理。当时,在调试过程中发现,PC机程序可以直接移植到ARM上,不需要任何改动。但是我们的程序,的确存在会产生大小尾问题代码(在使用fread()读入时)。这究竟是为什么?有人说,ARM是可以设置大小尾顺序的。后来这个问题也没有深究下去。五 参考文献

(1)嵌入式系统设计与应用开发:郑灵翔.北京:北京航天航空大学出版社 2006

下载LCD电子广告屏word格式文档
下载LCD电子广告屏.doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    LCD Engineer、手机 LCD 工程师岗位职责

    1.对LCM及camera样品的确认。2.LCM及camera相关问题的机解决和跟踪。3.配合各项目组,保证LCD和camera满足项目进度要求。4.对新产品LCD/camera的可行性评估。......

    单片机课程设计报告LCD显示温度

    《单片机原理与应用》 课程设计报告 题 目:LCD数字式温度湿度测量计 专 业:自动化 班 级:A1332 学 号:10 姓 名:曾志勇 指导老师:查兵 2016-06-08 目 录 1. 设计题目、要求及分工......

    《说“屏”》 说课稿

    《说“屏”》 说课稿 宜昌市十中语文组张萍 【教材分析】 一、单元教学内容:中国历史悠久,文化丰富发达,中国的建筑、园林、名胜古迹独具特色,在世界上也享有盛誉。八年级上第三......

    说屏教案

    八年级语文上册16说“屏” 教学目标: 1.整体感知课文,了解屏的相关知识;把握说明对象及特征,理解文中古诗句的含义;进一步提高说明文的阅读能力。 2了解中国古代的屏风,激发学生对......

    说屏教案

    《说“屏”》教案新疆教育学院国培中语班 杨雪萍 [教学目标] 1. 朗读课文,积累词语。 2. 理解课文内容,了解屏的相关知识。 3. 了解文中引用的古诗词的意思。 4. 整体感知课文,把握......

    说屏教案

    第十五课 说“屏”教案 教学目标: 1掌握重点词汇,正确的朗读课文。 2理解课文内容,了解“屏”的有关知识。 3了解文章的说明方法,说明顺序,体味文章生动的说明语言。 教学重点: 1......

    拼接屏验收报告

    方正水稻试验田 百万高清视频监控系统工程验收报告系统(工程)名称: 方正县水稻试验田高清监控系统 建设(使用)单位: 设 计、施 工单位: 哈尔滨正隆科技开发有限公司 验 收 日 期: 2......

    说屏说课稿

    说“屏”说课稿 说课程序 一、说教材 二、说教学方法 三、说教学过程 四、说板书设计 一、说教材 《说“屏”》是人教版八年级语文上册第三单元的一篇自读课文,这是一篇比较......