前回のプログラムでは,wait()関数を用いてあまり正確でない遅延を行うプログ ラムを書きました.
今回は,マイコンのタイマ機能を使って,より正確な時間を待つプログラムを作成 します.
H8/3694では,『タイマA』,『タイマV』,『タイマW』の三種類のタイマ機能が 存在します.
今回はその中でもインターバル/時計用のタイマである,『タイマA』を使います.
なお,ブリーフケースに上がっているプログラムとは使い方が若干違いますが,基 本的にはやってることは同じです.
#include <3694.h> /*-----------------------------------------------*/ /* 指定ms待つ関数 */ /*-----------------------------------------------*/ void ms_wait(unsigned int ms) { //====指定msループ==== while(ms--) { //====TMA設定==== TA.TMA.BYTE = 0x1c; //Clear TCA TA.TMA.BYTE = 0x13; //PSS, 入力クロックφ/512 while(TA.TCA < 39); //約1ms待つ. } } /*-----------------------------------------------*/ /* メイン関数 */ /*-----------------------------------------------*/ void main() { IO.PCR5 = 0xff; //Port8をすべて出力に設定. IO.PDR5.BYTE = 0x00; //LED全点灯. ms_wait(3000); //3秒待つ. IO.PDR5.BYTE = 0xff; //LED消灯. }
今回のプログラムでは,特にms_wait()関数が加わった他は分かるかと思います .
この練習プログラムの題材どおり,LEDを始めに点灯させた後,3秒間だけms_wait() 関数を使って待ち,
その後LEDを全消灯にします.
このプログラムではタイマAのインターバル機能を使っています.
本来、正確に一秒待つなどの用途はタイマAの時計用タイムベース機能のほうが適し ているのでしょうが,このプログラムでは,
マイクロマウスで使用するときに使いやすいインターバル機能を用いて解説します .
(とはいえ,今回はそれによる割り込みや出力は行いません.)
余力があれば時計用タイムベース機能についても後述します.
さて,ms_wait()関数の中を見て行きたいと思います.
まず,(引数からもらった数値)回だけwhile構文で中の命令を繰り返すようになっ ています.
つまり,while構文の中に約1[ms]待つようなプログラムが書かれており,それを whileで指定分だけ繰り返すことにより,
指定されたms待つことになります.
whileの中について見ていきます.
まず,最初にタイマカウンタA(TCA)をクリア(値を0に設定)します.
TCAは,リード可能なレジスタであり,直接ライトすることが出来ないので,間接的 にクリアしなくてはなりません.
そこで,ハードウェアマニュアルに書いてあるとおりにタイマモードレジスタA (TMA)を使いクリアします.
TMAの3Bit目(TMA3)~2Bit目(TMA2)をそれぞれ1に設定することにより,TCAはク リアされます.
また,4ビット目がリザーブビットで常に1を返すことから,一応書き込むときも1を 書き込んでおきましょう.
TA.TMA.BYTE = 0x1c;
これにより,TCAはH'00にクリアされるはずです.
次に,タイマAの機能を設定していきたいと思います.
今回は,インターバル動作なので,TCAへの入力源をプリスケーラS(PSS)とし, φ/512としてカウントします.
PSSとは,システムクロック(φ)を入力クロックとする13ビットカウンタで, その出力は周辺モジュールの内部クロックとしてしようされます.
つまり,今回はシステムクロックφ(20MHz)を1/512に分周したクロックをTCAの 入力としてタイマのカウント動作を行います.
さて,それではそのように動作するように設定を行います.設定にはTMAを用います .
まず,今回はTMOW出力は使用しないので,TMAの上位3Bit(TMA7~TMA5)は0にしま す.
4Bit目はリザーブビットなので,1とします.
プリスケーラSを使用するので,3Bit目(TMA3)は0とします.
φ/512をTCAへの入力クロックとするので,2Bit目(TMA2)~0Bit目(TMA0)は B'011となります.
以上をまとめると,次のようになります.
TA.TMA.BYTE = 0x13;
これにより,周波数20/512[MHz]でTCAがカウントされていきます.
さて,では1[ms]待つように少し計算しましょう.
20/512[MHz]を周期に直すと,2.56x10-5[s] = 2.56x10-2[ms]です.
つまり,TCAは2.56x10-2[ms]周期でインクリメントされることになりま す.
そのため,カウントを39回繰り返すと,
2.56x10-2x 39 = 0.9984[ms]
となり,およそ1[ms]とすることが出来ます.
故に,TCAが39になるまで待てば,そこでおよそ1[ms]待つことができます.
while(TA.TCA < 39);
これで,TCAが39になるまで待ち続けることができます.
(設定次第では他の割り込み動作は当然入ります)
タイマモードレジスタA(TMA)
アドレス:H'FFA6
タイマAの動作モードの選択,分周クロック出力,入力クロックの設定を 行います.
TMA7~TMA5:アウトプットセレクト(TMOWからの出力設定)
TMA3:インターナルクロックセレクト(タイマA動作モード選択≒プリスケーラ選択 )
TMA2~TMA0:インターナルクロックセレクト(分周比,またはTCAオーバーフロー周 期選択)
タイマカウンタA(TCA) アドレス:H'FFA7
8Bitのリード可能なアップカウンタです.ライトはできません.
オーバーフロー時に割り込みフラグレジスタ(IRR1)のIRRTAがセット(1になる)さ れます.
オーバーフローすると,TCAは値がH'00に戻り,再びカウントアップされていきます .
TMAのTMA3及びTMA2をセットすることでTCAはH'00にクリアされます.
課題プログラム③ 『LEDをきっちり1秒置きに全点滅させよ』