ステートマシンと電卓の実装

1.四則演算を行う電卓プログラム(50点)とその状態遷移図(50点)を作成せよ。仕様は以下の通り。
 ・数値の入力はPA0を押した回数とする。(何も押していない時は0、1回押すごとに+1)
 ・四則演算(+、-、*、/)の入力は、PA1を押した回数で選択する。(+、一回押すごとに-、*、/、+ ...の順で切り替える)
 ・=はPA2を押すことで実行。
 ・クリアはPA3。
 ・入力値、演算結果の表示はprintfで行う。表示の様式は任意。
 ・チャタリング対策は、添付の関数を用いることで代用可能とする。(自分で実装してもよい)
 ・動作を確認したい人は、このプログラムを実行する事。(表示などは、任意に設定して良い)

ex1) 3 + 4 = 7の演算は、
 PA0を3回押す ⇒ PA1を1回押す ⇒ PA0を4回押す ⇒ PA2を押す(演算結果が表示される) ⇒ 最初に戻る

ex2) 0 - 4 = -4の演算は、
 PA1を2回押す ⇒ PA0を4回押す ⇒ PA2を押す(演算結果が表示される) ⇒ 最初に戻る

※ PA3を押すと、入力したデータをクリアして、最初に戻る。

状態遷移図の記述に当たっては、始め・イベント・アクションを正確に記述する事。
記述がない、間違っている等については、減点とする。

●チャタリング対策済みのスイッチのON/OFF確認関数

#define TRUE   1
#define FALSE   0

// 状態の定義
#define S0  0
#define S1  1
#define S2  2
#define S3  3

// スイッチの指定
#define SW_PA0   0
#define SW_PA1   1
#define SW_PA2   2
#define SW_PA3   3

// スイッチON/OFF 判定
#define SW_ON(bit) (!(PA_DR & (0x1 << bit)))
#define SW_OFF(bit) (PA_DR & (0x1 << bit))

/*
  * 引数にSW_PA0などと指定すると、
  *    指定したスイッチが押されている場合にTRU
  *    離されている場合にFALSEを返す
  */
int detect_switch_on(int sw_no)
{
    static int status[4] = {S0};  // スイッチが4つあるので、それぞれ独立に状態遷移させる
                                          // staticを指定すると、関数を抜けても変数は保持される。
                                          // イメージとしては、関数内だけで使えるグローバル変数
    long int w;
 
    switch(status[sw_no])
    {
        case S0 :
            if (SW_ON(sw_no)) { // bitが0だったら、スイッチPAxが押されたと判断
                status[sw_no] = S1;
            }
            break;

        case S1 :  // スイッチを押したときのチャタリング対策
            for (w=0; w<9999; w++); // wait
            status[sw_no] = S2;
            break;
            
        case S2 :
            if (SW_OFF(sw_no))
            {
                status[sw_no] = S3;
            }            
            break;
            
        case S3 :  // スイッチを離したときのチャタリング対策
            for (w=0; w<9999; w++); // wait
            status[sw_no] = S0;

            return TRUE;
            break;
            
        default :
            status[sw_no] = S0;
            break;
    }

    return FALSE;
}

【detect_switch_on関数の使い方の例】

int main()
{
    ......
    while(1)
    {
        switch(status)
        {
            case S1:
                if (detect_switch_on(SW_PA0) == TRUE)
                {
                    cnt++;
                    status = S2;

のような感じで使う。


【その他の注意】
以下のようなコンパイルエラーが発生した場合は、セクションの定義を一部変更すること。

L1100 (W) Cannot find "B" specified in option "start"
L2321 (E) Section "D" overlaps section "P"

※修正した設定

これでも症状が改善しない場合は、B,Dの設定を0x00FFEA00などに変えて確かめること。

最終更新:2014年12月16日 09:58