連載
» 2009年11月18日 00時00分 公開

ポートを使いこなし、いざ制御プログラミングの世界へイチから作って丸ごと学ぶ! H8マイコン道(8)(3/3 ページ)

[横田一弘 埼玉県立新座総合技術高等学校 教諭,MONOist]
前のページへ 1|2|3       

――C言語によるポート制御ができるようになって、健一君もいろいろと興味がわいてきたようです。でも、健一君のいうとおり、プログラムの先頭にある「#define」が分からないと完全理解とはいえません。そこには、C言語の「ポインタ(pointer)」テクニックが生かされているのです。

ポインタでメモリの操作は自由自在

 ここまでの解説で、H8マイコンのポート操作はポートコントロールレジスタとポートデータレジスタの2種類のI/Oレジスタにより行われることが分かりました。では、これらのI/Oレジスタはどこにあるのでしょうか?

 そう、その答えは「メモリ」です。

 H8/3664のハードウェア・マニュアルを調べてみると、図5のようなメモリマップが見つかります。このメモリマップには、H8マイコンに内蔵されているROMやRAMが、メモリのどの番地にあるかが示されています。


H8/3664Fのメモリマップ 図5 H8/3664Fのメモリマップ

 H8/3664Fの場合、(0)16番地から(7FFF)16番地までがROM領域、(F780)16番地から(FF7F)16番地までがRAM領域です。そして、(FF80)16番地からの内蔵I/Oレジスタ領域に、ポートなどの周辺機能を操作するI/Oレジスタが配置されています。つまり、ポートコントロールレジスタとポートデータレジスタはここにあるのです。

 H8マイコンのように、メモリ空間の一部分にI/Oレジスタを配置することを「メモリマップドI/O」と呼びます。メモリマップドI/Oの利点は、I/Oレジスタをメモリと同等にアクセスできることです。つまり、I/OレジスタのアクセスにC言語のポインタが使えます。

 実際に各ポートへアクセスするために、H8Tiny-USBで使用するポートコントロールレジスタとポートデータレジスタの番地を表2に示します。

レジスタ名称 略称 ビット数 アドレス
ポートデータレジスタ1 PDR1 8 FFD4
ポートデータレジスタ5 PDR5 8 FFD8
ポートデータレジスタ8 PDR8 8 FFDB
ポートコントロールレジスタ1 PCR1 8 FFE4
ポートコントロールレジスタ5 PCR5 8 FFE8
ポートコントロールレジスタ8 PCR8 8 FFED
表2 H8Tiny-USBで使用するポートのI/Oレジスタ

 それでは、I/Oレジスタのアクセス方法を解説します。

 例えば、ポートデータレジスタ1は、FFD4番地のバイト領域です。C言語で「0xFFD4」は、単なる整数なのでキャスト演算子により、バイト領域へのポインタに型変換します。

    (char *)0xFFD4 

 これで「0xFFD4番地のバイト領域」を指すポインタができました。続いて、このメモリ領域にアクセスするには、

    *((char *)0xFFD4) 

と「参照演算子(*)」を使えばよいのです。

 また、「ポート1の状態を変数dataに入力する」には、

    data = *((char *)0xFFD4); 

と変数「data」に代入すればよいのです。

 このように、ポインタによるI/Oレジスタのアクセスを毎回コーディングするのは厄介です。そこで、プログラムの先頭部分で「#define」を使って、ポート定義をしているのです。

 最後に、ポート定義で使われている「volatile」について説明しましょう。

 I/Oレジスタの内容は、プログラムの処理とは別に内容が変わることがあります。例えば、入力ポートのポートデータレジスタの内容は、外部からの信号値が入っています。このようなことをCコンパイラに教えるために、「volatile」修飾子が用意されているのです。

コラム(1): C言語と2進数

H8マイコンの制御プログラムでは、バイト(8ビット)、ワード(16ビット)、ロングワード(32ビット)のデータを扱います。それでは、バイト、ワード、ロングワードのデータをC言語ではどのように表現するのでしょうか。

C言語の整数型(integral type)は、コンピュータ内で単に2進数で処理されるように定められています。C言語では、表3のようにバイトはchar型で、ワードはshort int(略してshort)型を、ロングワードはlong int(略してlong)型で扱います。

整数は、さらに負数を扱うかどうかによって、「符号付き整数(signed integer)」と、「符号なし整数(unsigned intsger)」に分かれます。制御プログラムにおいては、数値としてよりもビットに意味を持たせることが多いので、符号なし整数がよく使われます。

データ型 サイズ 数値の範囲
char(signed char)型 8ビット −128 〜 127
short(signed short int)型 16ビット −32768 〜 32767
long(signed long int)型 32ビット −2147483648 〜 2147483647
unsigned char型 8ビット 0 〜 255
unsigned short(unsigned short int)型 16ビット 0 〜 65535
unsigned long(unsigned long int)型 32ビット 0 〜 4294967295
表3 整数型のバリエーション



コラム(2): ポインタによるメモリ参照

C言語で特定の番地へアクセスするには、ポインタ(pointer)を使います。よく「ポインタはアドレスだ」などという人もいますが、それは決して誤りではありませんが、正確な答えではありません。

C言語のポインタは、参照するデータ型から派生されるデータ型です。ですから、配列を「intの配列」「charの配列」というように、ポインタも「intへのポインタ」「charへのポインタ」というべきです。

図6は「intへのポインタ(int *)」「charへのポインタ(char *)」の意味を図示したものです(intを16ビットとしている)。このようにポインタは、単にメモリのアドレスではなく、参照するメモリ領域の意味を知っているのです。

ポインタとメモリの領域 図6 ポインタとメモリの領域



photo

ここまでちゃんと理解できたかしら健一君?


制御プログラミングって、いろいろ大変なのよ。


photo

そうですね。


でも、C言語の理解にとっても役立つなー。


photo

あら、今回はまだやる気が残っているようね。


そんな健一君のために、また宿題を出してあげるわ。


photo

ゲッ!!


(やはり、そうくるか……)


photo

このワタシとデートしたかったら、今度はしっかり解いておくのよ。


あっ、いけない! ワタシ、今日合コンの約束があるんだった。


じゃ、バイバーイ!!


photo

えーーーっ!!


(ガックリ)



晴子さんからの宿題(2)

SW1を押した回数を、7セグメントLEDに表示するプログラムを作ってね。ただし、カウンタの初期値は「0」よ。それと、「9」の次のカウントで最初の「0」に戻ること!





 実際のH8マイコン制御プログラミングでは、メーカーが用意するヘッダファイルをインクルードすることで、I/Oレジスタを変数のように使うことができます。しかし、本連載では、C言語による制御プログラムの完全理解を目指し、あえてゼロから解説しました。いかがでしたか?

 さて次回は、スイッチ入力プログラムについて、さらに考察してみたいと思います。また、コンパイルの途中で「GCC(GNU Compiler Collection)」のC言語ライブラリが必要になりますので、こちらも併せて解説します。ご期待ください!(次回に続く)


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.