第 19 章 OLED 模块-I2C 协议
19.1 OLED 模块概述
19.1.1 OLED 简介
OLED(Organic Light-Emitting Diode,有机发光二极管)显示屏由许多微小的发光二
极管构成,每个发光二极管就对应着屏幕上的一个像素,通过控制二极管的亮灭就能在屏
幕上显示图像或文字。
按照驱动方式划分,OLED 显示屏分可分为两类,分别是 PMOLED(Passive Matrix,
被动矩阵)和 AMOLED(Active Matrix,主动矩阵)。
PMOLED 的驱动方式和前文的 LED 点阵类似,每次只能点亮一行或者一列,需要快
速的逐行或者逐列扫描来显示内容。
AMOLED 屏幕上的每个像素点都有一个单独的控制电路,可以独立进行控制。
本课程使用的是一块 PMOLED(Passive Matrix,被动矩阵)屏,其分辨率为 128x64。
19.1.2 驱动芯片
市面上的多数 OLED 显示屏都会带有驱动芯片,驱动芯片的核心作用是控制每个像素
点的亮灭以显示图像或文字,此外它还会提供数据接口(例如 I2C),用于接收屏幕上要显
示的数据。驱动芯片的存在使得我们可以通过简单的接口控制 OLED 显示屏,大大简化了
开发和控制流程。
本课程所使用的这块 OLED 屏的驱动芯片为 SSD1315,由于我们需要通过它来控制
OLED 显示的内容,所以需要重点学习它的用法。
19.1.2.1 基本工作原理
19.1.2.2 IIC 接口
虽然 SSD1315 的 MCU Interface 支持多种通信协议,但我们所选用的 OLED 显示模块
只暴露出了 IIC 接口。
由于 OLED 显示屏的作用是显示数据,它对于 MCU 来讲更多的是一个输出设备,因
此我们只需关注如何向 SSD1315 写入数据即可。下面是写数据的时序图:
19.1.2.3 GDDRAM
GDDRAM 的作用是存储显示数据,其容量是 128×64 bit,每个 bit 对应着屏幕上的一
个像素,该 bit 的值就能决定该像素的亮灭。
(1)内存组织结构
(2)内存寻址
在了解了内存组织结构之后,我们还需掌握内存的寻址方式,这样才能在我们指定的
位置写入指定的内容。
向 GDDRAM 写入数据时是以 byte 为单位的,按照上述的内存组织结构, 定位一个
byte,至少需要明确两点,分别是第几页(Page Address,页地址)和第几列(ColumnAddress,列地址)。因此 GDDRAM 内部设有两个指针, Page Address Pointer 和 ColumnAddress Pointer,分别指向当前要写入的页和列。为方便连续写入多个字节,每当成功写
入一个字节后,Page Address Pointer 或者 Column Address Pointer 会自动递增,指向下一
个要写入的位置。
根据指针递增逻辑的不同,GDFRAM 提供了三种不同的寻址方式,分别是页寻址,水
平寻址和垂直寻址,具体使用哪种模式,可以通过向 SSD1315 发送控制命令进行选择,具
体命令如下
下面逐一介绍三种寻址方式的工作原理。
(1)页寻址
这种寻址方式下,用户需要先向 SSD1315 发送控制命令设置页地址(例如 Page1)和
列地址(例如 COL3),此时 Page Address Pointer 和 Column Address Pointer 就会指向对
应的位置。之后便可开始连续发送数据,每成功写入一个字节,Column Address Pointer
都会自动+1,而 Page Address Pointer 始终不变,如果写到当前页末尾,Column Address
Pointer 会回到当前页的第 1 列。
设置页地址的命令如下
设置列地址的命令如下。
(2)水平寻址
这种寻址方式下,用户需要先向 SSD1315 发送控制命令,设置一个写入区域,具体来
讲就是分别指定页的起始地址和结束地址(例如 Page1~Page5)以及列的起始地址和结束
地址(例如 COL2~COL125)。此时 Page Address Pointer 和 Column Address Pointer 会指
向该区域的左上角。之后便可开始连续发送数据,每成功写入一个字节,Column Address
Pointer 会自动+1,当到达目标区域的右侧边界时,Page Address Pointer 便会自动+1。当写
到目标区域的右下角时,两个指针会再次回到左上角。如下图所示。
设置页地址范围的命令如下。
设置列地址范围的命令如下。
(3)垂直寻址
这种寻址方式下,用户需要先向 SSD1315 发送控制命令,设置一个写入区域,具体来
讲就是分别指定页的起始地址和结束地址(例如 Page1~Page5)以及列的起始地址和结束
地址(例如 COL2~COL125)。此时 Page Address Pointer 和 Column Address Pointer 会指
向该区域的左上角。之后便可开始连续发送数据,每成功写入一个字节,Page Address
Pointer 会自动+1,当到达目标区域的底部边界时,Column Address Pointer 便会自动+1。当
写到目标区域的右下角时,两个指针会再次回到左上角。如下图所示。
3)内存 bit 与屏幕像素映射关系
GDDRAM 中的每个 bit 都对应着屏幕上的一个像素,但具体哪个 bit 对应着哪个像素,
目前仍是不明确的,最理想的方式当然是每个 bit 和每个像素的位置完全对应,但默认情况
下并非如此。
bit 和像素之间的对应关系受两个环节的影响,第一个环节是 GDDRAM 和 SSD1315 输
出引脚(64 个 COM 和 128 个 SEG)的对应关系,第二个环节是 SSD1315 的输出引脚和
OLED 屏幕的连线方式。下面逐一分析。
(1)GDDRAM 和 SSD1315 输出引脚对应关系
(2)SSD1315 输出引脚和 OLED 屏幕对应关系
根据前文的描述,若要保证 GDDRAM 中的 bit 与 OLED 屏幕中的像素位置完全对应,
那么 GDDRAM 和 SSD1315 输出引脚的对应关系,需要进行重映射。
设置 Segment 重映射的命令如下。
设置 Common 重映射的命令如下。
19.1.3 相关资料
(1)实物图
19.2 需求描述
在 OLED 屏指定位置显示 ASCII 表中的指定字符.
19.3 硬件设计

19.4 软件设计
19.4.1 需求分析
想要在指定位置显示 ASCII 表中的指定字符,首先需要为每个字符制作字模。至于显
示位置的控制,只需通过命令指定自模数据写入 GDDRAM 的位置即可实现。
19.4.2 字模制作
19.4.3 显示位置
19.4.4 完整代码
(1)Int_Oled.h
#ifndef __INT_OLED_H__
#define __INT_OLED_H__
#include "Util.h"
/**
* @brief Oled 初始化
*
*/
void Int_Oled_Init();
/**
* @brief 在指定位置(x,y)显示字符串
*
* @param x 横坐标
* @param y 纵坐标
* @param str 待展示字符串
*/
void Int_Oled_ShowStr(u8 x, u8 y, u8 *str);
/**
* @brief 在指定位置(x,y)显示数字
*
* @param x 横坐标
* @param y 纵坐标
* @param num 待展示数字
*/
void Int_Oled_ShowNum(u8 x, u8 y, long int num);
/**
* @brief 清屏
*
*/
void Int_Oled_Clear();
#endif /* __INT_OLED_H__ */
(2)Int_Oled.c
#include "Int_Oled.h"
#include "Dri_IIC.h"
#define OLED_ADDR 0x78
#define DATA_MODE 0x40
#define CMD_MODE 0x00
code const u8 Int_Oled_Font[][16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, //! 1
0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //" 2
0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00,
0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3
0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00,
0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, //$ 4
0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00,
0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, //% 5
0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00,
0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, //& 6
0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //' 7
0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00,
0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, //( 8
0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00,
0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, //) 9
0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00,
0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, //* 10
0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, //+ 11
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, //, 12
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//- 13
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //- 13
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //. 14
0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04,
0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, /// 15
0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00,
0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16
0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17
0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00,
0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18
0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00,
0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19
0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00,
0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20
0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00,
0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21
0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00,
0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22
0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00,
0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23
0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00,
0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24
0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00,
0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25
0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, //: 26
0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, //; 27
0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00,
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, //< 28
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, //= 29
0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00,
0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, //> 30
0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, //? 31
0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00,
0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, //@ 32
0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00,
0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33
0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00,
0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34
0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00,
0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35
0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00,
0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36
0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00,
0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37
0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00,
0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38
0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00,
0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39
0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08,
0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40
0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00,
0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41
0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00,
0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42
0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00,
0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43
0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44
0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00,
0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45
0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08,
0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46
0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00,
0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47
0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00,
0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48
0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00,
0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49
0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00,
0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50
0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00,
0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51
0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00,
0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52
0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08,
0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53
0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08,
0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54
0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00,
0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55
0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08,
0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56
0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00,
0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57
0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00,
0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58
0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00,
0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, //[ 59
0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, //\ 60
0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00,
0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, //] 61
0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //^ 62
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //_ 63
0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //` 64
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65
0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67
0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00,
0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69
0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18,
0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71
0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72
0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73
0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00,
0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74
0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75
0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77
0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79
0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81
0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83
0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84
0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85
0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80,
0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86
0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80,
0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87
0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88
0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80,
0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90
0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, //{ 91
0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //| 92
0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00,
0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, //} 93
0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //~ 94
};
/**
* @brief 写显示数据
*
* @param bytes 字节数组
* @param length 数组长度
*/
void Int_Oled_WriteData(u8 bytes[], u8 length)
{
u8 i;
// 发送起始信号
Dri_IIC_Start();
// 发送设备地址
Dri_IIC_SendByte(OLED_ADDR);
Dri_IIC_ReceiveAck();
// 发送控制字节
Dri_IIC_SendByte(DATA_MODE);
Dri_IIC_ReceiveAck();
// 发送数据
for (i = 0; i < length; i++) {
Dri_IIC_SendByte(bytes[i]);
Dri_IIC_ReceiveAck();
}
Dri_IIC_Stop();
}
/**
* @brief 写控制命令
*
* @param bytes 字节数组
* @param length 数组长度
*/
void Int_Oled_WriteCmd(u8 bytes[], u8 length)
{
u8 i;
// 发送起始信号
Dri_IIC_Start();
// 发送设备地址
Dri_IIC_SendByte(OLED_ADDR);
Dri_IIC_ReceiveAck();
// 发送控制字节
Dri_IIC_SendByte(CMD_MODE);
Dri_IIC_ReceiveAck();
// 发送数据
for (i = 0; i < length; i++) {
Dri_IIC_SendByte(bytes[i]);
Dri_IIC_ReceiveAck();
}
Dri_IIC_Stop();
}
void Int_Oled_Init()
{
u8 bytes[6];
// 关闭屏幕
bytes[0] = 0xAE;
// Segment 重映射
bytes[1] = 0xA1;
// Common 重映射
bytes[2] = 0xC8;
// 启动内置电荷泵(用于升压)
bytes[3] = 0x8D;
bytes[4] = 0x14;
// 开启屏幕
bytes[5] = 0xAF;
Int_Oled_WriteCmd(bytes, 6);
}
/**
* @brief 设置页地址和列地址
*
* @param page 页地址
* @param column 列地址
*/
void Int_Oled_SetPointer(u8 page, u8 column)
{
u8 bytes[3];
bytes[0] = 0xB0 | (page & 0x07);
bytes[1] = 0x00 | (column & 0x0F);
bytes[2] = 0x10 | ((column >> 4) & 0x07);
Int_Oled_WriteCmd(bytes, 3);
}
void Int_Oled_Clear()
{
u8 i;
u8 j;
for (i = 0; i < 8; i++) {
Int_Oled_SetPointer(i, 0);
for (j = 0; j < 8; j++) {
Int_Oled_WriteData(Int_Oled_Font[0], 16);
}
}
}
void Int_Oled_ShowStr(u8 x, u8 y, u8 *str)
{
u8 i;
// 上半部分
// 设置页地址和列地址
Int_Oled_SetPointer(2 * y, 8 * x);
// 发送数据
for (i = 0; i < 16 - x && str[i]; i++) {
Int_Oled_WriteData(Int_Oled_Font[str[i] - 32], 8);
}
// 下半部分
// 设置页地址和列地址
Int_Oled_SetPointer(2 * y + 1, 8 * x);
// 发送数据
for (i = 0; i < 16 - x && str[i]; i++) {
Int_Oled_WriteData(Int_Oled_Font[str[i] - 32] + 8, 8);
}
}
void Int_Oled_ShowNum(u8 x, u8 y, long int num)
{
u8 str[17];
u8 i = 0;
u8 j = 0;
u8 tmp;
if (num == 0) {
str[0] = '0';
} else {
if (num < 0) {
str[i++] = '-';
num = -num;
j = 1;
}
// 转换字符串
while (num) {
str[i++] = num % 10 + '0';
num = num / 10;
}
// 字符串终止
str[i] = 0;
i--;
// 反转整个数字
while (i > j) {
tmp = str[i];
str[i] = str[j];
str[j] = tmp;
i--;
j++;
}
}
Int_Oled_ShowStr(x, y, str);
}
(3)main.c
#include "Int_Oled.h"
void main()
{
Int_Oled_Init();
Int_Oled_Clear();
Int_Oled_ShowStr(0, 0, "Hello world!");
Int_Oled_ShowNum(0, 1, 123456);
while (1) {
}
}