OLED屏幕

OLED简介

OLED(Organic Light-Emitting Diode,有机发光二极管)显示屏由许多微小的发光二极管构成,每个发光二极管就对应着屏幕上的一个像素,通过控制二极管的亮灭就能在屏幕上显示图像或文字。

按照驱动方式划分,OLED显示屏分可分为两类,分别是PMOLED(Passive Matrix,被动矩阵)和AMOLED(Active Matrix,主动矩阵)。

  • PMOLED

PMOLED的驱动方式和前文的LED点阵类似,每次只能点亮一行或者一列,需要快速的逐行或者逐列扫描来显示内容。

  • AMOLED

AMOLED屏幕上的每个像素点都有一个单独的控制电路,可以独立进行控制。

本次介绍的是一块PMOLED(Passive Matrix,被动矩阵)屏,其分辨率为128x64。

驱动芯片

市面上的多数OLED显示屏都会带有驱动芯片,驱动芯片的核心作用是控制每个像素点的亮灭以显示图像或文字,此外它还会提供数据接口(例如I2C),用于接收屏幕上要显示的数据。驱动芯片的存在使得我们可以通过简单的接口控制OLED显示屏,大大简化了开发和控制流程。

本次介绍的这块OLED屏的驱动芯片为SSD1315

基本工作原理

SSD1315原理图

  • MCU InterFace
    通信接口,MCU通过该接口向SSD1315发送显示数据或者控制命令(控制屏幕显示效果,例如对比度、亮度等)。该接口支持多种通信协议,其中就包括IC。
  • Command Decoder
    命令解码器,负责解析和执行主机发送的控制命令
  • Graphic Display Data RAM
    图形显示数据RAM,用于存储显示数据,其容量为128x64(bit)。每个bit对应屏幕上的1个像素。
  • Common/Segment Driver
    用于产生实际驱动OLED显示屏的信号。其中Common Driver用于产生行扫描信号共有64个输出引脚。Segment Driver用于产生每行要显示的内容信号,共有128个输出引脚。

IIC接口、写时序

SSD1315的MCU Interface支持多种通信协议,这里OLED显示模块只暴露出了IIC接口

OLED显示屏的作用是显示数据,是一个输出设备,我们只需关注如何向SSD1315写入数据即可。下面是写数据的时序图
写时序图

  • SA0
    SSD1315的地址,高6位是固定的011110,最后1位SA0可由用户自定义。参考0LED模块手册,可得最后1位的默认值为0
  • R/W#
    R/W#(读写标识)应为0,故地址+读写标识应为01111000(0x78)
  • Data byte
    数据字节,其内容可能是Data(显示数据),也可能是Command(控制命令)。
  • Control byte
    控制字节,在Data byte之前发送,用于声明后续Data byte内容的类型和格式,该字节只有高2位有效,其余6位均为0
  • D/C#(Data/Command)
    用于声明后续的Data byte是Data还是Command,1表示Data,0表示Command。
  • Co(Continuation Bit)
    用于声明后续内容是否连续,0表示连续,此时后边可以连续发送多个Data bvte:1表示不连续,此时后边只能发送一个Data byte。需要注意的是,当Co设置0时,本次通信中后续所有的字节都会被视作Databyte

内存组织结构

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

​​​​​​​内存寻址

定位一个byte,至少需要明确两点,分别是第几页(Page Address,页地址)和第几列(Column Address,列地址)。

GDDRAM内部设有两个指针

  • Page Address Pointer,指向当前要写入的
  • Column Address Pointer,指向当前要写入的

为方便连续写入多个字节,每当成功写入一个字节后,Page Address Pointer或者Column Address Pointer会自动递增,指向下一个要写入的位置。

设置寻址方式的命令
在这里插入图片描述

页寻址

这种寻址方式下,用户需要先向SSD1315发送控制命令设置页地址(例如Page1)和列地址(例如COL3),此时Page Address Pointer和Column Address Pointer就会指向对应的位置。之后便可开始连续发送数据,每成功写入一个字节,Column Address Pointer都会自动+1,而Page Address Pointer始终不变,如果写到当前页末尾,Column Address Pointer会回到当前页的第1列。

设置页地址的命令如下。
在这里插入图片描述
设置列地址的命令如下。
在这里插入图片描述

水平寻址

这种寻址方式下,用户需要先向SSD1315发送控制命令,设置一个写入区域,具体来讲就是分别指定页的起始地址和结束地址(例如Page1Page5)以及列的起始地址和结束地址(例如COL2COL125)。此时Page Address Pointer和Column Address Pointer会指向该区域的左上角。之后便可开始连续发送数据,每成功写入一个字节,Column Address Pointer会自动+1,当到达目标区域的右侧边界时,Page Address Pointer便会自动+1。当写到目标区域的右下角时,两个指针会再次回到左上角。

设置页地址范围的命令如下。
在这里插入图片描述

设置列地址范围的命令如下。
在这里插入图片描述

垂直寻址

这种寻址方式下,用户需要先向SSD1315发送控制命令,设置一个写入区域,具体来讲就是分别指定页的起始地址和结束地址(例如Page1Page5)以及列的起始地址和结束地址(例如COL2COL125)。此时Page Address Pointer和Column Address Pointer会指向该区域的左上角。之后便可开始连续发送数据,每成功写入一个字节,Page Address Pointer会自动+1,当到达目标区域的底部边界时,Column Address Pointer便会自动+1。当写到目标区域的右下角时,两个指针会再次回到左上角。

​​​​​​​内存bit与屏幕像素映射关系

GDDRAM中的每个bit都对应着屏幕上的一个像素,但具体哪个bit对应着哪个像素,目前仍是不明确的,最理想的方式当然是每个bit和每个像素的位置完全对应,但默认情况下并非如此。

bit和像素之间的对应关系受两个环节的影响,第一个环节是GDDRAM和SSD1315输出引脚(64个COM和128个SEG)的对应关系,第二个环节是SSD1315的输出引脚和OLED屏幕的连线方式。下面逐一分析。

GDDRAM和SSD1315输出引脚对应关系
在这里插入图片描述

SSD1315输出引脚和OLED屏幕对应关系
在这里插入图片描述

根据前文的描述,若要保证GDDRAM中的bit与OLED屏幕中的像素位置完全对应,那么GDDRAM和SSD1315输出引脚的对应关系,需要进行重映射。

设置Segment重映射的命令如下。
在这里插入图片描述
设置Common重映射的命令如下。
在这里插入图片描述

代码实现

Int_Oled.h

#ifndef __INT_OLED_H__
#define __INT_OLED_H__
#include "Com_Util.h"
/**
 * @brief Oled初始化
 *
 */
void Int_Oled_Init();

void Int_Oled_WriteData(u8 bytes[], u8 length);
void Int_Oled_WriteCmd(u8 bytes[], u8 length);

/**
 * @brief 清屏
 *
 */
void Int_Oled_Clear();

/**
 * @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);

#endif /* __INT_OLED_H__ */

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,
        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);
}

void Int_Oled_Clear() {
    u8 cmd_bytes[2]={0x20,0x00};
    u8 data_bytes[8] = {0};
    u8 i;
    Int_Oled_WriteCmd(cmd_bytes, 2);
    for ( i = 0; i < 128; i++)
    {
        Int_Oled_WriteData(data_bytes, 8);
    }
}

/**
 * @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_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);
}

mian.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) {
    }
}

补充

清屏优化

void Dri_IIC_SendByte(u8 byte)
{
    u8 i;
    for (i = 0; i < 8; i++) {
        SDA = (byte & (0x80 >> i)) == 0 ? 0 : 1;
        SCL = 1;
        SCL = 0;
    }
}

这是I2C中一段代码,现在对其进行优化

void Dri_IIC_SendByte(u8 byte)
{
    u8 i;
    for (i = 0; i < 8; i++) {
        //SDA = (byte & (0x80 >> i)) == 0 ? 0 : 1;
        if ((byte & 0x80) == 0x00) {
            SDA = 0;
        } else {
            SDA = 1;
        }
        byte <<= 1;
        SCL = 1;
        SCL = 0;
    }
}
void Int_Oled_Clear() {
    u8 cmd_bytes[2]={0x20,0x00};
    u8 data_bytes[8] = {0};
    u8 i;
    Int_Oled_WriteCmd(cmd_bytes, 2);
    for ( i = 0; i < 128; i++)
    {
        Int_Oled_WriteData(data_bytes, 8);
    }
}

优化清屏逻辑
原来的逻辑:通过128次循环,每次循环进行1次通信,1次通信写8个字节
现在的逻辑:只进行1次通信,循环写入128*8字节

void Int_Oled_Clear() {
    u8 cmd_bytes[2]={0x20,0x00};
    u8 data_bytes[8] = {0};
    u16 i;
    Int_Oled_WriteCmd(cmd_bytes, 2);
    // for ( i = 0; i < 128; i++)
    // {
    //     Int_Oled_WriteData(data_bytes, 8);
    // }

    // 发送起始信号
    Dri_IIC_Start();
    // 发送设备地址
    Dri_IIC_SendByte(OLED_ADDR);
    Dri_IIC_ReceiveAck();
    // 发送控制字节
    Dri_IIC_SendByte(DATA_MODE);
    Dri_IIC_ReceiveAck();
    // 发送数据
    for (i = 0; i < 128 * 8; i++) {
        Dri_IIC_SendByte(0x00);
        Dri_IIC_ReceiveAck();
    }
    Dri_IIC_Stop();

}

数字展示

使用库函数,将数字转成字符串

#include <STDIO.H>

void Int_Oled_ShowNum(u8 x, u8 y, long int num)
{
    char str[12];
    sprintf(str, "%ld", num);
    Int_Oled_ShowStr(x, y, str);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值