分享一个LCD驱动框架

首先需要说明的是本篇文章不是关于如何点亮一块LCD屏的教程,而是介绍一个LCD开发框架,更准确的说是介绍一个LCD的中间件(Middlwware),用来连接UI和不同类型的LCD屏。笔者本人的工作内容中很重要的一部分就是在不同的LCD屏上做UI开发,所以对如何最大程度复用LCD代码以及解耦屏驱有着一定的理解。好了,话不多说进入正文。

1、最初的代码

在写这篇文章的时候笔者翻看了自己在大二时候点的第一块屏幕(TFTLCD,驱动IC为ILI9341)的代码,看着自己几年前写的代码,思绪仿佛又回到了几年的那个夏天.......,咳咳,不好意思有点"触码伤情"了,回到正题,当时写的代码最大的问题就是------LCD的应用和驱动没有分离,耦合在一起。

如果仅从实现功能的角度来说完全ok的,但是从项目开发角度来看还是有不少问题,因为实际项目不可能一直只用一款屏或者MCU,一旦二者之一发生改变就意味着LCD驱动会改变,而LCD应用和驱动又是紧密耦合的,必然会受到影响要做出改变。这是不合理的,LCD应用是针对屏幕这个大类而不是具体的屏幕对象,比如说我要在屏幕显示一串字符"hello world",对LCD应用层来说是:"我要在这块屏幕(A屏、B屏...)显示hello world,但是具体怎么实现显示,我不关心,我只要结果"。另外一种情况就是如果一个项目要使用两块或者多块屏(虽然实际上这种情况很少见,就我个人目前还没遇到过),那是不是要LCD应用代码复制两份甚至更多,这明显会增加代码体积,而且看着也别扭。所以LCD框架就呼之欲出了。

2、呼之欲出的LCD框架

现在开始进入本篇文章的核心部分,理解下面的内容需要掌握结构体、函数指针等基础知识。为了对该框架有个宏观的认识,我准备了一个框图,如下所示:

下面我将以ILI9341 240*320的TFTLCD屏幕设备的添加过程,让大家对这个框架有更深的认识。

2.1、添加屏驱lcd_ili9341.c

本次使用的是8080接口和ILI9341进行通信,对于具体的驱动代码这里不做赘述,主要说明如何在屏驱中添加一个LCD设备,如下图所示:

其中lcd_driver是屏驱对象,包含了初始化、填充、开关显示等操作,其LcdDriverType_t类型在lcd_typedef.h中定义。lcd_ili9341_dev就是一个LCD设备,使用时需要被注册到LCD设备表中,该设备类型中包含设备的名称、分辨率、屏驱等信息,LcdDeviceType_t类型也是在lcd_typedef.h中定义。

2.2、添加lcd_ili9341_dev设备。

(1)在lcd_device.h中extern声明lcd_ili9341_dev,如下图所示:

同时在lcd_config中加上CONFIG_LCD_ILI9341的宏控,如下所示:

(2)将lcd_ili9341_dev添加到lcd_device.c中LCD设备表中如下图所示:

至此,一个新的LCD屏幕设备添加完成,我们可以通过Lcd_DeviceOpen()函数来打开这个设备并进行操作。下面是Lcd_DeviceOpen()函数的实现:

(3)使用样例

上述代码中打开了一个名称为"lcd_ili9341"的屏幕设备,并在起点坐标为(20,20)填充了一个宽200,高200的红色矩形,实际现象如下图所示:

3、未完待续。。。

4、总结

我始终认为对代码最好的解释就是代码本身,理解代码很多时候都是只可意会不可言传,所以后续我会将LCD框架这部分代码上传到gitte上,希望能给大家带来点收获,同时热切希望大家提出自己宝贵的想法,一起交流完善!!!