概要
本稿では、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();
}
}