インターフェース・バス(有線)

UART

調歩同期式のシリアル通信。デバッグや機器間通信に。

概要

UART(Universal Asynchronous Receiver/Transmitter:調歩同期式シリアル通信)は、送受信を非同期で行うシリアル通信インターフェースです。「調歩同期式」とは、送信側と受信側が共通のクロック信号を持たず(非同期)、データの先頭にスタートビットを置くことでタイミングを合わせる方式を指します。

UARTは組み込みシステムにおいて最も歴史が長く、最もシンプルなシリアル通信の一つです。2本のワイヤ(TXとRX)だけで双方向通信が実現でき、デバッグコンソールとの接続、GPSモジュール・Bluetoothモジュールとの通信、機器間の制御コマンド送受信など、幅広い用途で今も現役です。

なお、「UART」は通信方式(プロトコル)ではなくハードウェア機能(インターフェース)を指します。実際の電圧レベルは別途定義され、RS-232C(±12V系)、RS-485(差動信号)、TTLレベル(0/3.3V または 0/5V)など複数の物理層で使われます。

歴史・背景

UARTの起源はテレタイプ端末(TTY)時代の1960年代にまで遡ります。コンピュータとターミナルを接続するためのシリアル通信規格として発展し、1969年に制定されたRS-232C規格とともに普及しました。

1970〜80年代にはNational SemiconductorのIM6402やIntelの8250 UARTチップが広く使われ、PCのシリアルポート(COM1〜COM4)として搭載されました。8250の後継となる16550は、FIFOバッファを内蔵し、割り込み処理の負荷を大幅に軽減しました。

現代のマイコン(STM32、ESP32、AVRなど)はほぼ全機種がUARTペリフェラルを内蔵しており、「USART(Universal Synchronous/Asynchronous Receiver/Transmitter)」として同期モードも兼ねることが多いです。物理層としてはTTLレベルのUARTが主流となり、RS-232Cの±12V駆動はレガシー用途に限られるようになりました。

技術仕様

基本パラメータ(ボーレート設定)

UARTで最初に設定すべきパラメータは「ボーレート(Baud Rate)」です。1秒間に転送できるシンボル(bit)数を表します:

ボーレート用途
9600 bpsGPS、古いセンサー、デバッグ用途
19200 bps一部の産業機器、Modbus
38400 bpsBluetooth Classic SPP
57600 bps一般的なファームウェア書き込み
115200 bps最も多用される標準速度
230400 bps高速デバッグコンソール
460800 / 921600 bps高速ファームウェア転送
1 Mbps〜特定の高速アプリケーション

フレームフォーマット

UARTのデータフレーム構成:

アイドル状態: HIGH
スタートビット: 1ビット(LOW)
データビット: 5, 6, 7, または 8ビット(LSBファースト)
パリティビット: なし / 奇数 / 偶数(省略可能)
ストップビット: 1, 1.5, または 2ビット(HIGH)

最も一般的な設定は「8N1」:8データビット、パリティなし、ストップビット1。

例:文字'A'(0x41 = 0b01000001)を8N1で送信
[スタート(L)][1][0][0][0][0][0][1][0][ストップ(H)]
              ↑LSB                         ↑MSB

フロー制御

大量データ転送時にバッファオーバーフローを防ぐフロー制御:

  • ハードウェアフロー制御(RTS/CTS): RTSピンとCTSピンを追加し、受信バッファが満杯になったら送信を停止
  • ソフトウェアフロー制御(XON/XOFF): 制御文字(0x11=XON, 0x13=XOFF)でフローを制御
  • なし: 小データ量や送受信速度が十分に余裕ある場合

動作原理

UARTの受信側は、スタートビットの立ち下がりエッジを検出すると、ボーレートから計算したビット幅でサンプリングを開始します。中心付近(ビット幅の50%付近)でサンプリングすることでノイズ耐性を高めています:

ビット幅 = 1 / ボーレート
例:115200bps → 1 / 115200 ≈ 8.68μs/bit

サンプリングタイミング(オーバーサンプリング16倍の場合):
スタートビット検出後、8クロック待ってからサンプリング開始
以降、16クロックごとに各ビットをサンプリング

マイコンのUARTペリフェラルは、送受信にFIFOバッファを持ち、DMA(Direct Memory Access)と組み合わせることでCPU割り込みなしに連続受信が可能です:

// STM32 HAL + DMAを使ったUART受信の例

uint8_t rx_buffer[256];

// DMAで256バイト受信(受信完了まで割り込みなし)
HAL_UART_Receive_DMA(&huart1, rx_buffer, 256);

// 受信完了コールバック
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // rx_bufferにデータが揃った
        process_received_data(rx_buffer, 256);
    }
}

用途・ユースケース

UARTが活躍する主な場面:

  • デバッグコンソール: PCとUSB-UARTアダプタ(CH340, FT232等)で接続し、printfデバッグ。最も基本的なデバッグ手段
  • GPSモジュール: u-blox等のGNSSモジュールはNMEAセンテンスを9600〜115200bpsのUARTで出力
  • Bluetoothモジュール: HC-05/HC-06などのATコマンド付きモジュールはUARTで制御
  • マルチドロップ接続: RS-485と組み合わせることで複数デバイス間の通信が可能
  • 産業プロトコル: Modbus RTUはUART(RS-485物理層)上で動作
  • ファームウェア書き込み: STM32のDFUモードやESP32のシリアルブートローダーはUART経由で書き込み

実装・開発のポイント

デバッグコンソールの実装

// printf をUART経由で使う(STM32 HAL)
// syscalls.cにてfwrite/write関数をオーバーライド

int _write(int file, char *ptr, int len) {
    HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);
    return len;
}

// これにより以下が使える
printf("Hello UART! count=%d\r\n", count);

受信バッファとリングバッファ

可変長データを扱う場合はリングバッファ(循環バッファ)が便利です:

#define RX_BUF_SIZE 256
uint8_t rx_ring[RX_BUF_SIZE];
volatile uint16_t rx_head = 0, rx_tail = 0;

// 割り込みハンドラで1バイト受信
void USART1_IRQHandler(void) {
    if (USART1->SR & USART_SR_RXNE) {
        rx_ring[rx_head] = USART1->DR;
        rx_head = (rx_head + 1) % RX_BUF_SIZE;
    }
}

// メインループで読み出し
uint8_t read_byte(void) {
    while (rx_head == rx_tail);  // データ待ち
    uint8_t b = rx_ring[rx_tail];
    rx_tail = (rx_tail + 1) % RX_BUF_SIZE;
    return b;
}

ボーレートの誤差と注意点

マイコンの内部クロックからボーレートを生成するため、設定値と実際の速度に誤差が生じます。一般的に±2.5%以内であれば正常に通信できますが、長いケーブル・高速ボーレートほど厳しくなります。水晶振動子(外付けクロック)を使うか、HSEを参照することで誤差を減らせます。

受信タイムアウト処理

相手方からの応答がない場合を考慮したタイムアウト処理を必ず実装します:

// タイムアウト付き受信(ポーリング)
HAL_StatusTypeDef status = HAL_UART_Receive(&huart1, buf, len, 1000);  // 1000ms timeout
if (status == HAL_TIMEOUT) {
    // タイムアウト処理
}

他技術との比較

UART vs I2C vs SPI

項目UARTI2CSPI
必要な配線数2本(TX/RX)2本(SDA/SCL)4本以上(MOSI/MISO/SCK/CS)
接続形態基本1対1マルチマスタ・マルチスレーブ1マスタ・マルチスレーブ
速度〜数Mbps100k/400k/1M/3.4Mbps数十Mbps
クロック同期なし(非同期)あり(同期)あり(同期)
主な用途デバッグ・モジュール通信センサーディスプレイ・フラッシュ

UART vs RS-232C vs RS-485

  • UART(TTLレベル): 0V/3.3Vまたは0V/5V、短距離、1対1
  • RS-232C: ±12V系、信号レベルが異なるがプロトコルはUARTと同じ
  • RS-485: 差動信号、長距離(最大1200m)、マルチドロップ対応

関連用語

参考リンク