前陣子買了 Arduino/ESP 用的 TFT 彩色螢幕時,發現通訊介面清一色都是 SPI,不像之前買的 0.96" 128x64 單色 OLED 有 I2C 跟 SPI 兩種規格可選。我大概知道二者的差別是 SPI 要接的訊號線較多,但速度快;I2C 最大的好處是只需要兩條線就可串接一堆設備。由彩色螢幕只用 SPI 這點,可推測 I2C 速度慢應是一大罩門,但究竟有多慢,沒實測過心裡不踏實,便多花 90 塊買了片 SPI 介面 128x64 OLED 滿足好奇心。

thumbnail

爬文知道,I2C 的傳輸速度分為標準版 100 kbps 與快速版 400 kbps (還有更快的 3.4 Mbps,但一般 ESP/Arduino 開發板不支援),而 SPI 的傳輸速度為 10 Mbps 起跳,而 0.96" OLED 使用 SSD1306 晶片,依 DataSheet,SPI Clock 頻率上限為 10 MHz (Interface speed = 1/100ns = 10 MHz),序列訊號的資料傳輸量上限也差不多為 10 Mbps。延伸閱讀:

我打算用 ESP32 來測效能差異,程式庫用之前 Fork Adafruit SSD1306 加入 ttyPrintln() 自動捲動功能的版本。測試方法很簡單,ESP32 同時接 I2C 及 SPI 版 OLED,Adafruit SSD1306 程式庫原本就支援 I2C/SPI 兩種版本,故我分別建立 I2C 及 SPI 版的 Adafruit_SSD1306 物件,分別跑測試先顯示由右向左滑入 64x64 Bitmap 的動畫,再 ttyPrintln() 自動上捲列印數字 0 到 255,測試前後由 micros() 算出耗費的時間(µs):

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_SSD1306.h>
#include "bitmap.h"

#define SCREEN_ADDRESS 0x3C

// I2C OLED, SCK=22, SDA=18
Adafruit_SSD1306 displayI2C(128, 64, &Wire, -1);
// SPI OLED, CS=5, RST=17, DC=16, MOSI(D1)=23, SCLK(D0)=18
Adafruit_SSD1306 displaySPI(128, 64, 23, 18, 16, 17, 5);

// the display instance to test
Adafruit_SSD1306 display;

// the test procedure
void runTest(String testName)
{
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
  {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; // Don't proceed, loop forever
  }

  auto startTime = micros();
  // clear the buffer
  display.clearDisplay();

  // 64x64 image sliding from right to center
  for (int i = 128; i >= 32; i--)
  {
    display.clearDisplay();
    display.drawBitmap(i, 0, guineapigBitmap, 64, 64, WHITE);
    display.display();
  }
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 56);

  // print from 0 to 255 with auto scrolling up
  display.ttyPrintln();
  for (int i = 0; i < 256; i++)
  {
    display.ttyPrint(" " + String(i));
    display.display();
  }
  display.ttyPrintln();
  display.ttyPrintln();
  display.display();

  // calculating elapsed time (in µs)
  auto elapsed = micros() - startTime;
  display.ttyPrintln(testName + " elapsed time:");
  display.ttyPrintln(String(elapsed) + " us");
  display.display();
}

void setup()
{
  // test I2C OLED
  display = displayI2C;
  runTest("I2C");
  // test SPI OLED
  display = displaySPI;
  runTest("SPI");
}

void loop()
{
}

令人期待的時刻來臨,答案揭曉 - I2C 耗時 9.8 秒,SPI 耗時 1.2 秒,SPI 快了 8 倍,所以想要快速顯示,選 SPI 就對了。

實測影片

Display speed comparison of I2C and SPI version 0.96" 128x64 OLED with ESP32.


Comments

# by 夜市小霸王

應該再加上一個UART,就完美了 https://www.taiwaniot.com.tw/product/2-2-%E5%90%8B-uart%E4%B8%B2%E5%8F%A3-hmi-%E6%B6%B2%E6%99%B6%E8%9E%A2%E5%B9%95%E6%A8%A1%E7%B5%84/

# by 陳信羽

路過不過這樣應該是軟體SPI? arduino 有硬體SPI

Post a comment