OLED显示屏I2C接口

article/2025/11/7 2:27:32

简介

本文将介绍两种不同尺寸的OLED显示屏:0.96寸和0.91寸。他们都是4引脚I2C接口的,如下图所示:

注:经过项目测试发现,本文介绍的驱动方式和代码也完全适用于 1.54寸SSD1309主控的1.54寸OLED和1.29寸CH1115主控的OLED屏。如果需要更大的屏幕可以选用这两款,但是他们的分辨率仍然是126*64,只是显示的字体和图案可以更大。

0.96英寸OLED基本参数

  • 工作电压:3.3~5V(内置3.3V LDO,I2C通信接口电平是3.3V的)
  • 像素点阵规模:128x64(128列,64行,共8192颗LED)
  • 驱动IC:SSD1306

0.91英寸OLED基本参数

  • 工作电压:3.3~5V(内置3.3V LDO,I2C通信接口电平是3.3V的)
  • 像素点阵规模:128x32(128列,32行,共4096颗LED)
  • 驱动IC:SSD1306

可以发现,0.91英寸的像素点规模只有0.96英寸的一半,除此之外其余参数基本相同。接下来将主要介绍0.96英寸显示屏的使用方法。

接口定义

引脚名称引脚说明
VCC模块电源正,3.3~5V
GND模块电源地
SCL模块I2C总线时钟信号
SDA模块I2C总线数据信号

I2C通信接口

硬件设计

  • 模块内置了一个3.3V的LDO,型号为662K,所以支持3.3~5V供电。
  • 模块已经板载了SCL和SDA线的上拉电阻,且上拉到了3.3V。如果单片机是5V的,只要IO配置为开漏输出,则也是可以直接接入到模块的,因为开漏无法输出高电平。最主要的问题是3.3V能够被5V单片机识别为高电平,这个要看单片机数据手册。一般是没有问题的。
  • 其他I2C从机挂接到同一个I2C总线时,无需再外接I2C总线的上拉电阻了。
  • 模块的I2C从机地址为:0111 10 [SA0] [RW],SA0是硬件地址选择位,当SA0接高电平时,地址中的SA0就是1,当SA0接低电平时,地址中的SA0就是0。模块出厂的时候,一般SA0是接的低电平,用户可以自己动手修改模块后面的电阻来改变SA0为高电平。这也意味着,同一个I2C总线最多支持挂接2个OLED模块。

软件设计

在SSD1306的I2C协议中,用到了控制字节,控制位的格式为:[Co][D/C#][000000]。在发送指令字节或者数据字节前,需要先发送一个控制字节,通过控制字节中的D/C#位,来告诉SSD1306,接下来发送的一个字节是指令还是数据。这里我们先不考虑控制字节中Co位的作用,这样我们就可以编写出发送单个字节的指令和单个字节的数据的函数。

发送单个字节指令:起始信号【从机地址,ACK】【控制字节,ACK】【单字节的指令,ACK】结束信号

static void OLED_write_cmd(uint8_t cmd)
{IIC_start();IIC_write_byte(0x78);   //从机地址,SA0=0,RW=0 IIC_wait_ack();IIC_write_byte(0x00);   //控制字节,Co=0,D/C#=0IIC_wait_ack();IIC_write_byte(cmd);   //命令码IIC_wait_ack();IIC_stop();
}

发送单个字节显存数据:起始信号【从机地址,ACK】【控制字节,ACK】【单字节的数据,ACK】结束信号 

static void OLED_write_data(uint8_t dat)
{IIC_start();IIC_write_byte(0x78);   // 从机地址,SA0=0,RW=0IIC_wait_ack();IIC_write_byte(0x40);   //控制字节,Co=0,D/C#=1IIC_wait_ack();IIC_write_byte(dat);   //数据值IIC_wait_ack();IIC_stop();
}

上面的代码我们可以发现,每次发送一个指令或者数据字节,都要开启一次完整的I2C通信时序流程,要有起始信号,从机地址,控制字节和结束信号。指令性数据在正常运行时,使用的比较少,用上面的函数发送没什么大问题,但是发送到显存中的数据字节,则往往需要一次性发送多个,特别是在快速刷屏的时候,如果也使用上面的函数发送,会有大量的通信时间浪费在发送起始新,从机地址,控制字节和结束信号上了,效率低下。那么有没有办法一次性无间隔的连续发送多个显存数据呢?可以,这个时候控制字节中的Co位就派上用场了。

控制字节中的Co位作用:当控制字节中Co=0,且D/C#=1时,则接下来可以连续发送任意多个显存数据字节,直到产生停止信号。下面是代码实现。

一次性发送N个显存数据:起始信号【从机地址,ACK】【控制字节,ACK】【N个字节的数据,N个ACK】结束信号 

static void OLED_write_data_array(const uint8_t* dats,uint32_t len)
{IIC_start();IIC_write_byte(0x78);   //从机地址,SA0=0,RW=0 IIC_wait_ack();IIC_write_byte(0x40);   //控制字节,Co=0,D/C#=1IIC_wait_ack();for(uint32_t i=0;i<len;i++){IIC_write_byte(dats[i]);   //数据值IIC_wait_ack();}IIC_stop();
}

通过在0.91英寸OLED屏幕上测试发现,使用150KHz I2C总线,刷完一帧屏幕,使用单个发送字节显存数据函数需要大约100ms,而使用一次性发送多个显存数据的函数则只需要大约33ms,速度提升非常明显。

驱动芯片的指令集

这里将介绍如何看懂SSD1306数据手册中的指令集。如下图所示,这是截取指令集中的3条指令。

指令A用于设置页地址,它由连续的3个字节组成,第一个字节0x22代表指令码,用于标识指令功能本身,也就是当发送0x22指令时,驱动芯片SSD1306就知道现在要设置页地址了,而后面的两个字节A[2:0]和B[2:0]则是两个指令参数,指令参数是指令运行时所需的参数数据。为了方便理解,我们可以将指令码和指令参数与函数和函数的参数类比起来。表示为*的位意思是他们的值可以任意设置,一般置0即可。

指令B比较特殊,他将指令码和指令参数融合为了一个字节,高位部分固定为[10110],低位部分[X2,X1,X0] 则用于编码指令参数。

指令C也比较特殊,它只有一个固定的指令码,没有指令参数。类似于C语言中的无参数函数。

表格的第一列D/C#,用于告诉我们,发送对应的字节时,需要将D/C#位设置为0还是1。D/C#=0 代表发送的是指令性相关的数据,这些字节数据被SSD1306接收并解析,主要用于改变屏幕的工作参数。D/C#=1代表发送的是显示数据字节,这些字节将被写入到SSD1306的显存GDDRAM中作为显示数据使用。由于上图中的数据都是指令数据,所以他们在发送时,都要设置D/C#为0。

显存与页寻址模式

驱动芯片SSD1306带有一个128x64 bit大小的GDDRAM,用于存放显示数据,也就是所谓的显存。显存中的数据与显示内容是息息相关的,具体来说,显存中的每一个bit对应一颗像素点,如果显存中的某个bit为1,则它对应的那颗像素LED被点亮,否则是熄灭的。

寻址模式规定了GDDRAM存储单元的组织形式。GDDRAM支持3种内存寻址模式,可以通过指令选择为:①页寻址模式 ②水平寻址模式 ③垂直寻址模式。这里讲解一下最常用的页寻址模式。

如上图所示,当使用页寻址模式时,GDDRAM被划分为8个页:PAGE0~PAGE7,每个页由128个字节组成。那么通过单片机向GDDRAM中写入数据时,就需要指定2个地址:页地址和列地址,这样才能定位到GDDRAM中的一个的字节存储单元。例如,如果设置页指针为0,列指针为2,并写入显示数据0xF0,则效果如上图中蓝色所示。

在页寻址模式下,每次写入一个字节的显示数据,列地址自动增1。当列地址超过127时,会自动回归到0。但是页指针不会改变,除非使用指令重新设置指向其他的页。

如何设置页地址和列地址呢?

通过查看SSD1306的指令表,可以发现有对应的指令来设置页地址和列地址。如下图所示。

其中列地址需要拆成2部分写入,用第一条指令发送列地址值的低4bit部分,用第二条指令发送列地址值的高4bit部分。

 如何配置寻址模式为页寻址模式?

先发送指令码0x20,来告诉屏幕要现在要设置内存寻址模式,然后发送指令参数:0x00水平地址模式,0x01垂直模式,0x02页地址模式。芯片复位后默认就是页寻址模式

图片的显示

我们需要使用Pctolcd2002这款取模软件。首先我们需要准备一张图片,如果你需要在OLED屏上显示一个W像素宽,H像素高的图像,那么需要准备一张尺寸同等比例的图片。

例如我们要在0.96英寸OLED上显示一张128宽,64高的图片,则我准备了一张378x189的意法半导体logo图片。128/64 = 2,378/189 =2。然后用Windows自带的画图软件打开它,调整它的大小为想要的像素规模,然后保存为BMP格式。

接着打开Pctolcd2002软件,菜单栏【模式】修改为图形模式,【文件】【打开】,选中上一步生成的BMP图像。然后点击工具栏的【齿轮】按钮,在弹出的界面中按照下图进行配置,配置完成后点击【确定】返回主界面。

在主界面中,生成的点阵预览图可能细节上有瑕疵,这个时候可以使用鼠标进行修补,左键增加一个像素,右键取消一个像素。最后点击主界面右下角的【生成子模】按钮,即可输出子模字节数据。将这个子模数据以一维字节数组的形式定义在C程序中,就可以使用了。

由于我们的【取模方式】用的是【列行式】,则取模软件会从图片左上角第一列开始,每竖向8个像素点得到一个字节,一直到最后一列时取到128字节。下一次则换到下一个8像素宽的行从开始取。所以可以看出,【取模方式】用的是【列行式】对于页寻址模式是很方便的。

//128像素宽,64像素高,st意法半导体 logo
const uint8_t image_data[64*16]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x3E,0x0E,0x06,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xC0,0xF0,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,
0x3F,0x1F,0x1F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0xE0,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0x60,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFC,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x7F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x0F,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x07,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x07,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x07,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x80,0xE0,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x0C,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xC0,0xF0,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x40,0x60,0x60,0x70,0x78,0x7C,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x3F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x78,
0x7E,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x3F,0x3F,0x3F,0x1F,0x1F,0x0F,0x07,
0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};void OLED_showImage(void)
{uint32_t page;uint32_t i=0;for(page=0;page<8;page++){OLED_write_cmd(0xb0+page);   //设置页地址OLED_write_cmd(0x00);OLED_write_cmd(0x10);  //设置列地址为0起始地址OLED_write_data_array(image_data+i,128);  //发送128个字节的显存数据i+=128;}
}

汉字的显示

打开Pctolcd2002软件,菜单栏【模式】修改为字符模式,【选择字体】,设置【字宽和字高】。在下方输入需要取模的汉字,然后点击【生成字模】即可。设置里面的参数和上面图片取模的一样。

实际使用过程中,为了达到比较好的显示效果,汉字最小一般使用16x16宽和高。Pctolcd2002软件把每一个汉字当做一个基本的图像来进行取模的,且按照输入的文字依次进行取模。所以得到的子模数据是:第一个汉字的上半部分字模,第一个汉字的下半部分字模;第二个汉字的上半部分字模,第二个汉字的下半部分字模。。。这样的的方式得到的字模数据。如下:

0x00,0xFC,0x04,0x04,0xFC,0x20,0x50,0x48,0x44,0x43,0x44,0x48,0x50,0x20,0x20,0x00, //哈的上半部分
0x00,0x0F,0x04,0x04,0x0F,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00, //哈的下半部分
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, //士的上半部分
0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, //士的下半部分
0x40,0x40,0x44,0x44,0x64,0x54,0x4C,0x47,0x4C,0x54,0x64,0xC4,0x44,0x40,0x40,0x00, //奇的上半部分
0x00,0x00,0x00,0x1E,0x12,0x12,0x12,0x12,0x1E,0x40,0x80,0x7F,0x00,0x00,0x00,0x00, //奇的下半部分

所以,在显示汉字的时候,要先按顺序显示每个字的上半部分,然后换到下一个page,再按顺序显示每个字的下半部分。

static const uint8_t hanzi[] = {
0x00,0xFC,0x04,0x04,0xFC,0x20,0x50,0x48,0x44,0x43,0x44,0x48,0x50,0x20,0x20,0x00,
0x00,0x0F,0x04,0x04,0x0F,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,/*"哈",0*/
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,/*"士",1*/
0x40,0x40,0x44,0x44,0x64,0x54,0x4C,0x47,0x4C,0x54,0x64,0xC4,0x44,0x40,0x40,0x00,
0x00,0x00,0x00,0x1E,0x12,0x12,0x12,0x12,0x1E,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,/*"奇",2*/
};//参数han为汉字字模数据
//cnt为汉字个数
void OLED_print_chinese(const uint8_t *han,uint8_t cnt,uint8_t page,uint8_t col)
{uint8_t i;OLED_set_pos(page,col);for(i=0;i<cnt;i++){	OLED_write_data_array(han+i*16*2,16);  //发送汉字字模数据的上半部分}OLED_set_pos(page+1,col);  //切换到下一个pagefor(i=0;i<cnt;i++){	OLED_write_data_array(han+i*16*2+16,16);  //发送汉字字模数据的下半部分}
}

初始化序列

0.96寸IIC接口OLED初始化序列

//0.96寸IIC接口OLED初始化
void OLED_init(void)
{OLED_I2C_init();     //初始化驱动I2C总线的引脚//延时200ms等待OLED稳定OLED_write_cmd(0xAE );//--display offOLED_write_cmd(0x00 );//---set low column addressOLED_write_cmd(0x10 );//---set high column addressOLED_write_cmd(0x40 );//--set start line address  OLED_write_cmd(0xB0 );//--set page addressOLED_write_cmd(0x81 ); // contract controlOLED_write_cmd(0xFF );//--128   OLED_write_cmd(0xA1 );//set segment remap OLED_write_cmd(0xA6 );//--normal / reverseOLED_write_cmd(0xA8 );//--set multiplex ratio(1 to 64)OLED_write_cmd(0x3F );//--1/32 dutyOLED_write_cmd(0xC8 );//Com scan directionOLED_write_cmd(0xD3 );//-set display offsetOLED_write_cmd(0x00 );//OLED_write_cmd(0xD5 );//set osc divisionOLED_write_cmd(0x80 );//OLED_write_cmd(0xD8 );//set area color mode offOLED_write_cmd(0x05 );//OLED_write_cmd(0xD9 );//Set Pre-Charge PeriodOLED_write_cmd(0xF1 );//OLED_write_cmd(0xDA );//set com pin configuartionOLED_write_cmd(0x12 );//OLED_write_cmd(0xDB );//set VcomhOLED_write_cmd(0x30 );//OLED_write_cmd(0x8D );//set charge pump enableOLED_write_cmd(0x14 );//OLED_write_cmd(0xAF );//--turn on oled panelOLED_clear();         //清除屏幕显示
}

0.91寸IIC接口OLED初始化序列

//0.91寸IIC接口OLED初始化
void OLED_init(void)
{OLED_I2C_init();     //初始化驱动I2C总线的引脚//延时200ms等待OLED稳定OLED_write_cmd(0xAE);OLED_write_cmd(0x40);//---set low column addressOLED_write_cmd(0xB0);//---set high column addressOLED_write_cmd(0xC8);//-not offsetOLED_write_cmd(0x81);OLED_write_cmd(0xff);OLED_write_cmd(0xa1);OLED_write_cmd(0xa6);OLED_write_cmd(0xa8);OLED_write_cmd(0x1f);OLED_write_cmd(0xd3);OLED_write_cmd(0x00);OLED_write_cmd(0xd5);OLED_write_cmd(0xf0);OLED_write_cmd(0xd9);OLED_write_cmd(0x22);OLED_write_cmd(0xda);OLED_write_cmd(0x02);OLED_write_cmd(0xdb);OLED_write_cmd(0x49);OLED_write_cmd(0x8d);OLED_write_cmd(0x14);OLED_write_cmd(0xaf); //打开显示OLED_clear();     //清除显示
}


http://chatgpt.dhexx.cn/article/V8mX7wwA.shtml

相关文章

关于I2C接口的介绍

I 2C:Inter-Integrated Circuit 内部集成电路,应该翻译为集成电路总线,IC的正确读法为“I方C”。 这种通信协议由Philip最早提出,一种由数据线SDA和时钟线SCL两根信号线组成的串行通信总线,具体规范可以在NXP网站找到v2.1。不像UART没有CLOCK线,不能实现同步,I2C和SPI都…

【原创】【I2C】I2C介绍

一、这是个什么玩意 I2C首先它也是一个通信接口&#xff0c;同理通信接口就是用于模块之间的通信的&#xff0c;同SPI接口学习思路一样&#xff0c;首先明白它是一个接口&#xff0c;然后再扣它是一个怎么样的接口。 I2C(Inter&#xff0d;Integrated Circuit)总线是由Philips公…

I2C接口

一、I2C总线协议内容 1. I2C总线引脚定义 SDA (I2C数据引脚) CLK (I2C数据引脚) 2. I2C总线物理连接 I2C总线物理连接如下图所示&#xff0c;SDA和CLK连接线上连有两个上拉电阻&#xff0c;当总线空闲时&#xff0c;两根线均为高电平。连到总线上的任一器件输出的低电平&am…

“如何成为阿里云P8架构师?“ ”当然是考取阿里云新版ACE认证啊”

**简介&#xff1a;**阿里云新版云计算架构师ACE认证全面重构上线&#xff01;为建立云计算生态领域含金量第一的专家级人才标准和认证体系&#xff0c;影响泛云生态高层次技术人才&#xff0c;阿里云历时一年&#xff0c;组织近百位专家&#xff0c;对云计算架构师ACE认证进行…

阿里云认证(ACA/ACP/ACE)的分类以及官网价格

阿里云认证分类&#xff1a; 阿里云认证分为三个等级&#xff0c;分别为初级(ACA)、中级(ACP)、高级&#xff08;ACE&#xff09; 下面还有很多的子分类 在子分类中&#xff0c;云计算是认证中最受欢迎的&#xff0c;无论是ACA云计算&#xff0c;还是ACP云计算&#xff0c;都…

阿里云ACA、ACP、ACE认证考试区别,报名入口及模拟试题分享

阿里云认证考试包含ACA、ACP、ACE三种认证类型&#xff0c;是阿里云针对不同产品类别、用户成长阶段、生态岗位&#xff0c;精心打造不同的认证考试。获得阿里云认证考试证书能够基于阿里云产品解决实际问题。获得更多阿里云生态下的就业机会。 助理工程师&#xff08;ACA&…

成为阿里云架构师的进阶之路——阿里云首批ACE认证通过者逸疏专访

自2018年3月阿里云发布云计算架构师ACE(Alibaba Cloud Certified Expert,阿里云认证高级工程师)级别认证后,上线不到3个月,吸引了近百位业界优秀从业者参与考试。获得阿里云ACE认证,对于业界资深架构师来说,是自身实力的最好证明。 阿里云大学致力于培养云生态链路上的…

阿里云P8架构师|历时4个月1次通关ACE认证

李东是我在阿里云厂商这边了解到第一个自学通过ACE认证P8架构师&#xff0c;现将他学习考证记录分享给大家 写在前面&#xff1a; 我是来自阿里云数字政府行业线的解决方案架构师李东。 2022年3月28日阿里云发布了新版ACE&#xff08;Alibaba Cloud Certified Expert - Cloud…

阿里云新版云计算架构师ACE认证专家解读会重磅来袭

简介&#xff1a;专家命题人非常解读 9600元全额代金券限量发放&#xff01;活动钉群&#xff1a;31889256。 3月28日&#xff0c;阿里云新版云计算架构师ACE认证正式升级发布&#xff0c;面向云架构师、解决方案架构师、资深运维/交付等人群&#xff0c;提供技术能力认证。自升…

通过新版阿里ACE认证,实验操作题你来解一下

大家都知道了哈&#xff0c;阿里云新版ACE认证&#xff0c;现在是云认证界的塔尖位置&#xff0c;因为要成功拿到新版ACE认证&#xff0c;需要破关斩将&#xff0c;三个守门的将&#xff0c;分别是笔试&#xff0c;实验操作&#xff0c;以及面试 1&#xff0c;笔试 相对实验操…

为什么我不建议在阿里云官网报考ACP/ACE认证?

考acp的时候刚开始以为直接在阿里云官网寻找课程备考报名就可以了,官方提供的课程应该没有问题,但是实际学习的时候发现,官方提供的内容虽然涵盖了大部分知识点,但是由于缺少对应的学习服务,学习效果上总是差强人意。 除了学习效果意外,再就是两个更重要的原因,贵且麻烦…

阿里云ACA、ACP、ACE认证考试常见问题

阿里云专业技术认证包含&#xff1a; 阿里云Apsara Clouder技能认证 阿里云助理工程师认证ACA级别&#xff08;Alibaba Cloud Certified Associate&#xff09; 阿里云专业工程师认证ACP级别&#xff08;Alibaba Cloud Certified Professional&#xff09; 阿里云基于岗位的…

阿里云的ACP认证与ACE认证含金量高吗?

该文章详细的介绍了阿里云认证。 云计算ACP认证介绍&#xff1a; 阿里云云计算专业认证(ACP 级-Alibaba Cloud Certification Professional)是面向使用阿里云云计算产品的架构、开发、运维类人员的专 业技术认证&#xff0c;主要涉及阿里云的计算、存储、网络、安全类的核心…

阿里云认证未来网络学院ACE公开课——30分钟掌握ACE考试通关攻略

简介&#xff1a;新版ACE通关攻略&#xff0c;这4点经验&#xff0c;帮你斩获高分&#xff01;入群即赠价值3000元ACP全套线上课资料包&#xff01;公开课钉群&#xff1a;44832770。 新版ACE通关攻略&#xff0c;这4点经验&#xff0c;帮你斩获高分 阿里云云计算架构师 ACE 认…

技能证里的天花板-阿里云云计算架构师ACE认证将全面升级!

近年来&#xff0c;随着国内数字化实践的不断深化&#xff0c;中国企业上云意识和积极性明显提高&#xff0c;上云比例和应用场景深度有所提升。根据亿欧智库2022年2月发布的《2021中国公有云服务商能力指数研究报告》指出&#xff1a;随着数字经济和新技术的发展&#xff0c;预…

阿里云ACE认证介绍

01-阿里云ACE认证概述 阿里云云计算架构师ACE认证是针对云架构师&#xff0c;解决方案架构师&#xff0c;云运维专家等技术人员的阿里云高级别技术认证。 通过该技术认证可以有效证明该认证人员具备丰富的需求分析能力&#xff0c;云架构设计能力&#xff0c;云架构部署实施能…

运营商大数据中建模到底是什么意义?

建模字面意思不难理解&#xff0c;就是通过不同企业的特殊需求来建立不同的数据采集模型&#xff01;前面我们说过运营商大数据具备T1的时效性和超前的准确性&#xff0c;之所以它具备这两点特性完全是因为运营商大数据的建模方式&#xff01; 第一种建模方式&#xff1a;网址和…

三网运营商大数据如何实现精准获客,稳定客户资源获取平台

在过去&#xff0c;对众多企业来说&#xff0c;销售获客的方法大多是来自于一些地推或者电话营销&#xff0c;然而在如今的时代&#xff0c;人们在线上获客已经成为常态&#xff0c;让获客的方式也有了更多的可能性&#xff0c;企业想在激烈的竞争中突出重围&#xff0c;就需要…

销售业绩迅速提升10倍的秘诀——运营商大数据精准

销售行业备受关注的焦点无非就是业绩&#xff0c;在互联网时代&#xff0c;你有没有感觉到企业的传统销售模式获客越来越艰难。有时候时间浪费了不说&#xff0c;还毫无效果&#xff0c;那今天我们来讲一下如何短时间之内让你的销售业绩提升十倍呢&#xff0c;必须跟得上大数据…

运营商大数据 | 打造新型获客模式 破除流量困局

大师彼得.德鲁克曾说&#xff0c;“企业存在的唯一目的就是创造顾客。” 互联网时代&#xff0c;维系企业存在的一大动力&#xff0c;就是流量&#xff0c;创造流量&#xff0c;无疑等于是创造顾客。 时下企业竞争的关键&#xff0c;也就是流量的竞争&#xff0c;在生产、销售…