関数の宣言と定義の分離

次は、ドットマトリクスLEDを制御する関数を別ファイル化しましょう。

別ファイル化を行うにあたっては、「関数の宣言と定義の分離」が必要になります。ここでは、まずはこの関数の宣言と定義の分離を行うことにしましょう。

関数の宣言と定義の分離

C言語では、「関数の宣言」と「関数の定義(処理内容の実装)」は別々に行うことができます。

「関数の宣言」とは、関数がどのような名前で、どのような引数と返り値を持つかを宣言するものです。プログラム中で関数を使用する場合、関数が呼び出される部分より前に「関数の宣言」がされている必要があります。

「関数の定義」は、関数の処理内容を実際に実装することによって行われます。「関数の宣言」を別に行わない場合、「関数の定義」をもって「関数の宣言」も行われたとみなされます。

以下は関数の宣言と定義を別々に行った例です。

// 関数の宣言
void initLed();

// 関数の定義(処理内容の実装)
void initLed() {
  処理
}Code language: Arduino (arduino)

「関数の宣言」は関数が呼び出される部分より前に記述する必要がありますが、「関数の宣言」さえ適切に行われていれば「関数の定義」はどこで行ってもかまいません。この「どこで行ってもかまわない」というのがポイントで、別ファイルであってもかまわないのです。

ただし、ここではまずは同じファイル内で「関数の定義」の場所を移動させることにします。

プログラム例

Arduinoフレームワークで重要なのはsetup関数とloop関数です。これらの関数をソースコードの前のほうに持ってきて、他の関数の実装部分についてはソースコードの後ろのほうにまとめる、というようにすると、他の人が見て何が重要かより分かりやすいプログラムになるでしょう。

以下は、ソースコード冒頭ではinitLed関数とsetLed関数の宣言のみを行い、これらの定義(処理内容の実装)をソースコードの後ろのほうに持ってきた例です。

プログラム例 10-2

#include <Arduino.h> // Arduino.h の読み込み
#include "char8x8.h" // char8x8.h の読み込み

// ドットマトリクスLED初期設定関数
void initLed();
// ドットマトリクスLED点灯パターン設定関数
void setLed(byte patternAnode, byte patternCathode);

/*
 * setup 関数
 */
void setup() {
  /* ここにプログラムの最初に1回だけ実行したい処理を上から順に記述していきます */

  // シリアル通信を115200bpsで開始
  Serial.begin(115200);

  Serial.println("初期設定の開始");

  // ドットマトリクスLED初期設定
  initLed();

  Serial.println("初期設定の完了");
}

/*
 * loop 関数
 */
void loop() {
  /* ここにプログラム中で繰り返し実行したい処理を上から順に記述していきます */

  for(int i=0; i<8; i++) {

    // ドットマトリクスLEDのi行目を表示
    setLed(ledPatternA[i], ledCathodePattern[i]);
    // 時間待ち
    delay(1);
  }
}

// ドットマトリクスLEDアノード側ピンの配列
int ledAnodePins[8] = {0, 2, 4, 5, 16, 17, 18, 19};
// ドットマトリクスLEDカソード側ピンの配列
int ledCathodePins[8] = {21, 22, 23, 25, 26, 27, 32, 33};

/*
 * ドットマトリクスLED初期設定関数
 */
void initLed() {

  // 各アノード・カソード端子の設定
  for(int i=0; i<8; i++) {

    // 入出力設定
    pinMode(ledAnodePins[i], OUTPUT);
    pinMode(ledCathodePins[i], OUTPUT);

    // 出力レベル設定(全消灯)
    digitalWrite(ledAnodePins[i], LOW);
    digitalWrite(ledCathodePins[i], HIGH);
  }
}

/*
 * ドットマトリクスLED点灯パターン設定関数
 * 引数: patternAnode 表示するパターン( アノード側)
 *       patternCathode 表示するパターン( カソード側)
 */
void setLed(byte patternAnode, byte patternCathode) {

  // カソード側のパターンを反転
  patternCathode = ~patternCathode;

  // 列および行の点灯設定
  for(int i=0; i<8; i++) {
    // i 列目に patternAnod の i ビット目の値を設定
    digitalWrite(ledAnodePins[i], bitRead(patternAnode, i));
    // i 行目に patternCathode の i ビット目の値を設定
    digitalWrite(ledCathodePins[i], bitRead(patternCathode, i));
  }
}
Code language: Arduino (arduino)

ここでは、ドットマトリクスLEDを制御するピンの配列(ledAnodePins、ledCathodePins)も、setup関数やloop関数内では直接は使わないので、後ろのほうに持ってきています。

プログラムがビルドできること、およびマイコンに書き込んで以前と同様に動作することを確認しましょう。