關閉

第11章 Arduino UART(TTL Serial)序列通訊入門與實作

本章完整介紹 Arduino UART(TTL Serial)序列通訊原理,說明 UART、TTL Serial 與 RS-232 的差異,以及 Arduino Uno D0(RX)、D1(TX)腳位的正確接線方式。內容包含 Serial.begin()、Serial.print()、Serial.println()、Serial Monitor 與 Serial Plotter 的使用方法,並透過 ADC 數值與電壓輸出範例,學習序列通訊除錯、鮑率設定、TX/RX 交叉接線、共地及 5V/3.3V 電位注意事項。

UART(Universal Asynchronous Receiver/Transmitter)是 Arduino 與電腦、感測器、藍牙模組、GPS 及其他微控制器交換資料時最常見的序列通訊方式之一。

本章將從 UART、TTL Serial 與 RS-232 的差異開始,說明 Arduino Uno 的 RX、TX 腳位、鮑率設定、Serial Monitor 操作,以及 Serial.print() 與 Serial.println() 的實際用法。

進行接線前,必須先確認雙方的工作電壓。Arduino Uno 使用 5V TTL 邏輯,部分模組則使用 3.3V,不能只依照 TX、RX 名稱直接連接。

本章學習目標

完成本章後,你將能夠:

什麼是 UART?

UART 是 Universal Asynchronous Receiver/Transmitter 的縮寫,中文通常稱為「通用非同步收發器」。它是一種不需要共用時脈訊號的序列通訊方式,資料會依序逐位元傳送。

Arduino Uno 內建一組硬體 UART,可用來與電腦、藍牙模組、GPS、其他微控制器及各類序列設備交換資料。

什麼是 TTL Serial?

Arduino Uno GPIO 腳位輸出的 UART 訊號採用 TTL 邏輯電位。以 Uno R3 為例,LOW 約為 0V,HIGH 約為 5V,這種 UART 電氣訊號通常稱為 TTL Serial。

GPS、HC-05 藍牙模組、ESP8266 等裝置常使用 TTL Serial,但各裝置的工作電壓不一定相同。連接前應先查閱模組規格,確認 RX 腳是否能承受 Arduino Uno 的 5V 訊號;必要時應使用分壓或邏輯電平轉換器。

UART、TTL Serial 與 RS-232 的差異

UART、TTL Serial 與 RS-232 常被混用,但三者代表不同層面的概念。UART 是通訊控制器與資料傳輸方式;TTL Serial 是 UART 搭配 TTL 邏輯電位的訊號;RS-232 則是一套不同的電氣規範。

為什麼 Arduino 不能直接連接 RS-232?

傳統 RS-232 可能使用約 +3V~+15V 與 -3V~-15V 的正負電壓表示邏輯狀態。Arduino Uno 的 GPIO 不適合承受這類電壓,因此不能把 RS-232 設備直接接到 D0、D1。

連接 RS-232 設備時,應使用 MAX232、MAX3232 或功能相同的電平轉換模組。選用前仍應確認轉換器的供電電壓、接頭定義與訊號方向。

Arduino Uno 的 UART 腳位與接線方式

兩台 UART 設備連接時,TX 與 RX 必須交叉。Arduino 的 TX 要接到對方的 RX,Arduino 的 RX 要接到對方的 TX。

除了 TX 與 RX,雙方還必須共地,也就是將兩台設備的 GND 連接在一起。沒有共同參考電位時,即使鮑率設定正確,也可能無法穩定接收資料。

Arduino TX(D1) → 對方 RX
Arduino RX(D0) ← 對方 TX
Arduino GND       ─ 對方 GND

USB 為什麼也能使用 Serial?

Arduino Uno 除了主要的 ATmega328P 微控制器外,板上還有負責 USB 通訊轉換的晶片。官方 Uno R3 常見為 ATmega16U2,部分相容板則可能使用 CH340 等 USB-to-Serial 晶片。

當 Arduino IDE 上傳程式,或 Serial Monitor 與開發板通訊時,USB 通訊晶片會在電腦的 USB 資料與 ATmega328P 的 UART 訊號之間進行轉換。

電腦 USB
   ↓
USB 通訊轉換晶片
   ↓
UART
   ↓
ATmega328P

使用 Serial.begin() 設定鮑率

使用序列埠前,必須先在 setup() 中呼叫 Serial.begin(),並指定通訊鮑率。下列程式會啟用硬體序列埠,通訊速度設定為 9600 bps。

void setup()
{
  Serial.begin(9600);
}

void loop()
{
}

什麼是 Baud Rate?

Baud Rate(鮑率)用來表示通訊速度。一般 Arduino UART 教學中,常以 bps 表示每秒傳送的位元數。

通訊雙方必須使用相同的鮑率。若 Arduino 程式設定為 9600,而 Serial Monitor 選擇 115200,畫面通常會出現亂碼或無法辨識的字元。

Serial.print() 與 Serial.println()

Serial.print():輸出後不換行

Serial.print() 會輸出文字或變數內容,但游標會停在同一行,適合將多個資料組合成一行。

Serial.print("Temperature = ");
Serial.print(25);
Temperature = 25

Serial.println():輸出後自動換行

Serial.println() 在輸出資料後會加入換行,下一次輸出會從新的一行開始。

Serial.println("Hello Arduino");

第一個 Arduino Serial 實驗

下列程式每隔 1 秒輸出一次 Hello Arduino。上傳完成後,開啟 Arduino IDE 的 Serial Monitor,並將鮑率設定為 9600。

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  Serial.println("Hello Arduino");
  delay(1000);
}

預期 Serial Monitor 會每秒顯示一行 Hello Arduino。若沒有輸出,應先確認選擇的開發板、序列埠與鮑率是否正確。

Hello Arduino
Hello Arduino
Hello Arduino

輸出 analogRead() 讀取的變數

Serial 是 Arduino 除錯時最常用的工具。以下範例讀取 A0 的 ADC 數值,並在 Serial Monitor 顯示結果。

void setup()
{
  Serial.begin(9600);
}

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

  Serial.print("ADC = ");
  Serial.println(sensorValue);

  delay(500);
}

實際數值會依 A0 的輸入電壓而改變。預期輸出格式如下:

ADC = 632
ADC = 630
ADC = 628

使用 Serial Monitor 除錯

Serial Monitor 是 Arduino IDE 中重要的序列通訊與除錯工具。除了顯示開發板傳出的資訊,也能把使用者輸入的文字傳送給 Arduino。

開發程式時,可在重要流程加入序列輸出,確認感測器數值、條件判斷、函式執行順序或錯誤狀態。正式完成程式後,再依需求減少過多的除錯訊息。

使用 Serial Plotter 繪製數值變化

Arduino IDE 的 Serial Plotter 可以把連續輸出的數值轉換成折線圖,適合觀察溫度、光照、超音波距離、可變電阻與其他感測器的變化。

為了讓圖形穩定顯示,每一筆資料應使用一致的輸出格式。若同時輸出大量說明文字,可能影響 Serial Plotter 解析數值。

UART 常見錯誤與故障排除

Serial Monitor 顯示亂碼

最常見原因是鮑率不一致。確認程式中的 Serial.begin() 與 Serial Monitor 右下角選擇的鮑率完全相同,也要確認外部設備本身使用的鮑率。

TX 接到 TX 或 RX 接到 RX

一般 UART 通訊要使用交叉接法:TX 接對方 RX,RX 接對方 TX。若設備名稱標示方式特殊,應以該設備資料表或接線說明為準。

忘記連接共同 GND

兩台設備沒有共地時,TX 與 RX 缺少共同電壓參考,可能完全收不到資料,也可能出現不穩定或間歇性錯誤。

外部模組占用 D0、D1 導致程式無法上傳

Arduino Uno 的 D0、D1 同時用於硬體 UART、USB 序列通訊與程式上傳。若外部模組持續驅動這兩個腳位,可能造成上傳失敗或序列資料互相干擾。

5V 與 3.3V 電位不相容

部分 UART 模組的 RX 腳只能接受 3.3V。若直接接收 Arduino Uno TX 的 5V 訊號,可能造成通訊異常,甚至損壞模組。接線前必須查閱規格,必要時使用分壓電阻或雙向邏輯電平轉換器。

本章實作練習

練習一:每秒輸出文字

使用 Serial.println("Hello Arduino"); 每秒輸出一次文字,並確認 Serial Monitor 的鮑率與程式設定一致。

練習二:顯示 A0 的 ADC 值

使用 analogRead(A0) 讀取類比輸入,將 ADC 數值持續輸出到 Serial Monitor,並轉動可變電阻觀察數值變化。

練習三:顯示 ADC 值與電壓

將 ADC 值換算為電壓並輸出。以下範例假設 ADC 參考電壓約為 5.0V;實際值會受開發板供電與參考電壓影響。

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int adcValue = analogRead(A0);
  float voltage = adcValue * (5.0 / 1023.0);

  Serial.print("ADC = ");
  Serial.println(adcValue);

  Serial.print("Voltage = ");
  Serial.print(voltage, 2);
  Serial.println("V");

  delay(1000);
}

Challenge:製作序列除錯工具

建立一個每秒輸出 ADC 數值、換算電壓與 LED 狀態的序列除錯工具,並讓所有資訊排列在同一行。

const int ledPin = 13;

void setup()
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  int adcValue = analogRead(A0);
  float voltage = adcValue * (5.0 / 1023.0);
  bool ledOn = adcValue >= 512;

  digitalWrite(ledPin, ledOn ? HIGH : LOW);

  Serial.print("ADC: ");
  Serial.print(adcValue);
  Serial.print("  Voltage: ");
  Serial.print(voltage, 2);
  Serial.print("V  LED: ");
  Serial.println(ledOn ? "ON" : "OFF");

  delay(1000);
}
ADC: 512  Voltage: 2.50V  LED: ON

本章重點整理

下一章預告

第 12 章將介紹 I²C(Inter-Integrated Circuit)雙線通訊,包括 SDA、SCL、Arduino Uno 的 I²C 腳位、Wire.h 函式庫、I²C Scanner,以及 LCD1602 I²C、OLED、RTC、BMP280 等模組的通訊方式。