H8/3052F PIO出力  
2010/03/20

AKI-H8/3052Fマイコンボードが使える環境が整ったところで、一番簡単で分かりやすいプログラムから学んでいくことにしましょう。先ずはPIOポートからビット単位でのパラレル出力です。PIOポートとはパラレルIO(アイ・オー)のことで、マイコン端子のビットごとに0や1を出力したり、逆に外部回路からビット単位で状態を入力して、0か1かを判別したりといったことができます。今回はPIOの出力機能を使って、PIO端子に接続したLEDランプを自由に光らせてみましょう。


1.H8/3052FのPIO

H8/3052Fマイコンには、以下のPort1からPortBまでのPIOポートがあります。
Port 機 能 DDR DR PCR
Port1 8bit LED駆動 FFFC0 FFFC2 ---
Port2 8bit LED駆動 入力プルアップ FFFC1 FFFC3 FFFD8
Port3 8bit FFFC4 FFFC6 ---
Port4 8bit              入力プルアップ FFFC5 FFFC7 FFFDA
Port5 4bit LED駆動 入力プルアップ FFFC8 FFFCA FFFDB
Port6 7bit FFFC9 FFFCB ---
Port7 8bit FFFCE --- ---
Port8 5bit 2〜0シュミット入力 FFFCD FFFCF ---
Port9 6bit FFFD0 FFFD2 ---
PortA 8bit 7〜0シュミット入力 FFFD1 FFFD3 ---
PortB 8bit LED駆動 3〜0シュミット入力 FFFD4 FFFD6 ---

表のDDR、DR、PCRは、各ポートの動作を設定するためのレジスタや、データの受け渡しを行うレジスタのことで、表中のFで始まる文字は、各レジスタのアドレスを表します。 それぞれのレジスタの意味は以下の通りとなります。

■DDR (データディレクションレジスタ)

DDRは、Portをビットごとに入力か出力かに設定するレジスタです。出力に設定したいビットを1、入力に設定したいビットを0にします。例えば、Port1の0〜3ビットを出力、4〜7ビットを入力に設定したい場合は、Port1のDDRである0xFFFC0のアドレスにデータ0x0Fを書き込みます。
bit 7 6 5 4 3 2 1 0
data 0 0 0 0 1 1 1 1
 16進 0       F

0xとは、その後に続く数値が16進数であることを示す表記方法のことです。

■DR (データレジスタ)

DRは、Portとのデータのやり取りを行うレジスタです。出力ポートに設定してあれば、DRからデータを読み出してPIOポートにそのデータを出力します。入力ポートに設定してあれば、PIOポートの各ビットの0か1かの状態をDRに書き込みます。例えばPort1が出力ポートに設定してあるとき、Port1のDRである0xFFFC2のアドレスに0xC3を書き込むと、Port1の各ビットは以下の状態が出力されます。
bit 7 6 5 4 3 2 1 0
data 1 1 0 0 0 0 1 1
 16進    C 3   

※電気的にはdataが1の状態が5Vで、0の状態が0V(GND)のレベルが出力されているということになります。

■PCR (プルアップMOSコントロールレジスタ)

PCRは、Port2、4、5だけにある機能で、内部のプルアップ抵抗を付けるか、付けないかを設定するためのレジスタです。プルアップしたいビットを1、したくないビットを0に設定します。例えばPort2の0〜3ビットをプルアップ無し、4〜7ビットをプルアップ有りにしたい場合は、Port2のPCRである0xFFFD8のアドレスにデータ0xF0を書き込みます。
bit 7 6 5 4 3 2 1 0
data 0 0 0 0 1 1 1 1
 16進 F       0

※プルアップは、特にポートを入力に設定した場合に利用します。入力ポートにスイッチやオープンコレクタなどの無電圧のデバイスが接続されている場合、スイッチがOFFの状態(オープン状態)のときに電圧が不定になって、ONなのか、OFFなのかがわからなくなるような回路のときにプルアップを有りに設定します。プルアップ有りにすると、入力ポートはマイコン内部で電源電圧(5V)に吊られるため、スイッチがオープン状態の時でも、はっきりと1であると認識できるようになります。



2.PIO出力のプログラム例

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

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

#include "iodefine.h"

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

void main(void){

    unsigned long i;

    P1.DDR = 0xFF;      // port1を全て出力に設定
    P3.DDR = 0xFF;      // port3を全て出力に設定
    P4.DDR = 0xFF;      // port4を全て出力に設定
    P5.DDR = 0xFF;      // port5を全て出力に設定
    P6.DDR = 0xFF;      // port6を全て出力に設定
    PA.DDR = 0xFF;      // portAを全て出力に設定
    PB.DDR = 0XFF;      // portBを全て出力に設定

    P4.PCR.BYTE = 0x00; // port4のプルアップ抵抗なし
    P5.PCR.BYTE = 0x00; // port5のプルアップ抵抗なし

    while(1){

        //各portに○●○● ○●○●を書き込み
        P1.DR.BYTE = 0x55;
        P3.DR.BYTE = 0x55;
        P4.DR.BYTE = 0x55;
        P5.DR.BYTE = 0x55;
        P6.DR.BYTE = 0x55;
        PA.DR.BYTE = 0x55;
        PB.DR.BYTE = 0x55;

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

        //各portに●○●○ ●○●○を書き込み
        P1.DR.BYTE = 0xAA;
        P3.DR.BYTE = 0xAA;
        P4.DR.BYTE = 0xAA;
        P5.DR.BYTE = 0xAA;
        P6.DR.BYTE = 0xAA;
        PA.DR.BYTE = 0xAA;
        PB.DR.BYTE = 0xAA;

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


それでは、プログラムの中身について見てみましょう。

■コメント文

プログラム中の記述には、実際にマイコンの動きに関係のあるプログラム文と、直接マイコンの動きに関係しないコメント文があります。コメント文は、プログラムに関する説明や覚え書きなどを記載して、プログラム自体を分かりやすくする役割があります。 上記のプログラムはC言語で記載されていますが、以下に示す部分は全てコメント文になっています。

/**/ではさまれた部分。これは複数の行にまたがってコメント文を指定することができます。
//で始まる部分。これは複数の行ではなく、その行の//より右側の記述がコメント文であることを示します。

■メイン関数

void main(void) {   } はメイン関数と呼ばれ、このプログラムの中心となる部分です。{ と } の間にプログラムを記述します。
ここでは、先ずPort1,3,4,5,6,A,Bの各ポートのDDRを0xFFにセットし、全てのビットを出力に設定しています。その後、Port4,5のPCRを0x00にセットして、プルアップ無しとしています。これで今回使用したい各PIOポートの初期設定を完了します。次に、各PIOポートのDRに出力したいデータをセットします。ここでは先ず0x55をセットしています。0x55を2進数のビットで表現すると 0101 0101 になります。次に時間稼ぎの処理を行った後に、今度は各PIOポートのDRに0xAAをセットします。0xAAを2進数のビットで表現すると 1010 1010 になります。その後に再び時間稼ぎの処理を行います。「0x55のセット→時間稼ぎ→0xAAのセット→時間稼ぎ」という一連の処理は、while(1){   } の括弧の中に記述されおり、これによって無限に繰り返されます。つまり、各PIOポートに接続されたLEDは、0101 0101と1010 1010の表示を、時間稼ぎで設定した時間の周期で永遠に繰り返すという動きになります。

■時間稼ぎ処理

ここでは、LEDを 0101 0101 または 1010 1010 と表示する時間を得るために時間稼ぎを行っています。ここで時間稼ぎをしておかないと、0101 0101 と 1010 1010 の切り替わりが早すぎて、見た目では全てのLEDが点きっぱなしになっているように見えてしまいます。
for (i=0;i<0x0004FFFF;i++) {}
の部分が時間稼ぎの処理になります。メイン関数内の先頭に unsigned long i; の宣言を行っており、これと対になって機能します。for文は本来 {   } の括弧の中の処理を、i < ○○ の条件が成立する間、繰り返すという動きをします。今回の場合でいうと「i が0から始まって、1ずつ増やして行き、0x0004FFFFより小さい間は、{ }の中の処理を繰り返す」ということになります。ちなみに0x0004FFFFを通常の10進数に直すと、327,679という数字になります。しかし、今回は{ }の中には何もありません。ここでは単純に i をひとつ増やして i < 0x0004FFFF の条件に合致しているかどうかの比較を行うという処理を327,679回だけ繰り返しているということになります。マイコン自体がこの処理を行うのに費やす時間が、ここでいう時間稼ぎになります。0x0004FFFFの部分を、0x0008FFFF程度に増やしてビルドして見て下さい。点滅が遅くなります。

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

プログラムの中に、P1.DDRとか、P4.PCR.BYTEとか、P1.DR.BYTEなど、H8/3052Fの各Port用のレジスタに相当する記述が使われていますが、これらはC言語で標準で準備されているものではありません。では、いったいどこから出てきたものなのでしょう?
先頭部分の #include "iodefine.h" の部分に注目してください。これは、このプログラムではiodefine.hというヘッダファイルを読み込みますよという宣言になります。それではiodefine.hとは一体なんでしょう?
HEW4の環境で #include "iodefine.h"が記述されているプログラムを一度ビルドすると、画面左のツリー表示の「Dependencies」のところに「iodefine.h」のアイコンが表示されますので、そこをダブルクリックしてみましょう。プログラムの編集画面にiodefine.hの中身が表示されます。

ここには、H8/3052Fマイコンのレジスタを操作するための変数が構造体で宣言され、実際のレジスタのアドレスと紐付けされています。C言語ではポインタと呼ばれるアドレス空間を直接操作するための仕組みもあり、その都度プログラム上で変数として宣言すれば、同様にレジスタの操作を行うことも可能です。しかし少し煩雑になってしまうため、このようにあらかじめ準備されているヘッダファイルを利用するのが便利です。

iodefine.hを利用すれば、H8/3052Fのハードウェアマニュアルで解説されているレジスタ名と対比させやすく、プログラムも分かりやすいものになりますので是非お使い下さい。




3.pio_test1.C の実行

  実は、このプログラムは「環境作り FDTのセットアップ」でAKI-H8/3052Fマイコンボードへのプログラム書込みを試してみた際に使ったものです。

さて、pio_test1.cをビルドして実行してみましょう。Port1,3,4,5,6,A,Bという多くのポートのビットが、下記のような出力を交互に繰り返します。

●○●○●○●○
     ↑↓
○●○●○●○●

なので、一先ずお手元のハードウェア上で手っ取り早く正常に動作することを確認してみたいといった時には便利です。

今回は、H8/3052Fを使う上でPIOのPortを使った、最も簡単なプログラムをご紹介しました。非常に簡単でしたが、マイコンを使って外部の機器を制御するための基本中の基本でもあります。先ずは実際に動かしてみてここから理解を深めていけば、より高度で楽しいマイコンプログラミングの世界に入ることができるでしょう。

先頭に戻る

 

【表紙に戻る】