51マイコンにおけるUART通信の実装と制御

UART(Universal Asynchronous Receiver/Transmitter)は、低コストかつ高信頼性を持つ非同期シリアル通信インターフェースであり、マイコン同士、マイコンとPC、あるいは各種センサ・モジュールとの双方向データ交換を可能にします。8051アーキテクチャのマイコンには内蔵UARTが搭載されており、専用のレジスタ群を用いて送受信動作を柔軟に制御できます。

ハードウェア構成と制御レジスタ

通信動作の設定は主にSCON(Serial Control Register)およびPCON(Power Control Register)によって行われます。

  • SCON(0x98):通信モード選択、受信許可、中断フラグ管理を行う。
    モード1(8ビット非同期、可変ボーレート)では、REN = 1で受信を有効化。このビットが0の場合はRxDピンからの入力を無視します。
  • TI(Transmit Interrupt Flag):SBUFへの書き込み完了後、送信終了時に自動的に1にセットされる。ソフトウェアで明示的にTI = 0とリセットする必要があります。
  • RI(Receive Interrupt Flag):受信バッファ(SBUF)へのデータ格納完了時に1にセットされ、割り込み要求を発行。同様に、アプリケーション側でRI = 0としてクリアしなければならない。
  • PCON(0x87)SMOD = 1(ビット7)を設定すると、タイマー1によるボーレート生成時の分周比が2倍になり、より高い通信速度が得られます。

送信機能の実装

以下のコードは、1秒ごとにインクリメントされた値をUART経由で連続送信する例です。ボーレートは9600bps(SMOD=1時)で、タイマー1を8ビット自動再ロードモード(Mode 2)で使用しています。

#include <REGX52.H>

void UART_Init(void) {
    SCON = 0x50;        // モード1、REN有効
    PCON |= 0x80;       // SMOD = 1(ボーレート倍増)
    TMOD &= 0x0F;       // TMODの上位4ビットをクリア
    TMOD |= 0x20;       // T1: 8ビット自動再ロード
    TH1 = 0xF4;         // 9600bps(11.0592MHz, SMOD=1)
    TL1 = 0xF4;
    TR1 = 1;            // タイマー1開始
}

void UART_Transmit(unsigned char data) {
    SBUF = data;
    while (!TI);        // 送信完了待ち
    TI = 0;             // TIフラグクリア
}

unsigned char counter = 0;

void main(void) {
    UART_Init();
    while (1) {
        UART_Transmit(counter++);
        for (unsigned int i = 0; i < 30000; i++); // 簡易遅延(約1s)
    }
}

受信とエコーバック処理

受信処理には割り込み方式が推奨されます。以下は、受信した1バイトをP2ポートに出力し、同時にPCへエコー返信する実装です。割り込みベクタ番号4(RI/TI共通)を用います。

#include <REGX52.H>

void UART_Init(void) {
    SCON = 0x50;
    PCON |= 0x80;
    TMOD &= 0x0F;
    TMOD |= 0x20;
    TH1 = 0xF4;
    TL1 = 0xF4;
    TR1 = 1;
    ES = 1;             // シリアル割り込み有効化
    EA = 1;             // 全体割り込み有効化
}

void UART_Transmit(unsigned char data) {
    SBUF = data;
    while (!TI);
    TI = 0;
}

void UART_ISR(void) interrupt 4 {
    if (RI) {
        unsigned char received = SBUF;
        P2 = ~received;         // 受信値のビット反転出力
        UART_Transmit(received); // エコーバック
        RI = 0;
    }
}

void main(void) {
    UART_Init();
    while (1);
}

タグ: 8051 UART serial-communication Embedded-C scm

7月2日 23:08 投稿