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