如何使用 MCU 驱动 LCD 显示图片

关键字 :MCU 驱动LCD

        从上一篇文章中我们已经知道了 LCD 屏上的每一个像素点是怎样点亮的。那么本篇文章会告诉大家,LCD 屏上的每一个像素点是如何被点亮为不同颜色的,又是如何通过不同位置的像素及每个像素的不同颜色来会出各类风
格的图画。

一、显存

        首先我们需要引入一个新的名词:显存——保存显示内容的存储空间

        上一篇文章已经给大家介绍了,MCU 是通过 RGB 三组数据线来控制每一个像素点的颜色,然后通过同步信号依次去遍历每一个像素点。

        那么问题来了,这里的 RGB 数据是从哪里来的呢?

        是每次需要用到 RGB 数据的时候临时计算出来的吗?

        还是我们先找一块空地将这些数据先存起来,然后再从这块空地里去拿我们所需的数据呢 ?

        目前我们大多数方案都是采取找一块空地先将数据存起来的这个方案,规范点讲就是我们会为需要用到的显示数据划一块存储空间即显存,将数据保存在显存中,然后再从显存中取数据送到 LCD 上。

        既然确定了我们采用的是显存方案,那么紧接着又出来两个问题了。

        1)显存大小是多少呢?我们应该给显存划多大的空间?

        2)如何使用显存?或者说怎样通过控制显存来达到控制 LCD 的目的?

        对于第一个问题我们首先得清楚我们得显示方案中比较重要的两个参数:颜色深度和分辨率,知道这两个参数后将他们代入下列算式中即可:
        
        显存大小(Byte) = 颜色深度(Byte) * 分辨率

        以颜色采用 RGB565,分辨率为 480*272 分辨率得显示方案为例,该方案的颜色深度为 2 Byte。        则显存大小为 2 * 480 * 272 = 261,120 Byte = 255 KByte

        在程序中申请显存的体现如下

        uint8_t VARM[261120];

        或者

        uint8_t VARM[130560][2];

        再或者

        uint16_t VRAM[130560];

        无论是哪一种形式出现在程序中,只需要保证申请的的空间大小为 255 KByte 即可。

        对于第二个问题,我们得更为深入得去了解显存和 LCD 显示之前的关系。从上述显存计算及显存空间的申请方式来看,可以看到针对于每一个像素点都会分配一个大小为其像素点所显示的颜色深度大小的空间。还是以颜色采用 RGB565,分辨率为 480*272 分辨率得显示方案为例,显存空间一共需要申请 255 KByte,每个像素点分配 2 Byte 的空间去存储颜色信息。内存从低地址到高地址,LCD 从左上角到右下角,按照这个顺序我们可以建立起一个映射机制,每 2 Byte 映射到一个像素点。那么我们就可以改变内存显存中相应地址的数据从而达到改变 LCD 的目的,例如将 LCD 的第 66 行第 66 列的像素点设置为黑色,我们可以按照以下操作去做(内存申请方式采用
③):

        VRAM[66 * 480 + 66] = 0x0000;

        只需这一行代码,待显存数据刷到 LCD 屏上时,第 66 行 66 列的像素点就会变成黑色了。

 

二、图片

        在我们使用电子产品的时候我们看到的最多的内容就是图片了,通过上面学习我们应该可以比较清晰的知道图片是怎样显示到 LCD 屏幕上去的:图片中有每个像素点的颜色信息,然后将这些信息存储到显存中,再通过同步信号将显存中的数据推到 LCD 屏上,LCD 屏上就显示出图片了。

        在显存中一般都会存储着能够直接推给 LCD 的信息,当然这个显存是 RAM,有 RAM 当然就少不了 ROM 这东西,类似于电脑硬盘,手机 SD 卡之类的。图片通常都是先存储在 ROM 里面,然后在需要显示图片的时候我们才会将图片从 ROM 里搬运到 RAM 里。虽然说图片数据放在 RAM 里面不可精简的(不要问为啥不可精简),但有好事者发现图片的数据存放在 ROM 里的时候并不需要像存放在 RAM 里一样不可精简,反而是可以做很多奇妙的操作。例如一张纯黑的图片存在显存里的时候需要让每个像素点的颜色信息都填充为 0x0000,但存在 ROM 里的时候可能就只需要存图片的长宽和一个 0x0000,以一个非常小的数据量存下一张纯黑图片。

        基于这种思路,现在世界上出现了很多很多的图片压缩方案,例如我们比较常见的有 jpg,png,svg 这些,体现在实际生活着就是我们所看到的各式各样的图片了。

 

三、LCD 显示图片

        从前面两节中我们已经知道如何用 LCD 显示不同的画面(改变显存的内容),以及图片的基本情况(什么放在显存中,压缩一类的东西),那么接下来便用以上的信息来实现将图片显示在 LCD 上去。

        基本流程就是将图片存到 ROM 中去,然后将图片数据从 ROM 搬到 显存中去并展开,然后再让显存的数据推到 LCD 上去,就完成了将图片显示到 LCD 上,看上去还是比较简单的,下面就来演示下具体的做法:

        ①、找到合适的图片,图片大小和 LCD 屏大小一致,图片的格式选用 bmp(该格式并未进行压缩),然后以数据的形式存放在 ROM 里。

        ②、读取 bmp 图片的数据,从中提取显存需要的内容,如下图所示,无论任何文件都是以数据形式保存的,我们将 bmp 图片以数据形式打开,其具体情况就如下图所示,一堆的数据。

 

        ③、如上图蓝色区域内的数据,它们的形式是以 3 Byte 为一个单元进行排列的,由此可以推断出该图片每个像素的颜色深度为 3 Byte,而我们需要的颜色深度是 2 Byte,需要进行 RGB888 -> RGB565 的转换,可以通过下面的算式进行转换:

        #define RGB888_RED      0xFF0000

        #define RGB888_GREEN 0x00FF00
        #define RGB888_BLUE 0x0000FF
        uint16_t rgb888_to_rgb565(uint32_t color_rgb888)
        {
            uint16_t color_rgb565 = 0;
            /* RGB888 转 RGB565 */
            uint8_t color_red = (color_rgb888 & RGB888_RED) >> 16 >> 3;
            uint8_t color_green = (color_rgb888 & RGB888_GREEN) >> 8 >> 2;
            uint8_t color_blue = (color_rgb888 & RGB888_BLUE) >> 3;
            color_rgb565 = (color_red << 11) + (color_green << 5) + color_blue;
            return color_rgb565;
        }

        ④、得到 bmp 图片的数据并转成 RGB565 的形式后以常量的形式存在 ROM 里,然后当 MCU 开启后,将 ROM 里面的 bmp 图片的数据搬运到 RAM 里刷新 LCD 后,LCD 屏便显示出图片了。

 

PS: 看完本篇博文,相信你已经比较清楚 LCD 上各种各样的内容是怎样显示出来的了,电脑端的素材如何在 MCU 的 LCD 屏上显示。那么想不想继续深入下去,不仅仅是做 memcpy 这么简单粗暴操作,而是采用更为巧妙的去操控显存呢?那就敬请期待下一章节《界面设计小助手:GUI 库》吧!!!

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论