H8/3052F PIO入力  
2010/04/20

今回は、AKI-H8/3052FのPIOポートからビットの状態を入力する方法をご紹介しましょう。ここでいうビットの状態とは、入力しようとするPIOポートの各ビットが1なのか0なのかを示す情報で、単純に言うとPIOポートに接続されたスイッチがONかOFFかを認識するということです。といっても前回のH8/3052F PIO出力のページをご覧頂けた方にとっては非常に簡単なことでしょう。PIOポートの各ビットの状態を入力して識別し、処理することができるということは、マイコンプログラムにとって最も基本的で重要で機能です。これにより、外部の状態や条件に基づいてプログラムの動作に変化を与えることが出来るようになります。


1.H8/3052FのPIO

H8/3052FマイコンのPIOポートや各種レジスタについては、H8/3052F PIO出力のページをご覧下さい。
 


2.PIO入力のプログラム例 その1

それでは、早速ですが実際のPIO入力を行うプログラムの事例を見てみましょう。このプログラムはHEW4の環境でビルドできます。
【ダウンロード】 pio_test2.c
右クリックで「対象をファイルに保存」

今回のプログラムではport2を入力用、port1を出力用とし、port2から入力されたスイッチのON/OFF情報を、単純にport1に出力します。なのでport2のスイッチの状態が、すぐにport1のLEDランプの点灯となって現れます。

/***************************************/
/* C TEST PROGRAM BY RIKIYA 2010.04.19 */
/* for AKI-H8/3052F CPU BOARD          */
/* PROGRAM NAME pio_test2.C            */
/***************************************/

#include "iodefine.h"

//main***********************************

void main(void){

    P1.DDR = 0xFF;      // port1を全て出力に設定
    P2.DDR = 0x00;      // port2を全て入力に設定
    P2.PCR.BYTE = 0xFF; // port2のプルアップ抵抗あり

        while(1){

            //port2のデータをport1に代入
            P1.DR.BYTE = P2.DR.BYTE;

        }
}


すみません。プログラムが簡単すぎたかもしれませんが、中身について見てみましょう。

■コメント文

/**/ではさまれた部分と、//で始まる部分は、それぞれコメント文ですね。

■メイン関数

P1.DDR = 0xFF; によりport1を出力用に設定し、P2.DDR = 0x00; によりport2を入力用に設定します。また、P2.PCR.BYTE = 0xFF; によりport2のプルアップを全てONにしています。ここまでで環境の準備は完了です。次にwhile(1){ }によって無限ループを作り、その中でP1.DR.BYTE = P2.DR.BYTE; を実行します。これは文字通り、P2.DR.BYTEで与えられるport2からの入力データを、P1.DR.BYTEで示すport1に対して代入、つまり出力しているということになります。これがwhile(1){ }の無限ループによって高速に繰り返されることによって、port2への入力が即座にport1に反映される、という動作となって現れます。

■ヘッダファイルのインクルード

プログラムの中に、P1.DDRや、P2.PCR.BYTEなど、H8/3052Fのレジスタに相当する記述が使えるようにするためのヘッダファイルiodefine.hを読み込むため、プログラムの先頭部分で#include "iodefine.h" を記述しています。



3.pio_test2.c の実行

【MOVIE】 ダブルクリックで再生されます。
  左はプログラムpio_test2.cの動作ムービーです。port2に接続されているスイッチをONにすると、port1の該当するビットのLEDが消灯します。動作としては、スイッチONで該当するLEDが点灯するのが自然でしょうが、この事例では逆になっています。これはスイッチの回路とLEDの回路に起因します。
今回のマザーボードの回路についてはAKI-H8/3052F自作マザーボードのページをご参照下さい。スイッチはONでport2の各ビットがGNDに接続される回路になっており、LEDはH8/3052Fのport1出力を電源として直接点灯させています。

■1.スイッチがOFFだとPCRプルアップによってport2は1と認識される。
■2.そのままport1に1として出力されて、端子は+5VとなってLEDが点灯する。
■3.スイッチがONになるとport2はGNDに繋がって0と認識される。
■4.そのままport1に0として出力されて、端子は0VとなってLEDが消灯する。

ちなみにwhile(1){ }の中を P1.DR.BYTE = ~P2.DR.BYTE; のように「~」(にょろ)を追加して再度ビルドしてみてください。LEDの表示が反転して、スイッチがONになったLEDだけが点灯するようになります。

4.PIO入力のプログラム例 その2

先ほどのご紹介したプログラム例は、少し簡単すぎてつまらなかったですね。せっかくなので、入力したデータに何らかの演算を加えて出力結果に少し変化を持たせてみましょう
【ダウンロード】 pio_test2a.c
右クリックで「対象をファイルに保存」

このプログラムではport2を入力用、port1を出力用とし、port2から入力されたスイッチのON情報によってport1の該当するLEDを点灯させます。ただし、点灯したLEDの光はどんどん左側に流れていって消えてしまいます。続けてスイッチをONにすると、たくさんのLEDの光が左に流れていくというイルミネーションになります。
/***************************************/
/* C TEST PROGRAM BY RIKIYA 2010.04.19 */
/* for AKI-H8/3052F CPU BOARD          */
/* PROGRAM NAME pio_test2a.C           */
/***************************************/

#include "iodefine.h"

//main***********************************

void main(void){

    unsigned long i;
    unsigned short data = 0x00;

    P1.DDR = 0xFF;      // port1を全て出力に設定
    P2.DDR = 0x00;      // port2を全て入力に設定
    P2.PCR.BYTE = 0xFF; // port2のプルアップ抵抗あり

    while(1){

        //port2のデータ(のnot)と変数dataをorしてdataに代入
        data |= ~P2.DR.BYTE;

        //変数dataをport1に代入(出力)
        P1.DR.BYTE = data;

        //変数dataを1bit左にシフトして変数dataに代入
        data <<= 1;

        //時間かせぎ
        for (i=0;i<0x000FFFFF;i++) {}

    }
}


それでは、中身について見てみましょう。

■メイン関数

unsigned long i; は時間かせぎを行う際にカウントアップさせるための変数iの宣言です。unsigned short data = 0x00; は、port2から入力される8ビットデータを一時的に格納する変数で、同時に0x00(つまりゼロ)に初期化しています。次にport1を出力に、port2を入力に設定し、port2のプルアップをありに設定しています。その後while(1){ }による無限ループ処理に入ります。無限ループの中では以下のようなことをしています。

data |= ~P2.DR.BYTE;
なにやら変な記号が並んでいて意味が良くわかりませんね... 「 | 」(縦棒)はビット演算子でorを示します。また、「~」(にょろ)もビット演算子でnot(反転)を示します。更に、上の式を見慣れた形に書き換えると、data = data | ~P2.DR.BYTE; と同じ意味になります。これなら意味が通じるでしょうか。「dataとP2.DR.BYTEのビットを反転させた値をorしたものをdata代入しろ」ということになります。余計分からなくなりましたね... 以下に事例を示しましょう。
例えばdataが0x88(●○○○ ●○○○)で、P2.DR.BYTEが0xEC(●●●○ ●●○○)だった場合、
~P2.DR.BYTEは反転なので(○○○● ○○●●)となり、data(●○○○ ●○○○)と~P2.DR.BYTE(○○○● ○○●●)をorした値(●○○● ●○●●)がdataに代入される、という動きになります。

P1.DR.BYTE = data;
これは単純に先ほどビット演算の処理を行ったdataをport1に出力しているものです。このタイミングでLEDが●○○● ●○●●と点灯します。

data <<= 1;
さて、また変な記号が出てきました。なにやら左を向いた矢印のようです。「<<」もビット演算子で指定のビット数だけ左(上位)にシフトしろという意味です。これも見慣れた形に書き換えると、data = data << 1; と同じ意味です。ここでは「dataのビットを1ビット分だけ左(上位)にシフトさせて、dataに代入しろ」ということになります。先ほどの事例で言うと、dataが(●○○● ●○●●)だったら演算によってdataは(○○●● ○●●○)に変化します。シフトによって左隅からはみ出たビットは消えて、右隅から新たに現れたビットは○(ゼロ)になります。

for (i=0; i<0x000FFFFF; i++){ }
これは以前にもご紹介している時間稼ぎです。ここでは次のビット演算とLEDランプ点灯の更新までの間隔を調整しています。

さて、これら一連の処理が無限ループによって繰り返されると、いったいどういう動きになるのでしょうか。



5.pio_test2a.c の実行

【MOVIE】 ダブルクリックで再生されます。
左はプログラムpio_test2a.cの動作ムービーです。
port2に接続されているスイッチをONにすると、port1の該当するビットのLEDが点灯し、どんどん左に流れていきます。次々とスイッチをONにしてみると、流れている最中のLEDは残ったまま、新たなランプも流れに加わっていきます。ビット演算でわざわざor処理を行っているのは、このへんの動作に関連しています。また、流れの早さは時間かせぎによって決まります。
or処理「| 」をなくしてみるとどうなるか、「<<」を「>>」に書き換えてみるとどうなるか、などサンプルのプログラムを色々といじってみて、動作がどんな具合に変化するのか、試してみるのも楽しいかと思います。




今回は、H8/3052FのPIOからビット情報を入力する方法を見てみました。ついでに少しだけビット演算子によるビットの操作についても触れてみました。マイコンによって周辺機器とインターフェイスを取り、様々な制御を掛けていこうとするとき、PIOは色々と力を発揮してくれることでしょう。使い方はアイデア次第といったところです。是非工夫してみてください。

先頭に戻る

 

【表紙に戻る】