---
video: //player.bilibili.com/player.html?isOutside=true&aid=113249160860813&bvid=BV1eE4weXEQK&cid=26140020524&p=1&high_quality=1&autoplay=0
---

# 蓝色 128*64 显示屏（上）

128x64 OLED显示屏是一种常见的小型图形显示设备，具有128像素的宽度和64像素的高度。这种显示屏通常使用OLED（有机发光二极管）技术，提供较低功耗、快速响应时间和较高的对比度。

## 效果图

![](https://cdn.zhiyanbang.com/md17/12123.gif)

## 通讯原理  

老许手上拿的OLED显示屏是支持I2C的通讯方式。I2C在之前讲 TM1637 时已经给大家讲述过了。其原理图如下图所示：

![](https://cdn.zhiyanbang.com/md11/WeChat7383970672dd131cdd4d4c17733192db.jpg)

而我们的 OLED 的显示引脚如下：

![](https://cdn.zhiyanbang.com/md17/WeChat97ece4126d7e264a860dff704c05c950.jpg)

在我们的 ESP32 的硬件 I2C 引脚是 GPIO 22 (SCL) 和 GPIO 21 (SDA) 如下图：

![](https://cdn.zhiyanbang.com/md1/202303011502887.png)

## 硬件连接


| 器件 | 数量 |
|--------|--------|
| ESP32 | 1 |
| 128x64 OLED | 1 |
| 杜邦线 | 若干 |

![](https://cdn.zhiyanbang.com/md17/WeChat999865720e5241ee72af9c737dacc392.jpg)


## 软件代码

### 第一步

- 准备SSD1315 类库,老许给大家放出来了

```javascript
var C = {
    OLED_WIDTH: 128,
    OLED_CHAR: 0x40,
    OLED_CHUNK: 128
};

// commands sent when initialising the display
var extVcc = false; // if true, don't start charge pump 
var initCmds = new Uint8Array([
    0xAe, // 0 disp off
    0xD5, // 1 clk div
    0x80, // 2 suggested ratio
    0xA8, 63, // 3 set multiplex, height-1
    0xD3, 0x0, // 5 display offset
    0x40, // 7 start line
    0x8D, extVcc ? 0x10 : 0x14, // 8 charge pump
    0x20, 0x0, // 10 memory mode
    0xA1, // 12 seg remap 1
    0xC8, // 13 comscandec
    0xDA, 0x12, // 14 set compins, height==64 ? 0x12:0x02,
    0x81, extVcc ? 0x9F : 0xCF, // 16 set contrast
    0xD9, extVcc ? 0x22 : 0xF1, // 18 set precharge
    0xDb, 0x40, // 20 set vcom detect
    0xA4, // 22 display all on
    0xA6, // 23 display normal (non-inverted)
    0xAf // 24 disp on
]);
// commands sent when sending data to the display
var flipCmds = [
    0x21, // columns
    0, C.OLED_WIDTH - 1,
    0x22, // pages
    0, 7 /* (height>>3)-1 */
];

function update(options) {
    if (options) {
        if (options.height) {
            initCmds[4] = options.height - 1;
            initCmds[15] = options.height == 64 || options.height == 48 ? 0x12 : 0x02;
            flipCmds[5] = (options.height >> 3) - 1;
        }
        if (options.width) {
            C.OLED_WIDTH = options.width;
            flipCmds[1] = (128 - options.width) / 2; // 0x20 for 64, 0 for 128;
            flipCmds[2] = flipCmds[1] + options.width - 1; // 0x5f;
        }
        if (options.contrast !== undefined) initCmds[17] = options.contrast;
    }
}

function main(i2c, callback, options) {
    update(options);
    var oled = Graphics.createArrayBuffer(C.OLED_WIDTH, initCmds[4] + 1, 1, {
        vertical_byte: true
    });

    var addr = 0x3C;
    if (options) {
        if (options.address) addr = options.address;
        // reset display if 'rst' is part of options 
        if (options.rst) digitalPulse(options.rst, 0, 10);
    }

    setTimeout(function() {
        // configure the OLED
        initCmds.forEach(function(d) {
            i2c.writeTo(addr, [0, d]);
        });
    }, 50);

    // if there is a callback, call it now(ish)
    if (callback !== undefined) setTimeout(callback, 100);

    // write to the screen
    oled.flip = function() {
        // set how the data is to be sent (whole screen)
        flipCmds.forEach(function(d) {
            i2c.writeTo(addr, [0, d]);
        });
        var chunk = new Uint8Array(C.OLED_CHUNK + 1);

        chunk[0] = C.OLED_CHAR;
        for (var p = 0; p < this.buffer.length; p += C.OLED_CHUNK) {
            chunk.set(new Uint8Array(this.buffer, p, C.OLED_CHUNK), 1);
            i2c.writeTo(addr, chunk);
        }
    };

    // set contrast, 0..255
    oled.setContrast = function(c) {
        i2c.writeTo(addr, 0, 0x81, c);
    };

    // set off
    oled.off = function() {
        i2c.writeTo(addr, 0, 0xAE);
    };

    // set on
    oled.on = function() {
        i2c.writeTo(addr, 0, 0xAF);
    };

    // return graphics
    return oled;
}

```

### 第二步

- 显示字幕和动画

```javascript
I2C1.setup({scl:D22,sda:D21});

var pos = 0;
function draw() {
  g.clear();
  g.setFontVector(12);
  g.drawString("Hello",0,0);

  pos += 0.5;
  g.setFontVector(18 + Math.sin(pos)*4);

  g.drawString("World!",42-g.stringWidth("World!")/2,16);

  g.setFontBitmap();
  g.drawString("a tiny font",25,40);

  g.flip();
}


function go(){
  setInterval(draw, 50);
}

var g = main(I2C1, go, { address: 0x3C, height:64 });
```


