關閉

第12章 I²C 雙線通訊完整教學:Arduino Wire、位址掃描與 LCD1602 實作

完整介紹 Arduino I²C(Inter-Integrated Circuit)雙線通訊原理,說明 SDA、SCL、裝置位址、Master 與 Slave 架構,以及 Arduino Uno 的 A4、A5 腳位。文章包含 Wire.h 基礎、I²C Scanner 位址掃描、LCD1602 I²C 接線與程式實作、Pull-up 上拉電阻、通訊速度、多模組共用匯流排,以及常見無法顯示與連線問題排除。

I²C(Inter-Integrated Circuit)是一種常見的同步序列匯流排,只需要 SDA 與 SCL 兩條訊號線,就能讓 Arduino 與多個感測器、顯示器或擴充晶片通訊。

本章將從 I²C 的基本原理、Arduino Uno 腳位、裝置位址與上拉電阻開始,接著實作 I²C Scanner 與 LCD1602 I²C 顯示器,建立後續使用 OLED、RTC、BMP280、MPU6050 等模組所需的基礎。

不同模組可能使用不同工作電壓與 I²C 位址。接線前應先確認模組規格,並避免將僅支援 3.3V 的裝置直接接到不相容的 5V 邏輯電位。

本章學習目標

什麼是 I²C?

I²C 是 Inter-Integrated Circuit 的縮寫,最初由 Philips Semiconductor 提出,後來由 NXP 延續發展。它是一種同步序列通訊匯流排,常用於同一塊電路板或短距離配線中的晶片與模組通訊。

I²C 最大的特色是只需要兩條訊號線,就能讓一個控制器與多個裝置共享同一組通訊線路。Arduino 專案中的 LCD1602 I²C、OLED SSD1306、RTC DS3231、BMP280、BME280、MPU6050、ADS1115、PCF8574、EEPROM、INA219 與 PCA9685 等模組,都常使用 I²C。

為什麼 Arduino 專案常使用 I²C?

傳統平行介面的 LCD1602 通常需要 RS、E、D4、D5、D6、D7 等多條控制與資料線。當專案同時加入顯示器、感測器與時鐘模組時,Arduino 可用腳位很快就會不足。

改用 I²C 後,多個裝置可以共用 SDA 與 SCL。只要裝置位址不衝突,Arduino 就能透過位址選擇要通訊的模組,大幅節省腳位並簡化配線。

I²C 的兩條訊號線

SDA:序列資料線

SDA 是 Serial Data 的縮寫,用來傳送位址、資料與確認訊號。SDA 上的資料變化必須配合 SCL 時脈,通訊雙方才能正確判讀每一個位元。

SCL:序列時脈線

SCL 是 Serial Clock 的縮寫,由控制器提供時脈,使匯流排上的裝置依照相同節奏傳送與接收資料。

Arduino Uno 的 I²C 腳位

Arduino Uno 的 SDA 位於 A4,SCL 位於 A5。Uno R3 也在板子上另外提供標示為 SDA 與 SCL 的接腳,但電氣上仍與 A4、A5 相連。

同一條 I²C 匯流排上的所有裝置,通常需要共用 SDA、SCL 與 GND。各模組的 VCC 則必須依照模組規格連接 5V 或 3.3V。

I²C 匯流排架構與裝置位址

I²C 採用控制器與受控裝置的匯流排架構。Arduino 在多數入門專案中扮演控制器,LCD、RTC、OLED、BMP280 或 MPU6050 等模組則是受控裝置。

每個 I²C 裝置都有位址。Arduino 傳送資料前,會先指定目標位址,再與對應裝置交換資料。常見 LCD1602 I²C 背板可能使用 0x27 或 0x3F,BMP280 常見位址則可能是 0x76 或 0x77,但實際位址仍應以模組規格或掃描結果為準。

使用 I²C Scanner 找出模組位址

當 LCD 沒有畫面,或感測器程式無法讀取資料時,位址設定錯誤是常見原因。I²C Scanner 會依序測試常用的 7-bit 位址範圍,並在 Serial Monitor 顯示有回應的裝置位址。

上傳程式前,先確認模組已正確供電、SDA 與 SCL 未接反,而且 Arduino 與模組已共用 GND。

#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Serial.println("I2C Scanner");
}

void loop()
{
  byte error;

  for (byte address = 1; address < 127; address++)
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("Found: 0x");

      if (address < 16)
      {
        Serial.print("0");
      }

      Serial.println(address, HEX);
    }
  }

  delay(5000);
}

預期掃描結果

開啟 Serial Monitor 並設定為 9600 baud。若模組位址是 0x27,預期會看到 Found: 0x27。若沒有找到任何位址,應先檢查供電、接地、SDA、SCL、模組電壓與接觸不良問題。

Wire.h 函式庫基礎

Arduino 的 I²C 程式通常需要先加入 Wire.h,並在 setup() 中呼叫 Wire.begin() 初始化 I²C。

#include <Wire.h>

void setup()
{
  Wire.begin();
}

void loop()
{
}

實作一:LCD1602 I²C 顯示文字

準備材料

接線方式

顯示 Hello Arduino

下列範例使用常見的 LiquidCrystal_I2C 函式庫。不同函式庫的建構子或初始化函式可能不同,安裝前應確認函式庫文件與模組相容性。程式中的 0x27 必須改成 Scanner 實際找到的位址。

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Hello Arduino");
}

void loop()
{
}

程式上傳後,LCD 第一行預期顯示 Hello Arduino。若背光亮起但沒有文字,可先調整 I²C 背板上的對比旋鈕,再確認位址與函式庫是否正確。

實作二:在 LCD 顯示 ADC 數值

此實作可搭配第 9 章的 analogRead()。將可變電阻中間腳接到 A0,另外兩腳接 5V 與 GND,再把讀到的 ADC 數值顯示在 LCD 第二行。

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Analog Input");
}

void loop()
{
  int adcValue = analogRead(A0);

  lcd.setCursor(0, 1);
  lcd.print("ADC=");
  lcd.print(adcValue);
  lcd.print("    ");

  delay(200);
}

LCD 每 200 毫秒更新一次 A0 的 ADC 數值。程式在數值後補上空白,用來清除前一次顯示留下的多餘字元。

一條 I²C 匯流排可以連接多少模組?

I²C 可以讓多個裝置共用 SDA 與 SCL,例如同時連接 LCD、OLED、RTC、BMP280 與 MPU6050。能否正常共存,主要取決於裝置位址是否衝突、電壓是否相容、上拉電阻配置、線路長度、匯流排負載與供電品質。

若兩個模組使用相同且無法更改的位址,就不能直接在同一條 I²C 匯流排上獨立存取。可先查看模組是否提供位址選擇焊點,或使用 I²C 多工器等方式處理。

I²C 為什麼需要上拉電阻?

I²C 的 SDA 與 SCL 通常採用開漏極或開集極輸出。裝置主要負責把訊號線拉低,訊號線回到高電位則需要上拉電阻。

常見模組可能已內建約 4.7kΩ 的上拉電阻,因此單一模組短線測試通常不需要另外加裝。多個模組都內建上拉電阻時,等效阻值會下降;匯流排較長、模組較多或速度較高時,應依電壓、總電容與實際波形評估,不宜只憑固定阻值判斷。

I²C 通訊速度與配線限制

Arduino Wire 函式庫常以 100 kHz 標準模式運作,部分裝置也支援 400 kHz Fast Mode。是否能提高速度,必須同時確認控制器、所有受控裝置與配線條件。

速度越高,越需要縮短線材、降低雜訊、維持良好接地並正確配置上拉電阻。I²C 原本主要用於板級或短距離通訊,不適合直接當作長距離外部傳輸介面。

常見問題與故障排除

Scanner 找不到任何裝置

LCD 背光亮但沒有文字

多個模組接上後通訊不穩定

本章實作練習

本章重點整理

下一章預告

第 13 章將介紹 SPI(Serial Peripheral Interface)高速序列通訊,包括 MOSI、MISO、SCK、SS 的用途、Arduino Uno 的 SPI 腳位,以及 SPI 與 I²C 的差異。