H8/3052マイコン実習:入出力実習

[| ]  最終更新: 2011/02/10 20:13:17

概 要

ここではモニタを利用した、H8/3052の入出力機能の実習を行います。

入出力の確認のためには、通常はプログラムを製作し、コンパイルして、書き込むという一連の作業を繰り返しますが、ここでは日立製作所が提供しているフリーソフトウエアの組込型モニタおよびHtermを使用します。 組込型モニタは、ソースのみ公開されているため、秋月電子で販売されているCコンパイラを使って、3052用に調整したものを使用します。

実習内容は以下の通りです。


モニタの起動と操作

H8term
H8term
書込試験で書き込んだモニタと、パソコン側の操作ソフトHtermを使用します。

Htermを起動すると、Consoleウインドウが最初に開きますが、そのままでは通信できないので、一旦、[通信]→[切断]で、閉じます。
次に、[ファイル]→[プロパティ]を開き、通信ポートを使用するポート番号に(H8WriteTurboと同じ)、ビットレートを38400に設定します。
そこで接続を確認の上、H8trainの電源を投入すると、

 H8/3052 Advanced Mode Monitor Ver. 3.0A
 Copyright (C) 2003 Renesas Technology Corp.
と起動メッセージが表示されます(バージョンなどは異なる場合あり)。
なにも表示されない場合は接続や通信設定、電源を、表示されても意味を成さないごちゃごちゃした表示の場合は通信速度などを確認してください。

組込モニタ、Htermは様々な機能をもっていますが、ここではポート入出力機能のみを使います。
次に使用する、単純なポート入出力を例に操作法を示します。

まず、メニューの[表示]→[Peripheral]を選択すると、周辺機能選択ダイアログボックスが表示されます。 ここではそのなかの"I/O"を選択します。 すると、Peripheral-I/Oウインドウが開きます(右図:小さく表示されるので適当な大きさにリサイズしてください)。
左から、レジスタの名前(H8/3052のマニュアルPDFに記載されている制御レジスタ名称、P1DDRなど)、そのメモリ上のアドレス、直前の読み取り値、ビットごとの名称です。 重要なのはレジスタ名とその値です。値は最後になんらかの操作をした時の値で、現在の値をリアルタイムに出力しているわけではありません。
いまの値を確認したい場合は、メニューの[ウィンドウ]→[最新の情報に更新]を選択します。 また、マニュアルにも記述がありますが、現在の設定値そのものが表示されない場合があります。 たとえば、ポートのデータディレクションレジスタ(DDR)は「リードは無効、読み込むと1が読み込まれます」と記載されています。この場合の1とは、各ビットごとに1であって、結果的に画面では"FF"で表示されます。
なお、表示もそれを反映しているようで、ビット単位の確認が可能なものは、表示も2進数で、そのうち無効なビットは'.'で表記されています。

値の変更は、変更したいポートの行の上でマウス左ボタンでダブルクリックします。 すると、レジスタ内容変更のためのダイアログボックスが表示されるので、変更したい値を16進数で入力します。

ここでは、このレジスタ操作でいろいろ試してみます。


汎用ポートの入出力

ここでは、マイコン入出力のもっとも基本である、汎用ポートをつかったディジタルのビット単位の入出力を試します。 H8/3052マニュアルの9章も参照してください。

準 備

ボードを一旦リセットし、モニタを動作状態にして、周辺機能のI/Oを開いてください。

ポートの入力

現状ですべてのポートは入力になっています。
ポート1に端子基板をとりつけ、最新の情報に更新します(メニュー:ウィンドウ→最新の情報に更新)。 このとき、プルアップ型基板を取り付けた場合はP1DRが"11111111"に、プルダウン型を取り付けた場合は"00000000"になります。 ここでは、わかりやすいようにプルダウン型を取り付けます。

P1DRの表示が"00000000"であることを確認し、端子基板上で、"5V"端子とビット0の端子(黒、GND端子と間違わないこと)をクリップ付きコードで接続します。 その上で情報更新すると"00000001"になるはずです。 ならない場合は、接続やプルアップ/ダウンの違いなどを確認します。 もしかすると、接触不良や、組み立て不良があるかもしれないので、部品の交換もしてみます。

5Vと他の端子をつないでみたり、複数のビット端子を"5V"につないでみたりして、それに相当する情報が読み取れるかを確認してください。 また、プルアップアップ型基板に交換して、こんどは"GND"と各端子を接続して、表示がどのようになるかを確認してみてください。 ポート2でも同じようなことを確認してみるといいでしょう。

ここではコードの接続をしましたが、スイッチなどをつければその状態が読めることがわかると思います。 ちなみに、多くのシステムでは、プルアップ+GNDへのスイッチ、という配線を好みます。 その方がいいという明確な理由は見あたりませんが、GNDは基準電位なので、あちこちに存在し、場合によっては信号線だけ持って行けばいいという点、また、電源をひっぱっていって、何かの事故でケースなどに接触した場合に、ケースがアースであると良くないことが起こりえる、そもそもTTLの入出力はHighにするよりLowにするほうが扱いやすいと言ったことなどが関係すると思われます。

ポート出力

上から続けての場合はリセット不要ですが、別のITUなどを触った後はリセットしてください。 また、上で使った端子基板とその上の配線を除去したことを確認してから、進めてください(でないと、出力をショートさせることになります)。

ポート1にLED基板を取り付けます。 まずは、黄色LEDのHigh-active基板を使います。 接続した時点では消灯しているはずです。

つぎにポートを出力に設定します。 P1DDRレジスタでダブルクリックし、値をFFに設定します。 このとき、P1DRの表示が変化することがあります。 これは、P1DRの読込値は、P1DDRの対応ビットが0の場合は外部端子の電圧レベルを呼んできていて、P1DDRを1にすると現在の出力値を示すためです。 P1DDRを操作する前にP1DRが0でないと、表示が0に変わるとおもいます(リセット時にP1DRは初期値0)。

そして、実際の出力値を決めます。 P1DRに"01"を設定します。 Peripheralウインドウの表示は"00000001"に変わり、基板上ではビット0の赤LEDが点灯します。
同様に、"0F"を設定するとビット0〜3の4個が、55を設定するとジグザグのうち一列の0,2,4,6ビットが点灯します。

いろいろな値を設定して(設定前に結果の目標をたてて)みて、LEDの点灯を確認してください。 また、Low-active型の緑LEDの基板と交換して(もしくは上にカスケード接続)、逆のパターン、すなわち画面で0のビットが光り、1のビットが消えることを確認してください。
これまた、一般の回路ではこのLow-active型が好んで使われます。 これはほぼ間違いなく、TTLの出力段の非対称性や、より原始的にはトランジスタでエミッタ接地のスイッチ回路を作ったときに、必然的にこの形になることが原因です。 いまどきのCMOS出力型の素子はそういう非対称性はないので、High-Activeで問題は無いと言えます。

ビットごとの入出力設定

適当な出力をしたままで、P1DDRをたとえば0Fなどに設定してみます。 このとき、下位4ビットは点灯状況はそのままですが、上位は消えます。 これは、DDRの性質通りに、下位が出力のまま、上位が入力になったためです。
※HighとLowのLED基板を重ねて使っていると、両方の基板で、入力ピンが半端に光ります。そのままにしておくと芳しくありません。

このように、H8/3052の場合は端子一本ごとに入出力が決められます。 パソコン用のインタフェース基板などでは8本ごと、などの制約がある場合もよくありますので、仕様に注意しましょう。

ステッピングモータを回してみる

必要ならリセットの上、ポート1を出力に設定して、全ビット0を出力してください。 その上で、ステッピングモータを接続します。

まず、駆動回路とモータを接続します。 駆動回路には抵抗がいくつかとドライブ用の増幅素子(FETモジュール)が搭載されています。 これに、5ピンの端子がついているので、ここにモータのコネクタを接続します。 向きは、素子に近い側にモータの白線がつながるようにします。
※裏をみるとその端子だけ電源につながっています
次いで、駆動回路の電源に12(0.3A)〜24V(0.5A)程度の適当な電源(ACアダプタ)を接続します。
最後に、駆動回路から出ている10芯の線をポート1に接続します。 線の接続方向は、茶色がポートの1端子側、コネクタに対して、ケーブルが外向きに出るようにさします。
※黄色LED基板の上に挿すと、ポート状況が分かりやすくて良い まず、この状態で、モータの軸を指でまわしてみて、ごりごりと周期的な抵抗はあるものの、そこそこ楽に軸が回ることを確認してください。
次に、ポート1に"0000 0001"(値01)を出力します。 出力した瞬間に軸がちょっと動くかもしれません。 軸を指でつまんでみると、軸がある角度に固定され、強力にかたまっていることが感じられます。 相当強く軸をまわすと(やってみるときは怪我しないように注意)、動くもののすぐに止まります。

今度は、"0000 0010"(02)を出力してみます。 軸が見えるかどうかくらいわずかに動いて、またその角度で固定します。 同様に、"0000 0100"(04)、"0000 1000"(08)、そして再び "0000 0001"と変化させてみます。 そのたびにわずかずつ回転します。 値の変更を行う際に、軸を指でつまんでいると、その回り方が感じられます。

ここまでは、
 0001→0010→0100→1000→0001...
と回しましたが、今度は逆に、
 1000→0100→0010→0001→1000...
と指定してみましょう。逆に回りましたか?

さらに、

0011:03
0110:06
1100:0c
1001:09
0001:01
0011:03
0010:02
0110:06
0100:04
1100:0c
1000:08
1001:09
も試して、その違いを確認しましょう。

使い終わったら、駆動回路ははずしておいてください。


アナログ入出力

アナログ出力D/A

D/Aコンバータを利用してアナログ電圧を出力してみます。
H8/3052マニュアルの16章も参照してください。

まず、H8をリセットの上、H8trainのポート7に端子基板(抵抗無し)を取り付けます。 次いで、ディジタルテスタ、DVMなどを端子基板のGND端子とビット6(青)に接続します。

Htermのメニュー、[表示]→[Peripheral]からD/Aを選択すると、Peripheral-D/Aウインドウが開きます。 ここで、DACRの3つのビットに1、すなわちe0を設定します。 あとは、DADR0に適当な8ビットの数値を指定すると、それに応じてテスタの表示が変化します。
端子のビット7からも変換出力は出ていて、DADR1がその電圧を決めます。

いろいろな値を出力してみて、そのときの指定値と電圧の関係を拾ってみてください。 たとえば、00,11,22....FFなど。これを手書き/表計算でグラフ化すると、ほぼ直線になると期待されます。

アナログ入力A/D

次にA/Dコンバータを利用してアナログ電圧を読み取ってみます。
マニュアルの15章も参照してください。

H8trainのポート7に端子基板(抵抗無し)を取り付けます。 これに可変抵抗器を接続します。 可変抵抗器に3つある端子の両端の2端子をそれぞれ端子基板の+5およびGND端子に接続します。 可変抵抗器の中央の端子はビット0(黒)端子に接続します。 また同時に、GND-ビット0間にテスタもつないでおきます。

Htermのメニュー、[表示]→[Peripheral]からA/Dを選択すると、Peripheral-A/Dウインドウが開きます。 ここでは、A/D変換を「0〜3チャネルスキャン変換モード」に設定します。
マニュアル15.4.2節の記述が目的の動作です。 その記述によると

SCAN=1
CH2=0/1  スキャングループを選択、今回は0-3なのでCH2=0
CH1,CH0=11  スキャンの範囲を選択、今回は11
ADST=1
が動作条件と記載されています。 これらの設定は、ADCSRで決定します。 上記条件を設定するには、ADCSRに33を設定します。 なお、ADF,ADIEは変換完了フラグおよび割り込み設定、CKSは変換速度を決めるもので、1にすると倍速になります(が、ここでは見た目かわりません)。

以上の設定で自動的に繰り返し変換が延々と行われます。 変換結果はビット0端子に入力しているので、ADDRAに格納されます。 端子1,2,3に入力した場合は、ADDRB/RC/RDに格納されます。 ただし、それら値は[ウィンドウ]→[最新の情報に更新]をするまで画面に反映されません。

適当な電圧を可変抵抗器で設定して、その値を読み取ってみましょう。
たとえば、2V程度を入力した場合、"6500"などと表示されます。 この値は、16ビットの値で、上位10ビットに変換結果が詰められています。 H8/3052のA/D変換精度は10ビットで、その下に0が6個ついています。

0110 0101 00.. ....  '.'はダミーの0
そこで、これを実際の変換値に直すには、
1:2進数で下に6ビットシフトする
  → .... ..01 1001 0100 (0x194) → 404(d)
2:10進数に直してから、64(=2^6)で割る
  → 26856d → /64, 404(d)
という操作が必要です。
ちなみに2Vを変換する場合、期待値としては、2/5*1024(=2^10)=410でそれらしい値が出ていることが確認できます。

  0V〜5Vを0.5V刻みくらいで与え、そのときの電圧と変換結果をグラフにしてみましょう。ほぼ直線的な結果になると期待されます。


パルス入出力

PWM出力

まずは簡単にパルスを出力してみます。
マニュアルの10章も参照してください。

ITU0を使ってPWM波を出力してみます。
マニュアル10.4.4節にPWM出力のための設定がのっています。 それによると、ITU0のPWM出力はTIOCA0端子で、これはポートAビット2にあたります(共用、ページ1-9)。 10.4.4の説明文を元に、必要な設定を決めます。

TCR, TPSC0/1/2でクロックを決定
TCR, CCLR0/1でクリア要因決定
GRA/GRB に出力が1/0になるタイミングを設定
TMDRのPWMを設定
TSTRのSTRビットを1にする
となります。 それぞれのレジスタは10.2節にありますが、TSTR,TMDRはITU0-4で共通、TCR,GRA,GRBはITUのチャネルごとにあります。
なお、設定には出てきませんが、TCNT0(-4)は実際にカウントされて値が変化するレジスタです。

以上をふまえて、実際に操作します。まず、リセットして、端子基板をポートAに取り付け、端子GNDとビット2端子(赤)をオシロスコープに接続します。
Htermで、メニューの[表示]→[Peripheral]から"ITU"と"ITU0"の二つを開きます。 そのレジスタに対して以下の設定を行います。

ITU0:TCR 0x40(0b.1000000)
   TPSC2/1/0: 000  内部クロック(25MHz)でカウント
   CCLR1/0: 10   TCNT=GRBでクリア:GRBが0になる立ち下がりタイミングを決定
      CKEG1/0: 今回使わず、デフォルトの0のまま
ITU0:GRA: 0x7000  1になるタイミング
ITU0:GRB: 0x8000 0になるタイミング(+クリア=周期決定)

ITU:TMDR: 0x01   ITU0がPWM
ITU:TSTR: 0x01   ITU0がカウント動作
以上の設定をして、ポートAのビット2をオシロスコープで確認します。
(電圧レンジ2V/div程度、時間500us/div程度)
正しく設定できている場合、おおむね、760[Hz]、パルスのデューティ比(周期にしめるOnの時間比率)が1/8程度になっています。 また、最新の情報に更新するたび、ITU0のTCNTが0-0x8000の範囲でランダムに変化して見えます(規則正しく変化してても更新した時刻が適当なのでランダム)。
なお、760Hzは25MHz(25000000)を0x8000(32768)で割った値、約763から来ています。 また、デューティ比1/8は、TCNTが0からカウントアップしていき、0x7000に達した時点でGRAと一致して出力が1になり、0x8000に達した時点でGRBと一致して、出力を0にするとともに、TCNTをクリア、という動作によっています。
つまり、GRAはOffの幅を規定するようになっています。

以上をふまえて、GRAを0-0x8000の範囲で適当に変更し、デューティ比が変わることを、また、GRBを変化させると周期がかわることを確認してください(ただしGRA<GRBを守ること、大小が逆になると出力が1にならなくなります)。

パルス幅計測

次にパルス幅の計測を試みます。

これには、ITUのインプットキャプチャ機能を用います。 インプットキャプチャは、ITU0-4に対応するTIOCA/B端子が立ち上がり/立ち下がりしたときに、そのときのTCNTをGRA/GRBに保存する機能です。 これによって、立ち上がり、立ち下がりのタイミングをTCNTのカウント値で知ることができます。 さらに、これとタイマクリアを組み合わせます。

具体的には、GRAでパルス周期を、GRBでONの幅を計るようにします。 GRAがパルスの周期になるように、GRAのインプットキャプチャでクリアします。 また、GRBがパルスの幅になるようにするには、たとえば、GRAでクリアするときがパルスの立ち上がり、GRBがパルスの立ち下がりを拾うようにすれば、目的がかないます。 よって、GRAの条件はパルス立ち上がり、GRBは立ち下がりになります。

上で作ったPWMの幅を測定してみます。
まず、以下の設定をします。

ITU1:TIOR: 0x54   0b0101 0100
    IOB2/1/0:101  GRBには立ち下がりの値を記録
  IOA2/1/0:100  GRAには立ち上がりの値を記録
ITU1:TCR:  0x20   0b0100 0000
  CCLR1/0:01  GRA要因でクリア:TCNTは立ち上がりでクリア
  TPSC2/1/0:000  25MHzカウント

ITU:TSTR:0x03  (ITU0+ITU1)
その上で、先ほどのITU0の出力、ポートAのビット2をTIOCA1/CB1である、ビット4,5に接続します(2本とも接続しないと動作しません)。 うまくいけば、ITU1のGRAにはパルス幅(上の数値で言えば0x8000)、GRBにはパルスのOnの幅(ITU0のGRB-GRA)近辺の値が表示されます。
(計測のタイミングの違いで、若干値が異なる)

ここでは、自前のパルスの幅を測定しましたが、ファンクションジェネレータの出力なども、もちろん測定できます。 出力が0〜5Vの波形になっていることをオシロなどで十分確認して、念のため、10キロ程度の抵抗を挟んで接続してみましょう。

パルス数計測

実は、一番単純なITUの使い方です。 ITUは何の設定もしなければ、ただのカウンタになります。

ITU2で実際に試してみましょう。

ITU2:TCR:0x04
  CCLR1/0: 00  クリア無し
  CKEG1/0: 00  立ち下がりエッジカウント
  TPSC2/1/0: 100  外部クロックTCLKA(ポートAのビット0)でカウント
ITU:TSTR: 0x07 (ITU0+1+2)
この設定のうえで、最新の情報でITU2のTCNTをみつつ、ポートAのビット0につけた線を適宜電源にふれてみたり(プルアップ型はGNDに、プルダウン型なら+5に)、ITU0出力、すなわちポートAのビット0に触れてみるとよいでしょう。 上記設定のままなら、5秒ちょっとで約4千増えます。16進数でいったら、1000くらいです。(チャタリングを拾うこともある)
なお、カウンタのクリアはTCNTに直接0等を設定すればクリアになります。

応用としては、ぴったり1msくらいの周期を一つのITUでつくり、これをパルス計測のITUのTIOCAに入力し、インプットキャプチャ、クリアをしかけます。 このITUのクロックをTCLKAなどの外部クロックにしてやると、1msの間にTCLKがどれだけ入ったかが分かります。 これはすなわち周波数をkHz単位でみたものになります。 よって、周波数カウントもできることになります。


センサをつないでみる

温度センサ

温度センサで有名なものに、LM35というセンサがあります。
これは、温度1度あたり10mV(0度で0V)を出力するという、非常に扱いやすいセンサです。ちょっと工夫するとマイナスの温度も測れます。 このままだと感度がちょっと寂しいので、適当に抵抗をつないで、感度を約2.1倍にして、H8trainで試せるようにしてみました。

センサモジュールから出ている線には、ステレオジャックを経由して、H8trainに直接接続できるコネクタがついています。 このコネクタをA/D変換のための、P7に接続します。 向きは、線が基板から外を向くように(線の茶色側が1の表示の側にくるように)接続します。

あとは、先ほどのA/Dの表示状態にして、最新情報に更新(ALT+W→R)しながら、指で握ってみたり、お湯や冷水につけてみてください。 温度計があれば、その値と比較して、電子温度計として使えるか、確認してみましょう。

なお、A/Dだけでは不安な場合は端子基板を併用してディジタルテスタを並列に。

距離センサ

最近、ロボットコンテストのロボットなどに多用されるようになってきたものに、PSDという素子を用いた距離センサモジュールがあります。 これは、5V程度を供給すると、距離に応じた電圧が出力されるというありがたいセンサです。ものまでの距離というのは、自分で計ろうとするとなかなか難儀なので、とても助かります。
これを試してみましょう。

センサモジュールから出ている線には、ステレオジャックを経由して、H8trainに直接接続できるコネクタがついています。 このコネクタをA/D変換のための、P7に接続します。 向きは、線が基板から外を向くように(線の茶色側が1の表示の側にくるように)接続します。

あとは、先ほどのA/Dの表示状態にして、最新情報に更新(ALT+W→R)しながら、センサのまえの適当な位置に手をかざすなり、長めの定規と適当な障害物で、距離とA/D変換値の関係を調べてみると良いでしょう。 15cm〜50cm程度でそこそこ実用的です。

なお、A/Dだけでは不安な場合は端子基板を併用してディジタルテスタを並列に。

加速度センサ

最近はいろいろなものに加速度センサが使われています。
直接加速度を使うものとしては、自動車のエアバッグや、ABS、トラクションコントロールといった車の加速度が必要な用途があります。
間接的には、加速度のなかでも実は一番ポピュラーな重力加速度を測定することでロボットの姿勢角度を求めることにも使われます。 重力加速度は地球上では真下向きに必ず存在する加速度で、加速度センサでその方向を調べるわけです。振り子式の傾斜計、水準器なども、最終的にはこの重力加速度の方向を見ているものです。

そのような加速度センサを用意してみました。
アナログデバイセズのADXL202という比較的有名なセンサで、±2G(重力加速度の2倍)の範囲を測定できます。 測定結果は珍しいことにパルスのデューティ比で出力されます。
そこで、ITUを使って計ってみましょう。

センサは配線済みで、H8trainのコネクタに直結できるようにしてあります。 これをポートBに接続することで、ITU3,4の入力、TIOCA3/B3, A4/B4に接続されます。 ADXLは縦横2方向の加速度を検出できます。
上の例を応用して、ITU3,4をパルス幅計測に設定してください。

センサを傾けてみて、そのときのITU3,4のGRBの値を確認してみてください。 通常動作では、GRAはおおむねD200台を示しています。 なお、端子基板を間に挟んで、そこにオシロをつないでみると、加速度に連動してパルス幅が変わる様子が良く分かります。
使用上の注意としては、衝撃に弱いセンサなので(このICの中に細い立体構造がある)、机にぶつけたりしないように気をつけてください。



熊谷正朗 [→連絡]
東北学院大学 工学部 機械知能工学科 RDE
[| ]