PASのブログ

PASの中の人が書く雑記ブログです。

switch文とビットシフト アナマル.12

さて、今日はprg_process(int num)の中身を作ります。

それにあたっては、C言語の文法を2つ、switch文と、ビットシフトを学んだほうが楽かと思いますので、ご紹介します。

いきなり完成したソースを紹介

追加分のみ掲載

int BANK_DATA[4] = {0x1, 0x3, 0x7, 0xf};


void setup() {
  pinMode(LED[0], OUTPUT);
  pinMode(LED[1], OUTPUT);
  pinMode(LED[2], OUTPUT);
  pinMode(LED[3], OUTPUT);
  pinMode(LED[4], OUTPUT);
  pinMode(LED[5], OUTPUT);
  pinMode(LED[6], OUTPUT);
  pinMode(LED[7], OUTPUT);
  pinMode(SW[0], INPUT_PULLUP);
  pinMode(SW[1], INPUT_PULLUP);
  pinMode(SW[2], INPUT_PULLUP);
  pinMode(SW[3], INPUT_PULLUP);
}

void prg_process(int num)// PGMモード時動作
{

  switch (num)
  {
    case 0:
      digitalWrite(LED[4], LOW);
      digitalWrite(LED[5], HIGH);
      digitalWrite(LED[6], HIGH);
      digitalWrite(LED[7], HIGH);
      break;

    case 1:
      digitalWrite(LED[4], HIGH);
      digitalWrite(LED[5], LOW);
      digitalWrite(LED[6], HIGH);
      digitalWrite(LED[7], HIGH);
      break;

    case 2:
      digitalWrite(LED[4], HIGH);
      digitalWrite(LED[5], HIGH);
      digitalWrite(LED[6], LOW);
      digitalWrite(LED[7], HIGH);
      break;

    case 3:
      digitalWrite(LED[4], HIGH);
      digitalWrite(LED[5], HIGH);
      digitalWrite(LED[6], HIGH);
      digitalWrite(LED[7], LOW);
      break;
  }

  if (BANK_DATA[num] & 1)
  {
    digitalWrite(LED[0], LOW);    // LEDへの信号をLOW(点灯)
  }
  else
  {
    digitalWrite(LED[0], HIGH);   // LEDへの信号をHIGH(消灯)
  }

  if (BANK_DATA[num] >> 1 & 1)
  {
    digitalWrite(LED[1], LOW);    // LEDへの信号をLOW(点灯)
  }
  else
  {
    digitalWrite(LED[1], HIGH);   // LEDへの信号をHIGH(消灯)
  }
  if (BANK_DATA[num] >> 2 & 1)
  {
    digitalWrite(LED[2], LOW);    // LEDへの信号をLOW(点灯)
  }
  else
  {
    digitalWrite(LED[2], HIGH);   // LEDへの信号をHIGH(消灯)
  }
  if (BANK_DATA[num] >> 3 & 1)
  {
    digitalWrite(LED[3], LOW);    // LEDへの信号をLOW(点灯)
  }
  else
  {
    digitalWrite(LED[3], HIGH);   // LEDへの信号をHIGH(消灯)
  }
}

構造としては、

switch文にて、新たに追加したLED4,5,6,7を点灯する。(点灯しているLED以外は消灯する。)

BANK_DATA[num]に格納しているプログラムデータを分解してそれぞれに対応しているLED及びリレーをONにする。

prg_process関数を抜けて呼び出された位置に戻る。

これでプログラム動作をします。

switch文の使い方

switch文はifなどと同じ条件分岐の命令ですが、非常に明快です。

 switch (変数)
  {
    case 0: //←変数がゼロならbreak;まで実行して抜けろ
      digitalWrite(LED[4], LOW); //LED[4]を点灯しろ
      break; //抜けろ
  }

これだけの構造です。
0-20までnumが動くときはcase 20:まで書けば良いのです。
今回のように、numという変数を渡し続けて全体をコントロールするやり方もありますし、可変抵抗やセンサーを読んだ値をswitchで振り分けることも出来ます。

ビットシフト

ビットシフトとは、ビットの桁をずらすことです。

int BANK_DATA[4] = {0x1, 0x3, 0x7, 0xf};
まず最初に定義したBANK_DATA[]という配列は、
[sw0を押したときの(プログラムされている)LED[0,1,2,3]を並べたもの,sw1を押したときの(以下同文)]
です。0x○○と書く場合は、16進数です。つまり、
int BANK_DATA[4] = {0x1, 0x3, 0x7, 0xf};
を2進数で書くと
int BANK_DATA[4] = {0b0001, 0b0011, 0b0111, 0b1111};
という事になります。
(ちなみにこれはテスト用に初期設定しているだけで、最終的には保存→呼び出しという機能をつけます)

ビットシフトはビットずらしとも言います。
0001を右に1つずらすときは、 >> 1で、左にずらすときは<<と記述します。
a = 0b0001 >> 1; とするとaの中身は0b0000
a = 0b0001 << 1; とするとaの中身は0b0010

今回ビットシフトをしているのは、目的の桁の情報(0か1か)を抜き出すためです。

論理積 AND(&)

if (BANK_DATA[num] & 1) &とは、論理積を表します。
論理積とは、AもBも1なら1、それ以外(1と0,0と1,0と0)のときは0を返す論理演算です。

では、 BANK_DATA[num] & 1とは何をしているかというと、
BANK_DATA[num](例えば0のときは今回の場合0b0001)と1(0b0001)を論理和しなさいという事になり、それぞれの桁でANDを計算します。
& 1とすることで、下一桁が0か1かわかります。