🧩 1. ความหมายของ I²C และ SPI
ทั้ง I²C (Inter-Integrated Circuit) และ SPI (Serial Peripheral Interface) คือ “โปรโตคอลการสื่อสารแบบอนุกรม” ที่ออกแบบมาเพื่อให้ ไมโครคอนโทรลเลอร์ สามารถเชื่อมต่อกับ “อุปกรณ์หลายตัว” ได้โดยใช้ สายไม่มาก
🔸 I²C (อ่านว่า “ไอ-สแควร์-ซี” หรือ “ไอทูซี”)
- ใช้สายเพียง 2 เส้น:
SCL(Serial Clock) → สัญญาณนาฬิกาSDA(Serial Data) → สัญญาณข้อมูล
- เป็นระบบ Master–Slave
- 1 Master (ไมโครคอนโทรลเลอร์)
- หลาย Slave (เซนเซอร์, จอ ฯลฯ)
- แต่ละ Slave มี “หมายเลขประจำตัว” เรียกว่า Address (ที่อยู่ I²C)
📘 ตัวอย่าง:
ESP32 (Master) → BME280 (Addr: 0x76), OLED (Addr: 0x3C)
🔹 SPI (Serial Peripheral Interface)
- ใช้สาย 4 เส้น (หรือมากกว่าเล็กน้อย)
MOSI→ Master Out Slave InMISO→ Master In Slave OutSCK→ ClockSS→ Slave Select (เลือกอุปกรณ์แต่ละตัว)
- ความเร็วสูงกว่า I²C มาก (ระดับ MHz)
- เหมาะสำหรับงานที่ต้องการความเร็ว เช่น จอสี TFT, SD Card, เซนเซอร์วัดความเร็วสูง
⚙️ 2. สรุปความแตกต่างระหว่าง I²C กับ SPI
| รายการ | I²C | SPI |
|---|---|---|
| จำนวนสาย | 2 เส้น (SCL, SDA) | 4 เส้น (MISO, MOSI, SCK, SS) |
| การต่ออุปกรณ์หลายตัว | ง่าย (ระบุ Address) | ต้องมี SS แยกแต่ละอุปกรณ์ |
| ความเร็ว | ปานกลาง (100k–400kHz) | สูง (1–20 MHz) |
| โครงสร้าง | Master–Slave | Master–Slave |
| การเชื่อมต่อ | ใช้ Address | ใช้ขา SS |
| ตัวอย่างอุปกรณ์ | OLED, RTC, BME280, EEPROM | SD Card, TFT, Flash Memory |
🔹 3. I²C Communication ใน Arduino / ESP32
Arduino และ ESP32 มี ไลบรารี Wire.h สำหรับใช้งาน I²C ได้ง่ายมาก
✅ ขา I²C พื้นฐาน
| บอร์ด | SDA | SCL |
|---|---|---|
| Arduino UNO | A4 | A5 |
| Arduino MEGA | 20 | 21 |
| ESP32 (default) | 21 | 22 |
แต่ใน ESP32 สามารถกำหนดขา SDA/SCL เองได้ด้วย
🔹 4. ตัวอย่าง: I²C Scanner (ตรวจหา Address ของอุปกรณ์)
📘 โปรแกรมนี้ใช้หาว่าอุปกรณ์ I²C ต่ออยู่ไหม และมี Address อะไร
#include <Wire.h>
void setup() {
Wire.begin(); // เริ่ม I2C (SDA=21, SCL=22)
Serial.begin(115200);
Serial.println("\nI2C Scanner Running...");
}
void loop() {
byte error, address;
int nDevices = 0;
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at 0x");
if (address < 16) Serial.print("0");
Serial.print(address, HEX);
Serial.println();
nDevices++;
}
}
if (nDevices == 0) Serial.println("No I2C devices found.\n");
else Serial.println("Scan done.\n");
delay(2000);
}
ผลลัพธ์ใน Serial Monitor เช่น:
I2C device found at 0x3C
I2C device found at 0x76
หมายถึงมีจอ OLED (0x3C) และ BME280 (0x76) ต่ออยู่
🔹 5. ตัวอย่าง: แสดงข้อความบนจอ OLED (I²C)
📘 ใช้ไลบรารี Adafruit_SSD1306 + Adafruit_GFX
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("OLED not found");
for (;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 25);
display.println("ESP32!");
display.display();
}
void loop() {}
แสดงข้อความ “ESP32!” บนจอ OLED ขนาด 0.96 นิ้ว
🔹 6. การใช้ I²C หลายอุปกรณ์
ต่อขา SDA, SCL ร่วมกันได้เลย
แต่ต้องไม่ซ้ำ Address
📘 ตัวอย่าง:
- OLED (0x3C)
- BME280 (0x76)
Wire.beginTransmission(0x3C);
Wire.write(...);
Wire.endTransmission();
Wire.beginTransmission(0x76);
Wire.write(...);
Wire.endTransmission();
ระบบจะเลือกคุยกับอุปกรณ์ตาม Address ที่ระบุ
🔹 7. SPI Communication
Arduino และ ESP32 มีไลบรารี SPI.h สำหรับใช้งาน SPI
| บอร์ด | MISO | MOSI | SCK | SS |
|---|---|---|---|---|
| Arduino UNO | 12 | 11 | 13 | 10 |
| ESP32 (default) | 19 | 23 | 18 | 5 |
แต่ ESP32 สามารถกำหนดขาใหม่ได้ทั้งหมด
🔹 8. ตัวอย่าง: SPI อ่านข้อมูลจาก SD Card
📘 ใช้ไลบรารี SD.h
#include <SPI.h>
#include <SD.h>
#define CS_PIN 5
void setup() {
Serial.begin(115200);
if (!SD.begin(CS_PIN)) {
Serial.println("SD card not found!");
return;
}
Serial.println("SD card ready!");
File file = SD.open("/test.txt", FILE_WRITE);
file.println("Hello ESP32 SPI!");
file.close();
Serial.println("Data written to SD card.");
}
void loop() {}
🔹 9. ตัวอย่าง: SPI เชื่อมต่อจอ TFT
📘 ใช้ไลบรารี TFT_eSPI
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.drawString("Hello SPI!", 40, 60);
}
void loop() {}
🔹 10. การเลือกโปรโตคอลให้เหมาะสม
| งาน / อุปกรณ์ | แนะนำใช้ | เหตุผล |
|---|---|---|
| จอ OLED, RTC, เซนเซอร์หลายตัว | I²C | ใช้สายร่วมกันได้ |
| จอสี TFT, SD Card | SPI | ต้องการความเร็วสูง |
| ระบบหลาย Node | I²C (ง่ายต่อการขยาย) | Address-based |
| การส่งข้อมูลปริมาณมาก | SPI | Bandwidth สูงกว่า |
📚 11. แบบฝึกหัดท้ายบท
1️⃣ เขียนโปรแกรม I²C Scanner เพื่อค้นหา Address ของอุปกรณ์
2️⃣ เชื่อมต่อจอ OLED (I²C) และแสดงข้อความ “Hello LIC”
3️⃣ อ่านค่าจากเซนเซอร์ BME280 และแสดงบน OLED
4️⃣ บันทึกข้อมูลลง SD Card ผ่าน SPI
5️⃣ ทดลองเปลี่ยน Address ของอุปกรณ์ I²C และเชื่อมต่อพร้อมกัน 2 ตัว
🧾 12. สรุปแนวคิดสำคัญ
| หัวข้อ | อธิบาย |
|---|---|
| I²C | ใช้สาย 2 เส้น (SCL, SDA) ติดต่ออุปกรณ์หลายตัว |
| SPI | ใช้ 4 เส้น (MISO, MOSI, SCK, SS) เร็วกว่า |
| Master–Slave | MCU = Master, Sensor/Display = Slave |
| Address | หมายเลขของอุปกรณ์ใน I²C |
| Wire.h | ไลบรารีควบคุม I²C |
| SPI.h | ไลบรารีควบคุม SPI |
| I²C Scanner | โปรแกรมค้นหา Address |
| OLED / BME280 | ตัวอย่างอุปกรณ์ I²C |
| SD Card / TFT | ตัวอย่างอุปกรณ์ SPI |
