2019-07-08

01-01:    0.96寸oled模块详解

版权声明:Copyright © 2016-2019,Stardust Studio, All Rights Reserved

本文将从以下四个方面详细介绍oled模块的使用:

一、入门

二、进阶

三、高阶

四、网传程序存在的不合理问题

一、入门

在阅读后续内容时请先详细阅读:

1.OLED显示模块驱动原理及应用(点击即可跳转到http://blog.sina.com.cn/s/blog_57ad1bd20102wtq8.html);

2.(中文翻译版,版本:据内容推断为Sep 2007 Rev 1.0)OLED SSD1306 DataSheet(点击即可跳转到https://wenku.baidu.com/view/10b60c264a73f242336c1eb91a37f111f1850d88.html);

3.(英文原版,版本:Aug 2010 Rev 1.5)OLED SSD1306 DataSheet(点击即可跳转到https://wenku.baidu.com/view/3510c4f2915f804d2a16c1a8.html);

4.0.96寸OLED驱动详解(带字库)(点击即可跳转到https://wenku.baidu.com/view/cc5ae02b7f1922791788e831.html);

注:(1)本文是参照英文原版Rev 1.5,使用stm32F103系列单片机和4Pin IIC OLED来编写驱动程序的;

    (2)中文翻译版存在一些问题,仅供参考,所以要结合英文原版手册学习;

    (3)百度文库要付费下载,读者可以下载 “ XX文库 " 免费下载文档;

学习方法:(1)前三份文档是重点,先着重看完第一份文档,对oled有了了解之后详细看第二份文档,结合英文手册对oled有总体认知;

                (2)在学习时要对各种寄存器写入进行测试以便加深理解;

二、进阶

在大致看完前面四份文档后相信读者对oled显示屏已经有了大致的了解,那么现在到了看寄存器配置的时候了:

void OLED_Init(void)

{

//delay_ms(100); //这里的延时没有必要,IIC初始化相当于延时

/*指令集根据(SSD1306 DataSheet Aug 2010)编写*/

WriteCmd(0xae); //(display off)

/*(一)基础指令*/

WriteCmd(0x81); //(set contrast control register,亮度控制)

WriteCmd(0xff); //(亮度调节范围:0x00~0xff)

WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content,a5即白屏,无视RAM内容,用于测试显示屏)

WriteCmd(0xa6); //(set normal display,a7:反相显示,亮的部分变暗,暗的部分变亮)

// WriteCmd(0xae); //(display off,顶部已开启)

// WriteCmd(0xaf); //(turn on oled panel,底部已开启)

/*************/

/*(二)滚动显示*/

// WriteCmd(0x26);//(26h:水平右滚 27:水平左滚 29h:Vertical and Right Horizontal Scroll 2ah:Vertical and Left Horizontal Scroll)

// WriteCmd(0x00);//(固态字节(芯片固定字节,用户不可改动)

// WriteCmd(0x00);//(滚动起始页)

// WriteCmd(0x01);//(滚动速度,64 frames)

// WriteCmd(0x07);//(滚动结束页)

// WriteCmd(0x00);//(固态字节,如果是29h或2ah(h是16进制数的意思)则取值为0-63)

// WriteCmd(0xff);//(固态字节,如果是29h或2ah(h是16进制数的意思)则注释这行)

// WriteCmd(0x2e); //(关闭滚屏)

// WriteCmd(0x2f); //(激活滚屏)

// WriteCmd(0xA3); //(设置滚屏范围)

// WriteCmd(0x08); //(不滚屏的行数)

// WriteCmd(0x20); //(要滚屏的行数)

/*************/

/*(三)地址设置*/

// WriteCmd(0x00); //(set low column address,初始化设置了没用,因为OLED_SetPos函数中会重设)

//

// WriteCmd(0x10); //(set high column address,初始化设置了没用,因为OLED_SetPos函数中会重设)

WriteCmd(0x20); //(Set Memory Addressing Mode)

WriteCmd(0x10); //(00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid)

// WriteCmd(0x21); //(列(起止)地址)

// WriteCmd(0x00); //A[6:0] : Column start address, range : 0-127d,(RESET=0d)

// WriteCmd(0x7F); //B[6:0]: Column end address, range : 0-127d,(RESET =127d)

//

// WriteCmd(0x21); //(行(起止)地址)

// WriteCmd(0x00); //A[2:0] : Page start Address, range : 0-7d,(RESET = 0d)

// WriteCmd(0x07); //B[2:0] : Page end Address, range : 0-7d,(RESET = 7d)

// WriteCmd(0xb0); //(Set Page Start Address for Page Addressing Mode,0-7,初始化设置了没用,因为OLED_SetPos函数中会重设)

/*************/

/*(四)硬件配置*/

WriteCmd(0x40); //(set start line address,从RAM中哪一行起读取显示内容)

WriteCmd(0xa1); //(set segment re-map 0 to 127,列显示次序反向)A0h, X[0]=0b: column address 0 is mapped to SEG0 (RESET) | A1h, X[0]=1b: column address 127 is mapped to SEG0

WriteCmd(0xa8); //(set multiplex ratio设置只扫描哪些行,可提高帧率)

WriteCmd(0x3F); //(范围16-63)

WriteCmd(0xc8); //(Set COM Output Scan Direction,即行扫方向)C0h, X[3]=0b: normal mode (RESET) Scan from COM0 to COM[N –1] | C8h, X[3]=1b: remapped mode. Scan from COM[N-1] to COM0

WriteCmd(0xd3); //(set display offset,行扫偏移,公共极(垂直)方向移动)

WriteCmd(0x00); //(not offset)

WriteCmd(0xda); //(set com pins hardware configuration,4种组合,再结合行扫方向有8种)

WriteCmd(0x12); //(设为默认值)A[4]=1b(RESET), Alternative COM pin configuration | A[5]=0b(RESET), Disable COM Left/Right remap

/*************/

/*(五)时序设置*/

WriteCmd(0xd5); //(set display clock divide ratio/oscillator frequency)

WriteCmd(0xf0); //(set divide ratio频率设置成最高407 kHz,分频系数为1)

WriteCmd(0xd9); //(set pre-charge period,充电、放电周期1-15设置)

WriteCmd(0x22); //(设置为默认值2DCLK)

WriteCmd(0xdb); //(设置Vcomh电压,防止单元串扰,Vcomh反压)

WriteCmd(0x20); //(20h ~ 0.77 x VCC (RESET))

/*************/

/*(六)高级图形命令*/

// WriteCmd(0x23); //(显示屏淡出和闪烁设置)

// WriteCmd(0x21); //(Fade Mode & 16 Frames) A[5:4] = 00b Disable Fade Out/Blinking Mode[RESET] | A[5:4] = 10b Enable Fade Out mode | A[5:4] = 11b Enable Blinking mode

// WriteCmd(0xD6); //(放大一倍显示,矢量放大)

// WriteCmd(0x01); //A[0] = 0b Disable Zoom in Mode[RESET] | A[0] = 1b Enable Zoom in Mode

/*****************/

/*(七)充电泵设置*/

WriteCmd(0x8d); //(电荷泵设置,VBAT = 3.3V~4.2V to Charge Pump VCC = 7.0V~7.5V,使oled点亮)

WriteCmd(0x14); //(使能电荷泵)

WriteCmd(0xe3); //(空操作)

/***************/

WriteCmd(0xaf); //(turn on oled panel)

}

以上便是所有指令的详解,读者需要对这一部分内容重点掌握,其中IIC协议可以百度到较为详细全面的资料,在这里就不复述了。

三、高阶

在对oled进行正确配置并点亮后,就需要对其原理进行深刻理解了,下面是4 pin oled的原理图,着重学要注意的是画圈部分(市面上绝大多数4 pin oled都是使用这张原理图来封装的):

2019-07-08_第1张图片

有需要的读者还可以查阅OLED数据表了解其电气特性,附上一张封装图:

2019-07-08_第2张图片

四、网传程序存在的不合理问题

在对上述进行理解后,我们来讨论一下在网上传播的oled驱动程序存在的问题。

我们来看一下网上流传的这段程序:

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标

{

    WriteCmd(0xb0+y);

    WriteCmd(((x&0xf0)>>4)|0x10);

    WriteCmd((x&0x0f)|0x01);

}

对比看一下英文手册:


2019-07-08_第3张图片

意思是在正常显示模式下需要以下三个步骤来定义起始点坐标:

1. 通过命令 B0h 到 B7h 来设置目标显示位置的页开始地址

2. 通过 00h~0Fh 来设置低开始列地址的指针

3. 通过命令 10h~1Fh 来设置高开始列地址

其中三条指令可以互换顺序,细心的读者可能发现问题了:

OLED_SetPos函数中这条指令:

WriteCmd((x&0x0f)|0x01);

设置低地址时会导致二进制数据最后一位始终置1,这将会导致在设置坐标点时只能设置奇数列!

正确的书写形式是:

WriteCmd(x&0x0f);

即函数应该为:

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标

{

    WriteCmd(0xb0+y);

    WriteCmd(((x&0xf0)>>4)|0x10);

    WriteCmd(x&0x0f);

}

我们通过下面这个例子来加深理解:

在main函数中加入如下代码:

for(i=0;i<128;i++)

{

OLED_DrawPoint(i,31,1);

}

其中OLED_DrawPoint函数为画点函数:

/******************************************************

Function: void OLED_DrawPoint(u8 x,u8 y,u8 t)

Description: 在屏幕上任一位置画点,填充或清空

Input: x:0~127

y:0~63

t:1 填充 0,清空

******************************************************/

void OLED_DrawPoint(u8 x,u8 y,u8 t)

{

u8 data;  //data1当前点的数据

if(x>127||y>63)return;// 超出范围了

OLED_SetPos(x,y/8);

data = 0x01<<(y%8);

  if(t==0) data=0x00;

WriteDat(data);

}

其中u8为数据类型宏定义:

typedef uint8_t  u8;

在修正前,oled会断点显示,即只显示奇数列:

2019-07-08_第4张图片

修正后显示正常:

2019-07-08_第5张图片

后记——凡尘

时间匆忙,未能用篇幅举代码实例帮大家理解和校对错误,更多的是结构和整体压缩的内容,如有错别字和内容不合理的地方欢迎大家批评指正,如有想深入探讨或是项目需求的朋友欢迎加入QQ群:QQ群:

        星尘Arduino社区:630581178

        星尘STM8/32社区:700155855

        笔者邮箱:[email protected]

你可能感兴趣的:(2019-07-08)