8051マイクロコントローラでのUART通信プロトコル実装

概要

本稿では、8051マイクロコントローラ(MCU)のシリアルインターフェース(UART)を使用し、ホストコンピュータとの間でデータ通信を行うシステムの構築方法について解説します。通信仕様は、モード1(8ビットUART)、ボーレート9600bpsとします。データ送信はポーリング方式、受信は割り込み方式を採用し、LEDの制御およびシステム状態の返信を行うプロトコルを実装します。

システム要件

  • システム起動時、ブザーとリレーなどの不要な周辺機器を停止し、ホストPCへ「Welcome to XMF system!」に続いて改行コードを送信する。
  • ホストPCからのシングルバイトコマンドに基づき、下位機器(MCU)のLED8個のオン・オフを制御する。
  • ホストPCからの要求に応じて、下位機器の動作状態情報を返信する。

通信プロトコル仕様

コマンドは1バイト(8ビット)で構成され、上位4ビットがコマンド種別、下位4ビットがデータまたはパラメータを表します。

機能 上位ニブル 下位ニブル 説明
LED制御 A (0xA0) L4 L3 L2 L1 各ビットがLED1~LED4に対応。0:消灯、1:点灯。
B (0xB0) L8 L7 L6 L5 各ビットがLED5~LED8に対応。0:消灯、1:点灯。
状態読み出し C (0xC0) 0 「The System is Running...」と改行コードを返信する。

実装とコード解説

以下に、システム制御および通信処理の実装例を示します。コードは保守性を考慮し、モジュール化されています。また、元のロジックを維持しつつ、変数名や関数構成を見直しています。

ヘッダファイルおよび定義

#include <reg52.h>

// 拡張レジスタ定義
sfr AUXR = 0x8E;

// デコーダ(HC537)チャンネル選択用マクロ
#define DECODER_LED     4
#define DECODER_BUZZER  5
#define DECODER_DIGIT   6
#define DECODER_SEGMENT 7

周辺機器の初期化

システム起動時にLEDを消灯し、ノイズ発生源となるブザー等を停止させます。

void hardware_init(void)
{
    // デコーダ設定
    P2 = (P2 & 0x1F) | (0x80); // 出力選択: LEDポート (CH4)
    P0 = 0xFF;               // 全LED消灯

    P2 = (P2 & 0x1F) | (0xA0); // 出力選択: ブザー等 (CH5)
    P0 = 0x00;               // ブザー、リレー OFF
}

UART通信モジュール

Timer1をボーレートジェネレータとして使用し、UARTモード1で初期化を行います。受信割り込みを有効にします。

// グローバル変数:受信コマンドバッファ
volatile unsigned char rx_command = 0x00;

void uart_config(void)
{
    TMOD = 0x20;    // Timer1: モード2(8ビットオートリロード)
    TH1 = 0xFD;     // 9600bps @ 11.0592MHz
    TL1 = 0xFD;
    TR1 = 1;        // Timer1 スタート

    SCON = 0x50;    // モード1, 受信許可 (REN=1)
    AUXR = 0x00;    // 標準8051速度設定

    ES = 1;         // シリアル割り込み許可
    EA = 1;         // 全体割り込み許可
}

// 1バイト送信(ポーリング方式)
void uart_send_byte(unsigned char dat)
{
    SBUF = dat;
    while (TI == 0); // 送信完了待ち
    TI = 0;          // 割り込みフラグクリア
}

// 文字列送信
void uart_send_string(unsigned char *str)
{
    while (*str != '\0')
    {
        uart_send_byte(*str++);
    }
}

// シリアル割り込みサービスルーチン
void uart_isr_handler(void) interrupt 4
{
    if (RI == 1)
    {
        rx_command = SBUF; // 受信データを格納
        RI = 0;            // 受信フラグクリア
    }
    // TIフラグの処理はポーリング送信を行うためここでは不要
}

コマンド処理ロジック

メインループ内で受信コマンドを監視し、プロトコルに従ってLED制御やステータス返信を行います。ビット演算を用いてLEDの状態を更新します。

void process_commands(void)
{
    if (rx_command != 0x00)
    {
        unsigned char cmd = rx_command;
        rx_command = 0x00; // コマンド処理済みフラグをクリア

        // LED出力を選択
        P2 = (P2 & 0x1F) | (0x80);

        switch (cmd & 0xF0) // 上位4ビットで分岐
        {
            case 0xA0: // LED1-4 制御
                // 下位4ビットを反転してLED出力に反映(アクティブロー回路想定)
                // 例: コマンド0xA3 (0011) -> LED1,2 点灯
                P0 = (P0 & 0xF0) | (~cmd & 0x0F);
                break;

            case 0xB0: // LED5-8 制御
                // 下位4ビットを左にシフトして上位4ビットへマッピング
                // 例: コマンド0xB3 (0011) -> LED5,6 点灯
                P0 = (P0 & 0x0F) | ((~cmd << 4) & 0xF0);
                break;

            case 0xC0: // ステータス要求
                uart_send_string("The System is Running...\r\n");
                break;
        }
    }
}

メイン関数

void main(void)
{
    hardware_init();
    uart_config();

    // 起動メッセージ送信
    uart_send_string("Welcome to XMF system!\r\n");

    while (1)
    {
        process_commands();
    }
}

タグ: 8051 UART EmbeddedC SerialCommunication microcontroller

6月21日 01:24 投稿