C言語

スイッチのON/OFFによりLEDを点灯・消灯させる

CS+のプロジェクトを作成から、スイッチのON/OFFにより、LEDを点灯・消灯させることを学びます。
ポート機能で使用するレジスタの説明」や「IOポートの設定」にて学習しているため、ポート・レジスタに対して 0 と 1 を設定するのみでLEDを点灯/消灯させることができるとイメージできる方もいると思います。実際にその通りで、あまりプログラミングをすることもなくLEDの点灯/消灯が出来てしまいます。
このため、今回は、CS+のプロジェクト作成から、「IOポートの設定」で作成したファイルを利用し、main関数にてLEDを点灯するまでの一連の流れを学びたいと思います。

CS+のプロジェクトを作成する

最初にCS+を起動してプロジェクトを作成します。作成手順は、「CS+を使ってマイコン基板と接続する」の「CS+の起動から設定まで」章以降の手順で作成します。
プロジェクト名は、「LED_test」としましたが、好きな名前を付けていただいて問題ありません。

次に、「hdwinit.asm」は不要なので削除します。
「hdwinit.asm」を右クリックして、「プロジェクトから外す」を選択します。プロジェクト・ツリーからhdwinit.asmファイルが削除されていると思います。

「cstart.asm」は、CPUリセット後、main関数を呼び出すより前に、一番最初に呼び出されるスタートアッププログラムです。
各種初期設定等の処理を行ったりします。また、このプログラムからmain関数が呼び出されます。変更する場合は、アセンブラ言語で記述する必要がありますが、今回は、特に変更する予定はありません。

「hdwinit.asm」 は、周辺装置の初期化処理用のアセンブラファイルです。プロジェクト作成時は特に処理は記述されていません。
アセンブラ言語で記述する必要があるので、一度削除しました。この後で、このファイルにあるhdwinit関数をC言語で記述する予定です。

「stkinit.asm」は、スタック領域を初期化するアセンブラファイルです。特に変更する必要はありません。

「iodefine.h」は、マイコンの定数名の定義をしているファイルです。特に変更する必要はありません。

次からは、前回「IOポートの設定」にて作成した「RL78G14_init.c」に対して、main関数を呼び出す前に実行されるhdwinit関数を追加していきたいと思います。

RL78G14_init.cファイルにhdwimit関数を追加する

IOポートの設定」 で作成した RL78G14_init.c を開いて、hdwinit関数を作成します。
作成する場所は、RL78G14_init_IO_Port関数の前に追加します。
追加する関数の内容は次のとおりです。

void hiwinit( void )
{
    PIOR0 = RL78G14_INIT_PIOR0;
    PIOR1 = RL78G14_INIT_PIOR1;
    RL78G14_init_IO_Port();
}

PIOR0とPIOR1は、周辺I/Oリダイレクション・レジスタの初期化です。初期値のままなので、特に記述する必要はありません。今回は、明示的に記述しています。
周辺I/Oリダイレクション・レジスタの詳細は、「ポート機能で使用するレジスタの説明」にて解説しています。
その後に、「IOポートの設定」で作成した RL78G14_init_IO_Port関数を呼び出して、IOポートの初期化をします。

次に、まだRL78G14_INIT_PIOR0などの定数定義をしていませんので、記述していきます。
RL78G14_init.cファイルの#include "iodefine.h"の下に定数定義がされていますので、そこに次の定数定義を追加します。
特に定数定義で纏まっていればどこでも大丈夫です。

/* 周辺I/Oリダイレクション・レジスタ(PIORx) */
#define RL78G14_INIT_PIOR0 (0x00U)
#define RL78G14_INIT_PIOR1 (0x00U)

次は、RL78G14_init_IO_Port関数をstatic関数に変更し、プロトタイプ宣言を追加します。
static関数にすることは必須ではありませんが、 RL78G14_init_IO_Port関数は、ファイル内でしか使用しないため、静的な関数に変更しました。

static void RL78G14_init_IO_Port( void );  /* プロトタイプ宣言 */

プロトタイプ宣言は、hdwinit関数より上のほうで宣言していただければどこでも問題ありません。

プロジェクトにRL78G14_init.cファイルを追加する

CS+のプロジェクトを開いて、プロジェクト・ツリーにあるファイルを右クリックして、「追加」から「既存のファイルを追加」を選択します。

作成した「RL78G14_init.c」を選択して、「開く」ボタンを押します。
プロジェクト・ツリーに「RL78G14_init.c」が追加されていると思います。
ファイルが追加されたら、今度は、main関数にスイッチを押したら、LEDを点灯する処理を記述していきます。

main関数にLEDを点灯させる処理を記述する

スイッチの入力を監視し入力があった場合、LEDを点灯させるプログラムを記述していきます。

マイコン基板には、スイッチ(SW)が2つと、LEDが3つ付いています。
基板には、SW1、SW2と書かれたところがスイッチです。また、LED0、LED1、LED2と書かれたところがLEDになっています。
今回の仕様は次のとおりです。

  • SW1ボタンを押しているときに、LED0を点灯させます。押している間は点灯したままとし、SW1ボダンを離した場合はLED0を消灯させます。
  • SW2ボタンを押しているときに、LED1を点灯させます。押している間は点灯したままとし、SW1ボダンを離した場合はLED1を消灯させます。
  • SW1ボタンとSW2ボタンを押しているときは、LED0、LED1、LED2を点灯します。SW1とSW2を両方押している間はすべて点灯したままとします。

この仕様のほかにマイコン基板の回路の説明を行います。

SW1とSW2は、ボダンを押すと、0Vに繋がるようになっているため、押すと 0 が入力されます。また、プルアップ抵抗もプルダウン抵抗も付いていないため、内蔵プルアップ抵抗を設定していますので、ボタンを離した状態では、 1 が入力されます。

次に、LEDですが、LEDは、5Vに繋がっています。このため、マイコンから 1 を出力すると、5Vが出力される結果、LEDの両端が5Vとなり、電流が流れないため、消灯します。また、マイコンから 0 を出力すると、LEDが5Vに繋がっていることにより、点灯します。

整理すると、
SW1、SW2は、0 が押している状態、 1 が離している状態です。
LEDは、 0 で点灯させる、 1 で消灯させる、です。

SW1は、P75に割付いています。ポート・レジスタ「P7_bit.no5」で値が読み取れます。
SW2は、P73に割付いています。ポート・レジスタ「P7_bit.no3」で値が読み取れます。
LED0は、P17に割付いています。ポート・レジスタ「P1_bit.no7」に 0 / 1 を設定して点灯・消灯させます。
LED1は、P55に割付いています。ポート・レジスタ「P5_bit.no5」に 0 / 1 を設定して点灯・消灯させます。
LED2は、P01に割付いています。ポート・レジスタ「P0_bit.no1」に 0 / 1 を設定して点灯・消灯させます。

また、常時、スイッチの状態を取得できるように、無限ループを作成してその中に仕様を満たす処理を記述します。
また、P7_bit.no5 などを利用できるように、iodefine.hをインクルードする必要があります。

以上をもとにmain関数を作成してみましょう。

いろんな方法で実現できるかと思います。これが正解というものはありませんが、
参考までに、サンプルプログラムを次に示します。

#include "iodefine.h"

void main(void);

void main(void)
{
    while( 1 )
    {
        if( P7_bit.no5 == 0 ) /* SW1がONの場合 */
        {
            P1_bit.no7 = 0;   /* LED0を点灯 */
        }
        else
        {
            P1_bit.no7 = 1;   /* LED0を消灯 */
        }
        if( P7_bit.no3 == 0 ) /* SW2がONの場合 */
        {
            P5_bit.no5 = 0;   /* LED1を点灯 */
        }
        else
        {
            P5_bit.no5 = 1;   /* LED1を消灯 */
        }
        if( ( P7_bit.no5 == 0 ) && ( P7_bit.no3 == 0 ) )
        {
            P0_bit.no1 = 0;  /* LED2を点灯 */
        }
        else
        {
            P0_bit.no1 = 1;  /* LED2を消灯 */
        }
    }
}

サンプルプログラムの通りでなくても問題ありません。自分自身でいろいろ試してみるもの面白いと思います。

スイッチのON/OFFによりLEDを点灯・消灯させるプログラムの作成は以上になります。
今回は、スイッチの入力をその瞬間の値を読み取りましたが、スイッチは、微細な振動などによりON/OFFを繰り返したりすることがあります。このため、押したり、離したりしていないのに0/1が入力されることがあります。これをチャタリングと呼びます。このようなことが起こるので、一定の時間ONならONを、一定の時間OFFならOFFを確定させるということを行う必要がありますが、これは、マイコンの割り込み機能やタイマを学んだ後に紹介したいと思います。

RL78マイコンには、必ず必要な設定(オプション・バイト)がありますが、その設定をしていませんでした。
RL78マイコンで必ず必要な設定(オプション・バイト)」にて、解説していますので、まだされていない方は参照していただけると幸いです。

今回は、これで以上となります。

次回は、マイコンのタイマ機能について学びたいと思います。


-C言語