PIC12F683でウォッチドックタイマ(WDT)を使う方法をまとめました。
そもそもWDTって?何のためにあるのか
ウォッチドックタイマ(WDT)は、一定時間経過したら、リセット処理をする動作をします。
マイコンが通常に動作しているときには、WDTによって勝手にリセットされては困るので、WDTがタイムアウトするより前に、WDTが時間を計時しているカウンタをクリアして、WDTによるリセットがかからないようにします。
カウンタがクリアされても、WDTはまた計時のためにカウントを開始するので、WDTがタイムアウトするより前に、再びカウンタをクリアする必要があります。そして、これを延々と繰り返すことになります。
こんな面倒なことを、なぜするのか?というと、マイコンがどっかの処理にハマり込んだりして、抜けられなくなったようなとき(つまり異常時)に、自動でリセット(再起動)するためです。
マイコンが、何かの処理に異常に時間がかかったり、無限ループにはまり込んだりした場合、WDTのカウンタをクリアすることが出来ず、WDTによるリセットがかかります。この場合、マイコンは初期状態からやり直すことができます。
正直、こんなことが起こるのはマズイので、それで良しとするのか?という問題もありますが、フリーズして全く反応なし。みたいな状態よりはマシ。という発想のものです。
WDTを使うための3ステップ
PIC12F683でWDTを使うためには、以下のように設定していきます。
- WDTを有効にする
- タイムアウトになるまでの時間を設定する
- 定期的に(タイムアウトになる前に)クリア処理をする
Step1:WDTを有効にする
WDTを有効にする方法は2つあります。
- コンフィグレーションでWDTをONにする
- 「WDTCON」レジスタのSWDTEN(0bit目)を"1"(ON)にする
両者の違いは、コンフィグレーションでWDTを有効とした場合は、プログラムから途中でWDTを無効とすることはできません。しかし、「WDTCON」のSWTDENでWDTを有効にした場合は、SWTDENに"0"を書き込むことで、プログラムからWDTを無効にすることができます。
Step2:タイムアウトになるまでの時間を設定する
タイムアウトになるまでの時間は、「WDTCON」レジスタと「OPTION_REG」によって設定します。
WDTは、31kHzの内蔵クロックで動作して、勝手にカウントアップしていきます。そのため、31kHzの逆数である32.258usごとにカウンタをカウントアップしていきます。
このカウントを、WDT用のプリスケーラに入力していき、溢れたらリセットがかかります。そのため、プリスケーラの大きさが、タイムアウトになるまでの時間の長さになります。
WDT用プリスケーラの設定は、「WDTCON」レジスタのWDTPS<3:0>で設定します。
WDT用プリスケーラの最大値は65536で、その時のWDTのタイムアウト時間は2.114秒です。この値でも足りないときは、「OPTION_REG」で更にプリスケーラを追加することができます。
ただし、この追加のプリスケーラは、タイマー0と共用のものなので、このプリスケーラをWDTに割り当てた場合、タイマー0ではプリスケーラを使用することはできなくなります。
2段目のプリスケーラの設定は、「OPTION_REG」のPSAとPS<2:0>で設定します。
PSAを"1"にすると、共用プリスケーラはWDTに割り当てられます。プリスケーラの大きさは、PS<2:0>で選択します。
Step3:定期的に(タイムアウトになる前に)クリア処理をする
WDTがタイムアウトしてリセットがかかる前に、WDTカウンタをクリア処理をします。クリア処理は、xc.hに「CLRWDT()」というマクロが用意されています。
CLRWDT()をメインループ内において、メインループが一周するたびにWDTカウンタのクリアを実行するのが常套手段です。
WDT設定の例(タイムアウト時間:2.11s)
#include <xc.h> #pragma config WDTE = ON //WDT有効 WDTCON = 0x17; // 0001_0111 プリスケーラ65536, WDT:2.11sくらい OPTION_REG = 0xF7; // 1111_0111 プリスケーラはTMR0に使う(1:256) while(1){ //メインループ /* 他の処理 */ CLRWDT(); //WDTクリア }
0 件のコメント:
コメントを投稿