組み込み機器・ハードウェアの設計開発から装置製作まで社内一貫対応!

組み込み機器・ハードウェア設計製作.com
組み込み機器・ハードウェア設計製作.com

produced by株式会社アイディアイ

設計のポイント

switch-caseによるステートマシンの実装

設計内容分類組み込みソフトウェアにおけるC言語記述

実現したい仕様・課題

通信手順や起動シーケンス、モード遷移のような「段階を踏んで進む処理」を、フラグとif文の継ぎ足しで実装すると、状態の組み合わせが管理しきれなくなり、想定外の遷移や デッドロック的な状態残りが発生します。シーケンス制御を見通しよく、拡張しやすい形で実装したいというのが課題です。

設計のポイント

段階的に進む処理は、ステートマシン(状態機械)として設計し、enumによる状態定義とswitch-case文で実装するのが定石です。まず処理の段階をenumで列挙し(例:待機→接続→送信→応答待ち→完了)、状態変数を1つ持ちます。処理関数は「現在の状態に応じた処理を行い、遷移条件が成立したら状態変数を次の状態に書き換える」構造とし、メインループから周期的に呼び出します。各caseの処理を「待ち合わせでブロックしない」よう書くのが重要なポイントで、応答待ちであれば「届いていれば次へ、届いていなければ何もせず戻る」と記述することで、1つの関数で複数の機器・複数のシーケンスを並行して進められ、システム全体の応答性も保たれます。defaultには初期状態へ戻す処理を書き、想定外の状態値からの復帰経路を確保します。タイムアウトは状態と併せて開始時刻(またはカウンタ)を記録し、経過判定で エラー状態へ遷移させます。状態が増えてswitchが肥大化してきた場合は、状態ごとの処理関数を関数ポインタの配列にまとめる方式へ発展させることもできます。この構造はFPGA設計におけるステートマシンと同じ考え方であり、状態遷移図を先に描いてからコード化する、遷移図とcaseを1対1に対応させる、という進め方がそのまま通用します。シーケンスの仕様変更にも、該当状態のcase修正だけで対応でき、影響範囲が局所化されます。

【コード例】

typedef enum { ST_IDLE, ST_CONNECT, ST_SEND, ST_WAIT_ACK, ST_DONE } STATE;
static STATE st = ST_IDLE;

void comm_task(void) {              // メインループから周期呼び出し
  switch (st) {
    case ST_IDLE:     if (start_req)   st = ST_CONNECT; break;
    case ST_CONNECT:  if (connected()) st = ST_SEND;    break;
    case ST_SEND:     send_frame();    st = ST_WAIT_ACK; break;
    case ST_WAIT_ACK: if (ack_recv())  st = ST_DONE;
                      else if (timeout()) st = ST_IDLE; break;
    case ST_DONE:     st = ST_IDLE;   break;
    default:          st = ST_IDLE;   break;  // 不正状態から復帰
  }
}

補足情報

当事例のような、マイコンのファームウェアにおけるC言語記述のポイントをまとめた冊子の無料DLが可能です。
是非以下よりご確認ください。

マイコンのファームウェア C言語記述のポイント

>>ダウンロードはこちら!

お問い合わせ

組み込み機器・ハードウェア 設計製作.comを運営する株式会社アイディアイは、組み込み機器・ハードウェアの設計開発代行サービスを提供しています。
試験装置や制御機器、組み込みボードなど、設計・開発委託先をお探しの皆様、お気軽に当社に御相談ください。

技術資料のダウンロードはこちらから 技術資料ダウンロ―ド メールフォームでのお問い合わせはこちらから ご相談・お問合せ