如何移植μC/GUI在OLED12864上显示

来源:互联网 发布:知乎中国出口构成 编辑:程序博客网 时间:2024/05/21 15:26


     最近难得有时间休息,作为一个技术宅,也不能闲着是吧?于是乎花了一天的时间成功的将uCGUI移植在0.96寸单色OLED上显示。那么有的人该说了,它的分辨率只有128X64,没必要移植,呵呵,怎么说呢,在某些场合使用OLED非常合适。而且现在的OLED使用范围越来越广,所以研究下很有必要。

     那么该如何移植呢?首先我们应该明白uCGUI的工作原理:就是不断地调用画点函数画出来各种字符,图片等等,这是最基本的函数之一,其次就是读点函数:读取某个位置点的颜色,状态等。有了这两个函数一切都非常的好办。

     移植的总体步骤:

1、一个较好的硬件平台、正常显示的OLED源码、uCGUI

2、编写OLED的画点函数、读点函数、初始化函数

3、在uCGUI配置文件中更改相应的配置

4、移植成功。

    这里我重点想讲一下如何编写OLED的画点函数、读点函数。

    一般的OLED上没有这两个函数,反正我的OLED没有,那么为什么会这样呢??因为如果将那些功能函数都按照画点来写的话,OLED的显示比较缓慢,显然这是不合理的做法。那么我们就要自己编写这个函数了。

    我在网上找了半天没找到,无奈只能知己写了,于是乎打开了OLED驱动芯片SSD1306的数据手册,不要多想,全部是英文,只能硬着头皮看了。

    我们应该先明白SSD1306是如何工作的,下面看图:

 

上面的英文大概就是:GDDRAM是位图静态对应显示,128x64大小的RAM被分成8个页,从PAGE0~PAGE7,至于那个被用于显示,看下图:

 

大概翻译:当一个字节的数据被写入到GDDRAM中,所有的同一页的同一列的所有行被填满,数据的D0位被写入到顶部的行,数据的D7位被写入到最低行。

    好了,看到这两个图和这几句话我们就基本上明白它是如何显示的了;就是这样,一个共128*64个点的屏幕被分成了8个横着的块,每块有8*128个像素,向OLED写入数据时,低位在每块区域的最上面,高位在每块区域的最下面。比如:我们向第28行的第5列(也就是x=5,y=28的位置,x<=127,y<=63)写入一个数据为0xf0,线确定28行在那个区域才可以,28/8=3...4,也就是在PAGE=3的页的第4-1=3行。0xf0会被全部写入到第三页。

   那么我们需要的是在某个点写入一个数据,在写入时我们不希望影响到其它位的数据,我们先要确定这个点在那个页面的哪个行,然后将数值0x01向左移相应的位数,在或上原来点的数即可。下面看代码:

   

函数开始先判断数值是否合理,然后在操作控制端口准备写入数据,先通过y值取整判断第几页,然后取余具体到哪一行,然后将0x0向左移余的位数,接下来开始向驱动器写入指令

transfer_command_lcd(0xb0+pos);  每个驱动器都有其指令,下面我们来看下手册上的指令

  指令0xb0是设置页的起始地址,后面三位数X[2:0]具体设置到那个页,所以指令:0xb0+pos,设置了具体的页。然后开始设置列的地址指令看下图为:0x21。

 

在向其中写入列的指令后,再写入两次列的起始和结束的地址,直接写入十进制的列即可。

    因为我们的OLED是单色显示,所以写入数据1就为白,写入0就是黑,下面程序开始判断,我们先使用一个数组OLED_GRAM[x][pos]记录原来位置的数据,在将要写入的数据temp或上去然后调用写数据的函数transfer_data_lcd(OLED_GRAM[x][pos])将数据从新写入即可。

   最后操控控制端口将数据写入,这样指定画点的函数就完成了。

下面我们开始写读点的函数,由于我的OLED使用的是四线SPI的方式,手册上没有说明如何读数据,也就是说这种通讯方式只能向里面写入数据,不能读。看图:  

    那是不是没办法了呢?我们仔细想一想,OLED只是单色显示,也就是说在某个点上,有数就是白,没有就是黑,也就是0和1的区别,之前我们定义了一个显存数组,保存了每个点的数据,我们直接将显存中的数拿出来不就行了??于是乎读点函数就完成了。

      代码如下:

 

同样,先设置点的位置,然后将位置的值给数组,再将数组中的数据返回即可。有了这两个函数,移植就成功了一半!

    我再大概讲一下uCGUI的配置问题:配置只要细心就没什么问题。

配置文件用到的有:LCDDummy.c、GUIConf.h、LCDConf.h。

    第一个文件开始的头文件包含自己的OLED函数,还有相应的值为-1;

 

然后将文件中的函数void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)中的内容全部换成自己的画点函数OLED_DrawPoint(x,y,Point);将函数unsigned int LCD_L0_GetPixelIndex(int x, int y)中的内容全部换成自己的读点函数OLED_ReadPoint(x,y);

将函数LCD_L0_Init(void)中的内容换成自己的初始化函数OLED_Init();这样第一个配置文件就完成了。

    第二个文件:GUIConf.h

 

    第三个文件:LCDConf.h

 

 

   最后包含GUI.h文件,调用初始化函数GUI_Init();即可,下面是我的主函数代码:

 

移植成功了之后的效果图:

                 

怎么样,是不是很好看,我花了一天的时间终于完成,上午基本上在写读点函数,然后写好了就很快完成了,还是蛮不错的,最后一个时文本的反白显示,由于是单色,显示的效果不是很理想,但是可以满足很多应用了,总结起来基本上只需改动:LCDConfig.h、GUIConfig.h、LCDDummy.c、LCDDriver.c这几个文件和编写好相应的函数即可。所以还是比较容易的。
在移植过程中需要注意头文件是否正确包含,以及在LCD驱动中修改相应的以LCD为名的结构体指针,将其改成其他的名字如LCD2等,这样不至于和uC/GUI中的结构体冲突,一位它们也有一个叫LCD的结构体指针。还有就是移植时正确的设置MDK工程,在相应的C文件中包含正确的头文件。只要细心,认真,很容易就移植成功。
    后面还有对uC/GUI相关函数优化,使用LCD自带的函数替换、这样可以使得效率更高。还有相应的功能函数等,在这就不讲了,根据手册做就可以了。

 

                                 2015-09-26-21-48  大哥

 

 

 

2 0