LCD——S5PV210的LCD的理论与操作

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

参考博客

s5pv210 LCD编程原理 - biaohc - 博客园

一、关于LCD的简介

1、LCD简介

(1)什么是LCD

LCD(Liquid Crystal Display)俗称液晶。液晶是一种材料,这种材料具有一种特点,在电信号的驱动下液晶分子进行旋转,而旋转时会影响透光性,因此我们可以在整个液晶面板后面用白光照(称为背光),可以通过不同电信号让液晶分子进行选择性的透光,此时在液晶面板前面就可以看到各种各样的颜色,这就是LCD显示。

有些显示器(比如LED显示器)本身会发光,称为主动发光。有些(比如LCD)本身不会发光而只会透光,需要背光的协助才能看起来是发光的,称为被动发光。
液晶多应用于电视机、电脑显示屏、手机显示屏、工业显示屏等领域。

(2)其他主流显示设备

CRT:阴极摄像管显示器。

等离子显示:未成为主流。

OLED:目前未成为主流,但是很有市场潜力。

LED:主要用在户外大屏幕。

LCD:目前是主流显示器。

(3)LCD的显示原理(液晶分子透光+背光)

白光由各种不同颜色的光组成,被选择性透光之后可以产生各种不同颜色的光。

(4)LCD的发展史和种类(TN/STN/TFT)

TN最早。坏处是响应性不够好,有拖尾现象。

STN是TN的升级版。有效解决拖尾现象,显示更清晰。

TFT的最大特点就是超薄。
 

2、LCD的接口技术

(1)LCD的硬件接口采用TTL电平

+5V表示逻辑1,0V表示逻辑0,这种就叫TTL电平。

SoC的LCD控制器硬件接口是TTL电平的,LCD的硬件接口也是TTL电平的。所以他们可以直接对接,比如手机、平板、开发板,一般都使用软排线连接。

TTL电平的缺陷就是传输距离短,如果LCD屏幕和主板控制器太远(比如大于1米)就不能直接TTL连接,而要进行转换。转换方式为:主机SoC(TTL) —>VGA —> LCD屏幕(TTL)。

(2)各种接口(TTL、LVDS、EDP、MIPI)的传输速率、距离、适配性

http://blog.csdn.net/wocao1226/article/details/23870149

(3)RGB接口详解(参考数据手册P1207页时序图)

 (1)VD[23:0],24根数据线,用来传输图像信息。可见LCD是并行接口,速率才够快。

(2)HSYNC(水平同步信号) 

(3)VSYNC(垂直同步信号):时序信号线,为了让LCD能够正常显示给的控制信号。

(4)VCLK(像素时钟):LCD工作时需要主板控制器给LCD模组一个工作时钟信号,就是VCLK。

(5)VDEN(数据有效标志):时序信号,和HSYNC、VSYNC结合使用。

(6)LEND(行结束标志,不是必须的):时序信号,非必须,比如X210接口就没有。

3、LCD如何显示图像

(1)像素(pixel)

像素就是组成图像的最基本元素,或者说显示中可以被控制的最小单位,整个图像就是由很多个像素组成的。

像素可以被单独控制,或控制其亮或不亮(单色屏)、或控制其亮度强弱(譬如亮50%,35%,这样叫灰度屏,以前的黑白电视机)、或控制其显示一定的颜色(现在最常用的彩色显示屏)。
总结:整个显示图像是由一个个的像素组成的。我们要在显示器上显示一个图像,就是把这个图像离散化成一个个的点,然后把各个点的颜色对应在显示器的像素上。

(2)扫描
扫描就是依次将颜色数值放入屏幕中所有像素中的这个过程。

扫描这个词是由最早的CRT显示器遗留下来的,到LCD显示器的年代已经失去意义,但是我们还是延续着这么叫。

显示器的扫描显示原理依赖于人眼的视觉暂留。只要显示器扫描频率大于人眼的发现频率,人眼看到的图像就是恒定的。如果扫描频率偏小人眼就会看到闪动。

(3)LCD驱动器、LCD控制器

LCD驱动器一般和LCD显示面板集成在一起。这两者本来是分开的,做面板的是只做面板的,比如三星、LG、友达、奇美都是做面板的;驱动器也由专门的IC厂商生产;集成厂商买来面板和驱动器后集成在一起做成LCD屏幕。

面板只负责液晶分子的旋转透光,需要一定的模拟电信号来控制液晶分子。这模拟电信号由LCD驱动器芯片负责提供,而LCD驱动器的控制信号(数字信号)来自于自己的数字接口,这个接口就是LCD屏幕的外部接口(即上面第2节中讲到的接口)。

LCD控制器一般集成在SoC内部,负责通过数字接口向远端的LCD驱动器提供控制像素显示的数字信号。LCD控制器的关键在于时序,它必须按照一定的时序和LCD驱动器通信。LCD控制器受到SoC控制,SoC会从内存中拿像素数据给LCD控制器并最终传给LCD驱动器。

(4)显示内存(简称显存)

SoC在内存中挑选一段内存(程序员随便挑的,但是必须符合一定规矩),然后通过配置将LCD控制器和这一段内存形成一个映射关系。这个关系建立之后,LCD控制器会自动从显存中读取像素数据传输给LCD驱动器。这个过程不需要CPU的参与。

这关系建立之后,CPU不用再理会LCD控制器、驱动器、面板,只需要关心显存即可,因为只要把要显示的图像的像素数据丢到显存中,硬件就会自动响应,屏幕上就能自动看到显示的图像。

总结:LCD显示分为2个阶段,第一个阶段就是CPU初始化LCD控制器,使其和某段显存联系起来构成映射;第二个阶段就是将要显示的图像丢到显存中去。

4、LCD的六个主要时序参数

(1)LCD显示单位:帧(frame)

显示器整个画面的内容为一帧(frame)。

显示器工作时其实是一帧一帧地在显示,比如电影以每秒24帧的速度在播放图片。
一帧分为多行,一行分为多像素,因此一帧图像其实就是多个像素组成的矩阵。
 

(2)LCD显示一帧图像的过程

首先把帧分为行,然后再把行分为像素,然后逐个像素去显示。

其实就是LCD驱动器按照LCD控制器给的显示数据,驱动一个像素的液晶分子旋转,让这个像素显示出相应的颜色值的过程。
LCD控制器和驱动器之间一次只能传一个像素点的显示数据,所以一帧图像在屏幕上其实是逐行地依次被显示上去的,不是同一时间显示出来的。

(3)为了向前兼容出现的六个时序参数

HSPW水平同步信号脉宽
HBPD水平同步信号前肩
HFPD水平同步信号后肩
VSPW垂直同步信号脉宽
VBPD垂直同步信号前肩
VFPD垂直同步信号后肩

(1)一行的通信过程是这样的:LCD控制器先发送一个HSYNC高电平脉冲(脉冲宽度是HSPW),脉冲告诉驱动器下面的信息是一行信息。然后开始这一行信息,这一行信息包括3部分:HBPD+有效行信息+HFPD。其中前肩和后肩都属于时序信息(和LCD屏幕具体有关),有效行信息就是横向分辨率。所以你可以认为一行总共包含4部分:HSPW+HBPD+有效行信息+HFPD。

(2)一帧图像其实就是一列,一列图像由多个行组成,每行都是上面讲的这个时序。

(3)一帧图像的通信过程是这样的:整个帧图像信号分为4部分:VSPW+VBPD+帧有效信号+VFPD。VSPW是帧同步信号宽度,用来告诉驱动器一帧图像要开始了;VBPD和VFPD分别是垂直同步信号前后肩。

(4)必须说明:这6个参数对于LCD显示器其实本来是没用的,这些信号其实是老式的CRT显示器才需要的,LCD本身不需要,但是出于历史兼容性要求,LCD选择了兼容CRT显示器的这些时序要求,所以理解LCD显示器时序和编程时,用CRT的方式来理解不会错。

(5)这几个时序参数本身是LCD屏幕本身的参数,与LCD控制器无关。同一个主板如果接的屏幕不一样,则时序参数设置也会不同。这些参数来源一般是:

第一,厂家会一般以实例代码的形式给出。

查看九鼎的210裸机教程(s5pv210-fb.c的第774行)

        .h_fp            = 210,        // 160-210-354.h_bp            = 38,        // 46.h_sw            = 10,        // 1-40.v_fp            = 22,        // 7-22-147.v_fpe            = 1,.v_bp            = 18,        // 23.v_bpe            = 1,        .v_sw            = 7,        // 1-20

第二,来自于LCD的数据手册。

比如查看LCD数据手册(X210光盘资料\A盘\DataSheet\AT070TN92.pdf)

补充
1、注意这些数字的单位。H开头的三个单位都是DCLK(像素时钟),V开头的三个单位是TH。这样设置的好处是我们改变了像素时钟的设置时,不用改变这里的时序参数。
2、这些时序参数如果没设置好会影响什么?屏幕会跑偏。

5、LCD显示的相关概念

(1)像素(pixel)

整个图像是由一个个的像素组成的,像素就是一个显示点。

(2)像素间距(pitch)

pitch是连续2个像素的像素中心的距离。一般的像素是方形的,所以横向pitch和纵向的pitch一样的。但是也有不一样的。

像素间距会影响屏幕的最佳观看距离。像素间距大的适合远距离看,像素间距小的适合近距离看。

(3)分辨率(resolution)

整个屏幕的横向和纵向的像素个数就叫分辨率,譬如X210开发板用的屏幕是800×480。

屏幕尺寸和分辨率无关的,像开发板的屏幕尺寸是7寸的(纯屏幕对角线尺寸是7英寸)。

屏幕尺寸和分辨率和像素间距三者之间有关联。

(4)清晰度

清晰度是一个主观概念,是人眼对显示效果的一个主观判断。说白了就是人看起来感觉清晰不清晰。

客观来讲,清晰度由分辨率和像素间距共同决定。一般的,屏幕尺寸固定时分辨率越高越清晰,分辨率越低就越不清晰;分辨率固定下,屏幕尺寸越小越清晰,越大越不清晰。

清晰度还由其他很多因素共同决定。

(5)像素深度(bits per pixel,简称bpp)

一个像素在计算机中由多少个字节数据来描述。

计算机中用二进制位来表示一个像素的数据,用来表示一个像素的数据位越多,则这个像素的颜色值更加丰富、分的更细,颜色深度就更深。

一般来说像素深度有这么几种:1位、8位、16位、24位、32位。

6、颜色在计算机中的表示

(1)颜色的本质

颜色是主观存在,颜色其实是自然光在人的眼睛中和大脑中产生的一种映像。

颜色的本质决定于光的波长。

(2)自然光的颜色是连续的

光的波长是连续的,导致颜色也是连续的。理论上,只要你的眼睛分辨能力足够好,可以在自然界中发现无数种颜色。

(3)计算机中的颜色是离散的

计算机中不可能存储无数种颜色,所以必须将颜色有限化,所以就用有限种颜色来代表自然界中的无限种颜色。这个理论非常类似于之前学过的AD转换。

这种离散化表达颜色的缺点是不够真实,漏掉了很多种颜色。因此计算机中所能表达的颜色没有自然界中丰富,计算机屏幕上显示的图像和真实图像有差别。

计算机所能表达的颜色种类个数,这个参数叫:像素深度bpp。

(4)常见像素深度:1位、8位、16位、24位、32位
1位:用1个二进制位来表示颜色,这种就叫单色显示。示例就是理发店门口的LED屏。


8位:用8个二进制位来表示颜色,此时能表示256种颜色。这种叫灰度显示。这时候是黑白的,没有彩色,我们把纯白到纯黑分别对应255到0,中间的数值对应不同的灰。示例就是以前的黑白电视机。


16位:用16个二进制位表示颜色,此时能表示65536种颜色。这时候就可以彩色显示了,一般是RGB565的颜色分布(用5位二进制表示红色、用6位二进制表示绿色、用5位二进制表示蓝色)。这种红绿蓝都有的颜色表示法就是一种模拟自然界中所有颜色的表示方式。但是因为RGB的颜色表达本身二进制位数不够多(导致红绿蓝三种颜色本身分的都不够细致),所以这样显示的彩色失真比较重,人眼能明显看到显示的不真实。


24位:用24个二进制位来表示颜色,此时能表示16777216种颜色。这种表示方式和16位色原理是一样的,只是RGB三种颜色各自的精度都更高了(RGB各8位),叫RGB888。此时颜色比RGB565更加真实细腻,虽然说比自然界无数种颜色还是少了很多,不过由于人眼的不理想性,所以人眼几乎不能区分1677万种颜色和无数种颜色的差别了。于是乎就把这种RGB888的表示方法叫做真彩色。(RGB565就是假彩色)


32位:总共用32位二进制来表示颜色,其中24位表示红绿蓝三元色(还是RGB888分布),剩下8位表示透明度。这种显色方式就叫ARGB(A是阿尔法,表示透明度),现在PC机中一般都用ARGB表示颜色。

补充:颜色的三基色是RGB,也就是说所有的颜色都可以由红绿蓝三种颜色组成。

二、S5PV210的LCD控制器

1、LCD控制器结构框图

LCD控制器部分内容在数据手册的第1162页。

S5PV210的LCD控制器叫做FIMD,它是与图像处理相关的一些部件,与摄像头、图像处理部分有关联。FIMD在内部与AHB总线等相连接,在外部提供RGB接口、I80接口、YUV接口。我们实际使用的是RGB接口。

2、“虚拟屏幕”的概念

该内容位于数据手册1194页。

我们平时看到的屏幕所显示的场景,实际是由很多个虚拟屏幕叠加在一起的效果,比如新闻图像、电视台台标、下方飘动的字幕新闻。

虚拟屏幕其实就是内存中的一个显存区域,有几个显存区域就有几个虚拟屏幕。这些虚拟屏幕被映射到一个真实的显示屏,将来显示屏所显示的内容,其实是这几个虚拟屏幕所显示的内容的叠加。叠加时,上面一层会覆盖下面一层,因此要注意谁在前谁在后,这可以通过相关寄存器进行设置

使用(虚拟屏幕)而非(整个LCD只使用一个显存)的好处:第一,不污染源图像,方便程序处理;第二,减少屏幕刷新,提高显示效率,减少CPU工作量。

S5PV210的LCD控制器中有5个虚拟屏幕,Window0到Window4。

3、“虚拟显示”的概念

该内容位于数据手册1206页。

当我们需要在屏幕上看到不同的图像时,就需要对显存区域进行刷新。即使我们只需要将屏幕的显示稍微移动,也要将整个屏幕对应的显存空间全部刷新,其工作量和完全重新显示一幅图像是一样的。这样显然不好,因为CPU刷新屏幕的工作量很大,效率很低。

虚拟显示解决的问题,就是在小分辨率的屏幕上真实地显示大分辨率的图像。具体做法就是在内存中建立显存时,建立一个很大的显存区域,然后让LCD与其中的一部分区域对应,作为有效显示区域。将来要显示大图像时,将图像信息一次性全部加载到显示缓存区,然后通过移动有效显示区域就可以显示大图像的不同区域了。

4、主要寄存器简介

(1)DISPAY_CONTROL寄存器

  • 设置为10或11,即RGB模式可行。

(2)VIDCON0寄存器

  • bit0~1:为使能控制信号都使能;
  • bit2:选择时钟源,选HCLK,连的是HCLC_DSYS 为166MHz;
  • bit4:开启分频;
  • bit13~6:设置时钟大小,时钟频率要小于控制器的最大时钟,也要小于LCD驱动器的最大时钟。
  • bit18:设置RGB数据传输为并行还是串行,因为有24根数据线所以为并行;
  • bit28~26:选择为RGB模式。

(3)VIDCON1寄存器

  • bit5~6:设置HSYNC和VSYNC的极性,如果LCD的高低电平脉冲是相同的话,则Normal,如果极性相反则Invert。

(4)VIDTCONn寄存器

  • n=0,1,2,3。
  • 这些寄存器主要用来设置时序,需要根据LCD数据手册中的时序来设置。

(5)WINCONn寄存器

  • n=0~4;
  • bit0:使能window0 ;
  • bit5-2:选择RGB888模式;
  • bit15:设置输出顺序为 red green blue还是 blue green red,设置为1时BGR,设置为0时RGB。

(6)VIDOSD0A、VIDOSD0B、VIDOSD0C寄存器

  • 都是用来设置内存中window0的大小;
  • 比如设置为LCD屏幕的尺寸,即左上坐标为(0,0),右下坐标为(1023,767)。

(7)VIDW0xADD0Bx寄存器、VIDW0xADD1Bx寄存器

  • VIDW0xADD0Bx寄存器,设置内存中window0的起始地址;
  • VIDW0xADD1Bx寄存器,设置内存中window0的结束地址。

(8)SHODOWCON寄存器

  • 设置虚拟windows显示,以下位可以分别设置哪个windows显示。

5、LCD有关的原理图

二、代码实战

1、宏定义

首先是一些寄存器或者常量相关的宏定义:

#define GPF0CON			(*(volatile unsigned long *)0xE0200120)
#define GPF1CON			(*(volatile unsigned long *)0xE0200140)
#define GPF2CON			(*(volatile unsigned long *)0xE0200160)
#define GPF3CON			(*(volatile unsigned long *)0xE0200180)#define GPD0CON			(*(volatile unsigned long *)0xE02000A0)
#define GPD0DAT			(*(volatile unsigned long *)0xE02000A4)#define CLK_SRC1		(*(volatile unsigned long *)0xe0100204)
#define CLK_DIV1		(*(volatile unsigned long *)0xe0100304)
#define DISPLAY_CONTROL	(*(volatile unsigned long *)0xe0107008)#define VIDCON0			(*(volatile unsigned long *)0xF8000000)
#define VIDCON1			(*(volatile unsigned long *)0xF8000004)
#define VIDTCON2		(*(volatile unsigned long *)0xF8000018)
#define WINCON0 		(*(volatile unsigned long *)0xF8000020)
#define WINCON2 		(*(volatile unsigned long *)0xF8000028)
#define SHADOWCON 		(*(volatile unsigned long *)0xF8000034)
#define VIDOSD0A 		(*(volatile unsigned long *)0xF8000040)
#define VIDOSD0B 		(*(volatile unsigned long *)0xF8000044)
#define VIDOSD0C 		(*(volatile unsigned long *)0xF8000048)#define VIDW00ADD0B0 	(*(volatile unsigned long *)0xF80000A0)
#define VIDW00ADD1B0 	(*(volatile unsigned long *)0xF80000D0)#define VIDTCON0 		(*(volatile unsigned long *)0xF8000010)
#define VIDTCON1 		(*(volatile unsigned long *)0xF8000014)#define HSPW 			(0)
#define HBPD			(40 - 1)
#define HFPD 			(5 - 1)
#define VSPW			(0)
#define VBPD 			(8 - 1)
#define VFPD 			(8 - 1)// FB地址
#define FB_ADDR			(0x23000000)   //这个是任意的,只要对齐就好
#define ROW				(480)
#define COL				(800)
#define HOZVAL			(COL-1)  
#define LINEVAL			(ROW-1)

2、LCD进行初始化

// 初始化LCD
void lcd_init(void)
{// 配置引脚用于LCD功能/**LED、LCD、蜂鸣等,都是与gpio口有关的*因此,涉及这些器件的,都需要初始化gpio口*而初始化gpio,需要用到相关的配置寄存器,比如GPIOCON寄存器控制引脚的模式*而至于配置哪个GPIO,需要看原理图。*这里从原理图知LCD接到gpf0123,所以要到相应的配置寄存器中进行配置*/GPF0CON = 0x22222222;GPF1CON = 0x22222222;GPF2CON = 0x22222222;GPF3CON = 0x22222222;// 打开背光	GPD0_0(PWMTOUT0)/**由原理图可知,当PWMTOUT0接低电平时,正5V电压加到背光上,也就打开了背光灯*而查阅PWMTOUT0可知,它就是GPD0_0这个引脚*把GPD0_0这个引脚配置为输出模式,通过GPD0CON寄存器配置*然后配置GPD0_0这个引脚输出值为0,通过GPD0DAT寄存器配置*/GPD0CON &= ~(0xf<<0);GPD0CON |= (1<<0);			// output modeGPD0DAT &= ~(1<<0);			// output 0 to enable backlight// 10: RGB=FIMD I80=FIMD ITU=FIMD//由上面寄存器的分析可知,这里可以设置为10DISPLAY_CONTROL = 2<<0;// bit[26~28]:使用RGB接口// bit[18]:RGB 并行// bit[2]:选择时钟源为HCLK_DSYS=166MHzVIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );// bit[1]:使能lcd控制器// bit[0]:当前帧结束后使能lcd控制器VIDCON0 |= ( (1<<0)|(1<<1) );// bit[4]:选择需要分频// bit[6~13]:分频系数为15,即VCLK = 166M/(14+1) = 11M,那么bit[6~13]=14;VIDCON0 |= 14<<6 | 1<<4;//屏幕有的是高电平脉冲提示开始,有的是低脉冲提示开始// H43-HSD043I9W1.pdf(p13) 时序图:VSYNC和HSYNC都是低脉冲提示开始
// s5pv210芯片手册(p1207) 时序图:VSYNC和HSYNC都是高脉冲提示开始,所以需要反转VIDCON1 |= 1<<5 | 1<<6;// 设置时序VIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;VIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;// 设置长宽(这里设置的是物理尺寸)VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);// 设置windows0// bit[0]:使能// bit[2~5]:24bppWINCON0 |= 1<<0;WINCON0 &= ~(0xf << 2);//先清零WINCON0 |= (0xB<<2) | (1<<15);//再设置#define LeftTopX     0
#define LeftTopY     0
#define RightBotX   479
#define RightBotY   271// 设置windows1的上下左右//这里设置的是显存空间的大小,可以比屏幕大。//这里设置和物理屏幕一样大VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);// 设置fb的地址VIDW00ADD0B0 = FB_ADDR;//这个可以任选的,但必须对齐(比如按照1M对齐)//每个像素点3个字节(24bit的bpp)就可以了的,但是为了对齐,用了4字节。VIDW00ADD1B0 = (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);//上述两句表明了一个屏幕占用的空间大小// 使能channel 0传输数据SHADOWCON = 0x1;
}

3、一些功能函数

(1)清屏

void lcd_clear_screen(int color)
{int i, j;for (i = 0; i < ROW; i++)for (j = 0; j < COL; j++)lcd_draw_pixel(i, j, color);
}

(2)显示点、线

// 描点
void lcd_draw_pixel(int row, int col, int color)
{unsigned long * pixel = (unsigned long  *)FB_ADDR;*(pixel + row * COL + col) = color;//假设像素点坐标为(row,col),则该像素点在内存中的位置计算方法如下
//有一个基地址,pixel(这里是一个指针,注意它是指针,加1会加上4个字节)
//偏移量=每行多少个像素*有多少行*每个像素占用多少个字节+col个像素*每个像素多少字节
//             COL    * row   *          4          +   col   *  4
//那么所处的位置应该是(int)pixel+COL*row*4 + col * 4
//或者简单地写成 pixel + row * COL + col	}// 划横线
void lcd_draw_hline(int row, int col1, int col2, int color)
{int j;// 描第row行,第j列for (j = col1; j <= col2; j++)lcd_draw_pixel(row, j, color);
}// 划竖线
void lcd_draw_vline(int col, int row1, int row2, int color)
{int i;// 描第i行,第col列for (i = row1; i <= row2; i++)lcd_draw_pixel(i, col, color);
}// 划十字
void lcd_draw_cross(int row, int col, int halflen, int color)
{lcd_draw_hline(row, col-halflen, col+halflen, color);lcd_draw_vline(col, row-halflen, row+halflen, color);
}

(3)显示英文字符

每个英文字符占用16*8个像素,如果单色显示则每个像素占1bit,每个英文字符是16Byte。

要想得到显示,必须知道该字符的字模,然后填充即可。

// 写字
// 写字的左上角坐标(x, y),字的颜色是color,字的字模信息存储在data中
static void show_8_16(unsigned int x, unsigned int y, \unsigned int color, unsigned char *data)  
{  
// count记录当前正在绘制的像素的次序int i, j, count = 0;  for (j=y; j<(y+16); j++)  {  for (i=x; i<(x+8); i++)  {  if (i<XSIZE && j<YSIZE)  {  // 在坐标(i, j)这个像素处判断是0还是1,如果是1写color;如果是0直接跳过if (data[count/8]) 
//表示一个字模中(16行,每行8个像素)的
//第几行(每行8bit)*/ & (1<<(count%8))/*表示该行的第几bitlcd_draw_pixel(i, j, color);}  count++;  }  }  
} // 写字符串
// 字符串起始坐标左上角为(x, y),字符串文字颜色是color,字符串内容为str
void draw_ascii_ok(unsigned int x, unsigned int y, \unsigned int color, unsigned char *str)
{int i;  unsigned char *ch;for (i=0; str[i]!='\0'; i++)  {  ch = (unsigned char *)ascii_8_16[(unsigned char)str[i]-0x20];show_8_16(x, y, color, ch); x += 8;if (x >= XSIZE){x -= XSIZE;			// 回车y += 16;			// 换行}}  
}

(4)显示中文字符

(5)显示图像

之前都是单色显示,每个像素点用一个bit来表示(不是0就是1)。

而图像是彩色的,每个像素点占用4字节(RGB888时),像素点情况很多。

显示图像需要取模,这里使用软件image2LCD来取模。

只要知道RGB顺序的含义,知道生成的步骤即可(一般设置输出的和屏幕实际大小一样)。

// 画800×480的图,图像数据存储在pData所指向的数组中
void lcd_draw_picture(const unsigned char *pData)
{u32 x, y, color, p = 0;for (y=0; y<480; y++){for (x=0; x<800; x++){// 在这里将坐标点(x, y)的那个像素填充上相应的颜色值即可color = (pData[p+0] << 0) | (pData[p+1] << 8) | (pData[p+2] << 16);lcd_draw_pixel(x, y, color);p += 3;//注意这里的p不是指针,而是int数。//由于RGB888,三个一组,所以下一个像素是p+3}}
}

4、验证步骤

由于这样处理得到的bin文件大于16KB,所以需要分成BL1,BL2部分。这里引用chapter10的分割方法,详见chapter14\6.LCD目录下的内容。最后使用烧录脚本(./write2sd),不能使用windows里的烧录工具。write2sd是一个脚本,内容如下:

#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=./BL1/BL1.bin of=/dev/sdb seek=1
sudo dd iflag=dsync oflag=dsync if=./BL2/BL2.bin of=/dev/sdb seek=45

bmp格式是原始图像,没有经过压缩?因此可以直接使用image2LCD软件解释成数据。而jpg、png、gif等经过压缩的图像不可以直接用image2LCD解释。需要先用对应的解压缩库对其解压缩,才能使用image2LCD软件?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分析三星提供的sd_fusing文件夹(用来制作SD卡启动镜像)

以下内容源于网络资源的学习与整理&#xff0c;如有其侵权请告知删除。 参考博客 uboot分析&#xff1a;SD卡镜像制作脚本分析 - 走看看 如何烧写u-boot到SD卡 S5PV210 Uboot开发与移植01&#xff1a;Uboot概述&#xff08;推荐&#xff09; 一、sd_fusing文件夹简介 1、文件…

Linux系统管理----LVM逻辑卷和磁盘配额作业习题

1&#xff0e;为主机增加80G SCSI 接口硬盘 2&#xff0e;划分三个各20G的主分区 [rootlocalhost chen]# fdisk /dev/sdb 命令(输入 m 获取帮助)&#xff1a;n Partition type: p primary (0 primary, 0 extended, 4 free) e extended Select (default p): Using default r…

外存——S5PV210的外部存储器(nandflash与inand的介绍)

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考内容 关于iNand ,oneNand,moviNAND的区别——大家一起来扫盲 - 嵌入式系统 总结 本文首先介绍了目前主流的外存设备有哪些。 然后介绍了NandFlash芯片的接口、结构、常见操作&#xff0c;以及…

uboot中关于LCD的代码分析

以下内容源于朱有鹏《物联网大讲坛》课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 1、在uboot-jiuding/board.c中&#xff0c;init_sequence中的display_banner中的open_backlight函数中&#xff0c;给GPF3_5输出高电平。 注释掉这一句uboot的LCD显示照样正常的&am…

寒假自助游之济南

以前很少去旅行&#xff0c;主要原因是孩子年龄比较小&#xff0c;再就是经济方面的考虑。如今孩子渐渐长大了&#xff0c;行路与读万卷书同等重要&#xff0c;遂决定以后无论寒暑假都应陪孩子到处走一走。我不喜欢那种走马观花式的跟团游&#xff0c;因而自助游便是最佳选择。…

与fastboot相关的知识

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 一、fastboot的基本知识 1、什么是fastboot &#xff08;1&#xff09;fastboot是android使用的一种刷机方法。 android系统设计了2种刷机方式&#xff1a;fastboot和recovery。 &#xf…

Android中Activity启动模式详解

在Android中每个界面都是一个Activity&#xff0c;切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。 Android总Activity的启动模式分为四种&#xff1a; Activity启动模式设置&#xff1a; <activity and…

第一次软工作业展示——潘学

第一次软工作业完成啦&#xff01; 回首这个作业的完成过程&#xff0c;我是很有收获。这个作业有几个难点&#xff1a;1、在给定目录下读取TXT文件的内容&#xff1b;2、从读到的内容中分析出单词&#xff1b;3、统计单词的出现频率并输出。 我之前只学习过C和java&#xff0c…

uboot源码——命令体系

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 参考资料&#xff1a;http://www.cnblogs.com/biaohc/p/6394710.html 一、uboot命令体系基础 1、使用uboot命令 uboot启动后进入命令行环境&#xff0c;在此输入命令按回车结束&#xff0…

XMPP文件传输(XEP-0096协议说明)

XMPP XEP-0096协议是XMPP中的文件传输协议。 关于文件传输&#xff0c;在xmpp协议中有不少协议可以实现&#xff0c;而XEP-0096协议是其中非常简单的一个协议。由于邮件被删&#xff0c;我的代码demo丢失&#xff0c;因此只能在这里给大家讲一下其中的逻辑实现&#xff0…

uboot源码——环境变量

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 参考资料&#xff1a;http://www.cnblogs.com/biaohc/p/6398515.html。 一、uboot的环境变量基础 1、环境变量的作用 在不改变源码、不用重新编译的情况下&#xff0c;可以通过设置环境变量…

Linq To Sql进阶系列 -目录导航

博客园CLR基础研究团队|CLR团队精品系列|C# 3.0专题 [Linq To Sql进阶系列] 目录导航 1 Linq To Sql进阶系列&#xff08;一&#xff09;-从映射讲起 本系列&#xff0c;或多或少&#xff0c;直接或间接依赖入门系列知识。但&#xff0c;依然追求独立成章。因本文作者水平有限&…

uboot源码——mmc驱动分析

以下内容源于朱有鹏《物联网大讲坛》课程的学习&#xff0c;以及博客http://www.cnblogs.com/biaohc/p/6409197.html的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 一、uboot与linux驱动 1、uboot是裸机程序 狭义的驱动的概念&#xff1a;操作系统中用来具体操控硬…

RDIFramework.NET(.NET快速开发框架) 答客户问(2014-02-23)

1、框架的部署安装&#xff0c;服务器端和客户端 答&#xff1a;开发版以上版本支持SOA模式&#xff0c;也即真正的面向服务端的模式&#xff0c;在实际使用过程中&#xff0c;可根据项目的实际需要&#xff0c;来选择性的进行部署&#xff08;直连模式或SOA模式&#xff09;&a…

I2C通信——I2C通信的基础介绍

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除 。 参考博客 SPI、I2C、UART&#xff08;即串口&#xff09;三种串行总线详解_天糊土的博客-CSDN博客_串口总线 s5pv210 I2C通信详解 - biaohc - 博客园 嵌入式常用技术概览之IIC(I2C)_C_XianRen的博…

IBM SOA[ESB,BPM,Portal等]基础架构图解

最近公司对众多的异构系统进行SOA化&#xff0c;产品选型为IBM的Websphere系列产品的WMB&#xff0c;BPM&#xff0c;Portal&#xff0c;LDAP等技术&#xff0c;根据具体的描述&#xff0c;连猜带蒙的画了个系统协作图&#xff0c;有不对的地方欢迎大家拍砖....谢谢。 SOA详细技…

css3图标悬停导航菜单

纯css3制作的图标悬停导航菜单&#xff0c;包含9中不同的悬停风格&#xff0c;干净大气。转载于:https://blog.51cto.com/jimanyu/1362823

I2C通信——S5PV210的I2C通信简单案例

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考内容 I2C子系统详解3——I2C总线驱动层代码分析_天糊土的博客-CSDN博客 一、S5PV210的I2C控制器 1、为什么需要控制器&#xff1f; 通信双方通过时序协调工作&#xff0c;但是时序比较复杂而…

POJ 2718

题意&#xff1a;给出最多10个数字&#xff0c;将它们划分为两个整数&#xff0c;求差异值最小的值&#xff08;除非只有一位数&#xff0c;否则不允许出现先导0&#xff09; 题解&#xff1a;很显然如果总共有n个数&#xff0c;必然有一个整数长n/2,另一个长n-n/2&#xff0c;…