Coding4Fun - OLED 顯示器 I2C vs SPI 效能評測
2 |
前陣子買了 Arduino/ESP 用的 TFT 彩色螢幕時,發現通訊介面清一色都是 SPI,不像之前買的 0.96" 128x64 單色 OLED 有 I2C 跟 SPI 兩種規格可選。我大概知道二者的差別是 SPI 要接的訊號線較多,但速度快;I2C 最大的好處是只需要兩條線就可串接一堆設備。由彩色螢幕只用 SPI 這點,可推測 I2C 速度慢應是一大罩門,但究竟有多慢,沒實測過心裡不踏實,便多花 90 塊買了片 SPI 介面 128x64 OLED 滿足好奇心。
爬文知道,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。延伸閱讀:
- 認識UART、I2C、SPI三介面特性 by MAKERPRO
- SPI vs I2C Protocols - Pros and Cons
- How to Drive the SSD1306 OLED LCD display
我打算用 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