0.96寸OLED屏幕滚动程序

前言

  本文章只对0.96寸OLED显示屏幕驱动滚动指令做阐述,而对于取模、字符、数字、汉字和图片如何打印不做论述。

首先,先说明在我学习期间遇到的问题:

???网上同样的滚动驱动指令代码,有的却并没有达到对应的效果。

  原因:驱动芯片的不同。现在市场上正常能买到的0.96寸OLED屏幕的驱动芯片,据我所认识的有两种,一种是SSD1306,另外一种则是SSD1315(购买时询问清楚)。对于大多数的驱动代码,这两种芯片的控制指令集是可以兼容的,但也由于两种不同的芯片,导致屏幕在驱动滚动的指令集上有所差异,如果用芯片SSD1306的滚动指令集去驱动芯片SSD1315控制的OLED屏幕,便会出现上述问题。由于网上SSD1306驱动的滚动指令集已有很多,所以本文的驱动滚动指令集代码针对的是SSD1315芯片驱动的OLED屏幕。因此下文只会出SSD1315芯片的相关知识点,其他芯片一概忽略。

为了方便下面理解,再补充说明一点:

  0.96寸的OLED屏幕,通俗易结的理解就是一块由64*128个小灯泡(也就是所谓的’像素’)组成的屏幕。我们就是通过点亮小灯泡从而组成字符、汉字或者图像的。要实现这一功能我们得通过I2C通讯(本文使用的是I2C通讯)或SPI通讯与OLED屏幕模块搭建通讯通道。操控着单片机对OLED发送指令,而指令又分两种:一种是命令指令(command),用来硬件初始化配置和本文要阐述的滚动指令;另外一种是数据指令(Data),通俗的讲就是发送对应的数据,让指定的哪一盏小灯泡点亮。两种指令区别如下:

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
    OLED_I2C_Start();
    OLED_I2C_SendByte(0x78);//选择要通讯的从机的地址
    OLED_I2C_SendByte(0x00);//写命令(发送0x00指令)  ☆☆☆命令指令和数据指令的区别
    OLED_I2C_SendByte(Command); 
    OLED_I2C_Stop();
}

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
    OLED_I2C_Start();
    OLED_I2C_SendByte(0x78);//选择从机地址(OLED屏幕自带的地址一般都为0x78)
    OLED_I2C_SendByte(0x40);//写数据(发送0x04指令) ☆☆☆命令指令和数据指令的区别
    OLED_I2C_SendByte(Data);
    OLED_I2C_Stop();
}

OK,感谢耐心观看至此!接下来,进入正文。

 一、OLED屏幕水平移动

效果演示

OLED屏幕水平移动演示


看完演示视频,便来看看是如何实现的吧!

  首先,我们知道0.96寸OLED屏幕模块的驱动芯片是SSD1315,而要对一个产品深入的了解,不可避免的我们要从芯片的数据手册(Datasheet)上入手。所以我将SSD1315芯片数据手册上,关于驱动OLED屏幕水平移动的命令表部分,截取放置下面以供学习,如下:

​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​在这里插入图片描述

  通过浏览上诉表格,不知可否已有一点想法。下面是我对此观察、学习、和查阅网上大佬们倾囊相授的资料所总结出来的心得:
  根据上表可知,要使OLED屏幕水平滚动,核心要点就是,得依次(注意:顺序不能乱)发送七条指令,除此之外,还得在开头和结尾各自额外加一条指令,分别是停止滚动(0x2E)和启动滚动(0x2F)。先看以下流程,再做细讲。

     /*  水平滚动设置(九字节指令)*/
    
    OLED_WriteCommand(0x2E);    //先停止滚动,待配置好后再开始滚动
    OLED_WriteCommand(0x26);    //水平向左(0x27)/向右(0x26)滚动
    OLED_WriteCommand(0x00);    //dummy byte(空比特、虚拟字节),暂未发现其指令作用
    
    OLED_WriteCommand(0x00);    //设置滚动起始页地址
    OLED_WriteCommand(0x05);    //设置滚动速度(0x00~0x07数值越小速度越慢)
    OLED_WriteCommand(0x07);    //设置滚动结束页        
    
    OLED_WriteCommand(0x00);    //dummy byte(空比特、虚拟字节)

    OLED_WriteCommand(0x7F);//dummy byte(空比特、虚拟字节),图片最终消失的置 (列)
    
    OLED_WriteCommand(0x2F);    //开始滚动

(注:这里发送的0xxx是命令指令,不是点亮小灯泡的数据指令哦!)



·第①条指令 OLED_WriteCommand(0x2E);

    让OLED屏幕停止滚动,避免一下载程序,屏幕上的内容就动起来。说到这读者也应该明白,其实这一条指令可加可不加,想让屏幕是一开始停止,过一段时间再滚动(在启动滚动前加个延时函数),还是一开始就立马滚动,凭借个人喜好和项目要求来即可,个人建议加上更方便一些,避免内容还没显示上就开始滚动(如果上一次已经开启了滚动),导致乱码,需要复位好多次,或者重新断电上电才能出现正常显示的效果。


·第②条指令OLED_WriteCommand(0x26);

    控制OLED屏幕向左侧(0x27)或者右侧(0x26)水平滚动。若想让OLED屏幕向左侧滚动,就发送命令指令0x27;想让OLED屏幕向右侧滚动就发送命令指令0x26。例:这里发送的是0x26,让屏幕向右侧水平滚动捏。


·第③条指令OLED_WriteCommand(0x00);

    发送虚拟字节0x00,暂未发现该指令的作用,如果有小伙伴知道,可以留言分享一下哦,谢谢。


·第④条指令 OLED_WriteCommand(0x00);

    设置滚动的起始页地址。就是从OLED屏幕的第几行开始,到结束页地址之间的区域水平滚动,其余不含括在内的区域,不会进行水平滚动。取值范围可看上表的B[2:0](0x00~0x07)。例:这里设置的起始页地址是0x00,就是屏幕最顶端


·第⑤条指令 OLED_WriteCommand(0x05);

    设置滚动的速度。取值范围看上表的C[2:0](0x00~0x07),每个取值都有一个对应的帧数,帧数越小,滚动的速度就越快哦。例:这里设置的是0x05,对应的是6帧的速度


·第⑥条指令 OLED_WriteCommand(0x07);

    设置滚动的结束页地址。如指令④中所言,起始页地址到结束页地址之间的区域,进行水平滚动,在此区域外的不会进行水平滚动。例:这里设置的结束页地址为0x07,就是屏幕最后一页,也就是让整个屏幕都水平滚动了起来,需要注意的是,结束页地址要>=起始页地址。(取值范围:0x00~0x07)


·第⑦条指令 OLED_WriteCommand(0x00);

    定义起始列地址。通俗来讲,就是定下来的某一列作为起始列(的地址),OLED屏幕便从这一(地址)列开始做水平滚动。同时!滚动消失的字幕也将重新在这一(地址)列出现,然后一直循环地做水平滚动。例:这里设置起始列地址为:0x00,即左侧最边边的一列 。

·第⑧条指令 OLED_WriteCommand(0x7F);

    定义结束列地址。同样的,定下来某一列做为结束列(的地址),滚动的字幕便会从这一(地址)列消失,然后重新出现在起始列(的地址)滚动出来。例:这里设置结束列地址为:0x7F,即右侧最边边的一列。注意:结束列地址 >= 起始列地址


·第⑨条指令 OLED_WriteCommand(0x2F);

    让OLED屏幕开始滚动。经过前面的命令,设定完毕之后,就剩这最后一步便可以启动OLED屏幕开始滚动啦。
在这里插入图片描述



 二、OLED屏幕垂直滚动

效果演示

垂直上、下滚动演示

好的,感谢各位看官,看完继续挥动我们的三板斧。一板斧,上数据手册操作指令截图!!!


在这里插入图片描述


  根据上表可知,要使OLED屏幕垂直滚动,核心得依次(注意:顺序不能乱)发送八条指令,除此之外,记得在开头和结尾各自额外加一条指令,分别是停止滚动(0x2E)和启动滚动(0x2F),先挥动二板斧,再做细讲。

OLED_WriteCommand(0x2E); //先关闭滚动,

OLED_WriteCommand(0x2A);    //垂直水平向左滚动(0x2A),垂直水平向右滚动(0x29)
OLED_WriteCommand(0x01);    //水平滚动关闭(0x00)、开启(0x01),控制水平运动方法①

OLED_WriteCommand(0x04);    // 起始页地址
OLED_WriteCommand(0x05);    // 滚动时间的间隔                                                            
OLED_WriteCommand(0x05);    // 终止页地址    
 
OLED_WriteCommand(0x01);    //垂直滚动偏移量                                          
          
OLED_WriteCommand(0x00);        //起始列地址,控制水平运动方法②
OLED_WriteCommand(0x00);        //终止列的址
    
OLED_WriteCommand(0x2F);        // 开启滚动

·第①条指令 OLED_WriteCommand(0x2E);

    设置OLED屏幕停止滚动。有个好处就是避免还没配置好就开始滚动,大部分会致使屏幕乱码现象,需要复位好多下才能正常显示,所以在配置之前,最好能让屏幕先不要动,先让字幕显示在屏幕上,一切准备就绪后再开启滚动。


·第②条指令 OLED_WriteCommand(0x2A);

    设置垂直水平向左滚动(0x2A)、或垂直水平向右滚动(0x29)。细心的朋友应该发现,这里除了垂直滚动还有水平滚动的作用,也就是垂直+水平(斜线)运动。是的,这里设置的就是这两项运动同时进行,但是为什么演示里只有垂直运动,而没有水平运动呢?这是因为下面有指令(我在对应的指令旁边标了☆×5)能让水平运动不进行,而且有两钟方法,下面再做细讲。例:这里设置的是垂直水平向左滚动。


·第③条指令 OLED_WriteCommand(0x01); ☆☆☆☆☆

    数据手册上给的说明是设置列滚动偏移量数。但以我的理解,这条指令的作用就是使能(0x01)或失能(0x00)水平滚动。也就是开启或关闭屏幕的水平滚动功能,视频中演示的只做垂直运动,就是将水平运动给失能了,但是这里我明明发送的指令是0x01使能,开启了滚动呀,为什么没有水平滚动呢?因为我用了另外一种方法(下面将会讲到,再做细讲),让水平滚动没有进行,或者进行的地方并不是有字幕的区域,所以有字幕的区域就不会有水平的运动啦。例:这里设置的是使能水平运动。


·第④条指令 OLED_WriteCommand(0x04);

    设置起始页地址。经过设置上一个实验水平滚动的赘述,大家应该有所意识了吧,这里设置的就是从第几页(行)开始,到第几页(行)结束之间的区域进行滚动。但是其实这里有个小bug,就是只要你让指定的一页(行)进行滚动,你会发现整个屏幕都是会滚动起来的,而并不是说只是让这一页的字幕进行滚动,其余的静止,要做到这情况需要增加额外的指令,下一个实验再做补充说明。但是!这是起始页到结束页的选取,却可以让你选择你要指定的哪一页(行)进行水平运动(从而让这一页的字幕做斜线运动),视频中不做演示,稍后过完整个流程你可以自己尝试尝试。例:这里设置的起始页地址为0x04。

(简约说明:起始页地址到终止页地址之间做,垂直+水平【==斜线】运动。剩余的都只做垂直滚动,没有水平运动)


·第⑤条指令 OLED_WriteCommand(0x05);

    设置时间间隔(可以理解为速度)。取值范围为:0x00-0x07,对应的帧数越大,间隔也就越大,即速度越慢。例:这里设置的是0x05,对应的帧数为4帧,速度即是视频演示的速度。(取值范围0x00~0x07)

·第⑥条指令 OLED_WriteCommand(0x05);

    设置结束页地址。看过起始页地址的解说,应该有所理解了,这里就不做多赘述了。例:这里设置的结束页地址为0x05。例:结束页地址 >= 起始页地址。(取值范围0x00~0x07)


·第⑦条指令 OLED_WriteCommand(0x01);

    设置垂直滚动偏移量。简单的理解就是,垂直移动一次,挪动多少行。比如0x00偏移量为0,即垂直方向移动一次,挪动0行,也就是垂直方向并没有移动,不滚动了。数值越大,移动一次跳跃的间隔也就越大,比如0x03偏移量为3,即垂直方向移动一次,挪动3行,视野上呢就是跳跃一样!重点来啦!!!重点来了!!!若想让屏幕垂直向下滚动,就是在这一步发送指令0x3F啦!,速度是和0x01(垂直向上滚动)对应的,然后想要让偏移量增大的话就是减小数值,比如0x3E、0x3D…。例:这里设置的偏移量是0x01,移动一次挪动一行。


·第⑧条指令 OLED_WriteCommand(0x00); ☆☆☆☆☆

    设置起始列地址。这里设置的就是列,也就是横的方向,长宽中的长、水平移动的方向上的运动范围了。通过设置起始列地址到结束列地址,可以选择指定列的范围做水平运动,其他的列不做水平运动,然后通过设置起始、结束页地址和起始、结束列的地址,就可以实现哪几页、哪几列进行垂直+水平运动,其余的做垂直运动。这就是控制水平运动第二种方法!如本次演示视频的中的实现代码里,第③条指令我将水平运动使能,但是视频中演示的只做垂直运动,就是因为我将水平运动的列的范围限载在没有字幕的区域,所以屏幕上有字幕的区域并没有做水平运动,只是做垂直滚动。例:这里设置的起始列地址为0x00。


·第⑨条指令 OLED_WriteCommand(0x00); ☆☆☆☆☆

    设置结束列地址。这里设置的结束列地址为0x00,即我只是让0x00这一列做水平运动,但是这一列上并没有字幕啥的,所以这一列做水平运动了也看不出来,不会影响到其他列的运动状态。例:这里设置的结束列地址为:0x00。注:结束列地址 >= 起始列地址(取值范围0x00~0x7F)


·第⑩条指令 OLED_WriteCommand(0x2F);

    启动滚动。快去尝试尝试吧!

(个人疑惑:有一个功能我始终没能实现,那就是让指定的区域做垂直运动,剩余的区域静止不动。查阅了网上很多资料也并没有找到对应的实现程序,如果有哪位小伙伴发现了这个功能,拜托告知我一声,谢谢了!!!)



 三、OLED屏幕垂直、水平、斜线、静止运动

效果演示

屏幕多运动状态演示

看完上述演示视频,观察可发现,

在这里插入图片描述


  A、B区域做水平滚动;A、C区域做垂直滚动,所以他们的交集A区域既有垂直滚动又有水平滚动,也就是在做斜线运动了。而剩余的D区域则静止不动。这是如何实现的呢?其实就是在实验二的基础上,再添加三条指令(设置垂直滚动区域),先见如下数据手册节选:


在这里插入图片描述


  废话不多说,继续上二板斧,再做探讨(有了前面知识的讲解,所以下面重复的便简略带过,不加以详细分析啦)!

    OLED_WriteCommand(0x2E);       // 先关闭滚动

    //设置垂直滚动的区域【除去这个范围的行,其余全都是水平移动--若有开启】
    OLED_WriteCommand(0xA3);        //选择垂直滚动的行区域命令(0xA3)
    OLED_WriteCommand(0x00);        //起始行地址(取值范围:0x00-0x3F)
    OLED_WriteCommand(0x10);        //终止行地址    
    
    OLED_WriteCommand(0x29);        // 0x29是垂直水平向右滚动,0x2A是垂直水平向左滚动
    OLED_WriteCommand(0x01);        //水平滚动关闭(0x00)、开启(0x01)

    
    //设置水平滚动的区域【除了这个范围内,其余的不做水平滚动(既不做水平又不做垂直滚动的区域静止)】
    OLED_WriteCommand(0x00);        // 起始页地址(取值范围:0x00-0x07)
    OLED_WriteCommand(0x04);        // 滚动时间间隔
    OLED_WriteCommand(0x03);        // 终止页地址     
    
    
    OLED_WriteCommand(0x01);        // 垂直滚动偏移量(0x0F向下滚动)、0x4F、0x8C、E、F、0x90、0xD0


    // 选择要作用的列【除去这个范围的列,其余全都是垂直移动--若开启】
    // 水平滚动的区域将会发生在被选用的区域①
    OLED_WriteCommand(0x00);        //起始列地址(取值范围:0x00-0x7F)
    OLED_WriteCommand(0x57);        //终止列地址

    OLED_WriteCommand(0x2F);        // 开启滚动  



·第①条指令 OLED_WriteCommand(0x2E);

    设置停止滚动。可加可不加,但是建议加上,避免一下载就滚动致使乱码。


·第②条指令 OLED_WriteCommand(0xA3); ☆☆☆

    这②、③、④的代码指令就是与实验②的区别所在啦!首先该条指令就是设置垂直滚动区域。就是告诉从机OLED模块,我要设置垂直滚动的区域啦,你准备好!然后接着将区域(起始页地址到结束页地址)发送给从机,从机便按照指令执行,只让指定的区域做垂直运动啦。剩余的做水平运动,如果连水平运动都没有的话,就是静止状态啦!!!

(注意:0xA3就是要设置垂直滚动区域的指令,然后接着发送的两条指令从机都会认为是设置的垂直滚动的区域地址)


·第③条指令 OLED_WriteCommand(0x00); ☆☆☆

    设置(垂直滚动)起始页地址例:这里设置的起始页地址为:0x00。


·第④条指令 OLED_WriteCommand(0x10); ☆☆☆

    设置(垂直滚动)结束页地址。起始页地址到结束页地址之间的区域做垂直滚动,其余的区域不做垂直滚动。这时对这些区域设置水平滚动,就只做水平的滚动,如果连水平滚动都没有,即是静止状态。

(注意:这里设置的页地址,针对的是垂直运动!!!)


·第⑤条指令 OLED_WriteCommand(0x29);

    设置垂直水平向左滚动(0x2A)、或垂直水平向右滚动(0x29)。例:这里设置的是垂直水平向右滚动。


·第⑥条指令 OLED_WriteCommand(0x01);

    设置列滚动偏移量数。实验二有详细讲解(就是使能或失能水平滚动),这里不做多的赘述了。例:这里设置的为0x01,使能水平滚动。


·第⑦条指令 OLED_WriteCommand(0x00);

    设置(水平滚动)起始页地址


·第⑧条指令 OLED_WriteCommand(0x04);

    设滚动时间间隔。与实验二一致,如若不懂返回实验二详细看即可。


·第⑨条指令 OLED_WriteCommand(0x03);

    设置(水平滚动)结束页地址

(注意:这里设置的页地址,针对的是水平滚动!!!)


·第⑩条指令 OLED_WriteCommand(0x01);

    设置垂直滚动偏移量。这里详细讨论一下,这里要使垂直滚动方向向下呢,不再是像实验二一样的规律了,而是要发送0x0F,经过我的多方尝试,我发现在这条指令上,发送不同的数据是有各种的情况出现的,比如大家可以尝试发送0x4F、0x8C、0x8E、0x8F、0x90、0xD0指令试试看,如若还发现了什么新奇的指令效果,不妨留言告知一二,一起学习进步呀!!!例:这里设置的偏移量是0x01,垂直向上滚动。


·第①①条指令 OLED_WriteCommand(0x00);

    设置起始列地址例:这里设置的列的地址为0x00,就是最左侧的边边一列。


·第①②条指令 OLED_WriteCommand(0x57);

    设置结束列地址。(参考实验一的讲解)定义好起始列的地址和结束列的地址后,在这些列构成的区域做水平运动,剩余的列呢就不做水平运动,又因为垂直滚动只发生在第一页,所以剩余的区域D就是静止状态啦!希望不要绕晕咯。例:这里设置的列的地址为0x57。

(注意:这里的列的地址,针对的是水平运动!!!)


·第①③条指令 OLED_WriteCommand(0x2F);

    启动滚动

  OK,有关SSD1315芯片驱动的OLED屏幕,如何驱动屏幕运动的有关实验到此就完结撒花啦。我相信观看到这里的读者一定很累很辛苦,但是获取知识的过程本就不是一蹴而就的,同时也正是这些痛苦才使我们收获硕果时,充满着如获珍宝的喜悦,甚至这种喜悦是超越珍宝所能带来的快乐的。新手第一篇博客内容,希望能够对你有所帮助,如若有不到之处,欢迎指出点明,共同学习进步!!!




等!等!等!等一下

再给大家附上一点小功能指令,具体详情,通过以上的学习方法自己去摸索摸索吧!

功能一:设置布灵布灵的闪烁或者逐渐淡出的功能!

    /*  设置淡出或闪烁(双字节指令)  */
    OLED_WriteCommand(0x23);        // 设置淡出or闪烁指令(0x23)
    OLED_WriteCommand(0x30);  // **A5A4 A3-A0:设置每个淡出步骤的时间间隔     
                                    //禁止模式(0x0?)   淡出模式(0x2?)    闪烁模式(0x3?)

功能二:设置缩放,就是将内容放大。
 /*  设置缩放(双字节指令)  */
    OLED_WriteCommand(0xD6);         //设置缩放指令(0xD6)
    OLED_WriteCommand(0x00);         //0x00:禁用        0x01:启动缩放

功能三:内容移动设置。跟水平滚动的区别是,这一套指令集发送一次只会移动一列。
    /*  内容移动设置(执行一次挪动一列,且仅移动设定的范围内的屏幕),若连续发送此移动指令,指令之间必须间隔12ms以上,否则出现乱码 */
    OLED_WriteCommand(0x2C);        //向右(0x2C)/向左(0x2D)滚动一列
    OLED_WriteCommand(0x00);        //虚拟字节(设置为0x00)
    
    OLED_WriteCommand(0x00);         //设置起始页地址
    OLED_WriteCommand(0x01);         //虚拟字节(设置为0x01)
    OLED_WriteCommand(0x07);         //设置终止页地址
    
    OLED_WriteCommand(0x00);         //设置起始列地址,
    OLED_WriteCommand(0x7F);         //设置终止列地址,数据消失于此列

快去试试吧!

(有一点值得留意,就是在发送命令指令集中间,发送数据指是不会造成命令流程造成影响的?!可以自己做做实验佐证一下。)

  • 16
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值