前回、液晶に2つのメッセージを交互に表示するテストプログラムを作成しました。
動作は前回と全く同じで、簡単です。
しかし、ソフト的には全く異なり、複雑になっています。
前回は、実行時間のほとんどをディレールーチンが使っていたので、この間、他の事は何も出来ませんでした。
今回、新たにタイマールーチンを作成し、メインルーチンから複数のタイマーをスタートさせ、タイムアップを
チェックする構造にしました。
初期化が済めば、メインルーチンは1mS以内で回りますので、他の処理を追加する事が出来ます。
左は今回のプロジェクトの内容です。
動作は前回と全く同じです。
ソースファイルが2つ増えています。
今回は、タイマー1とCCP1を組み合わせ、CCP1でタイマー割り込みを発生します。
ファームウエアのダウンロード (ZIP圧縮されています。)
コンパイラのバージョンにより、プロジェクトに若干の変更が必要になります。
タイマー関係の定数、変数、関数の宣言が追加されています。
前回と同じです。
表示時間はタイマーで設定するので、この関数は使用しなくなりましたが、液晶の初期化等でまだ使用しています。
前回と全く同じです。
今回、メイン関数は複雑になりました。
液晶表示のタイミングを8つのステートに分け、順次、次のステートに移り、リング状に進みます。
特定のステートでタイマーをスタートさせ、次のステートに移ってタイムアップをチェックし、タイムアップで
さらに次のステートに移ります。
タイムアップしなければ、ステートはそのままで、メインルーチンは何もしないで回ります。
メインルーチンが時間待ちで止まることはありません。
従って、メインルーチンに他の処理を追加する事が出来ます。
追加した他の処理も液晶表示と同様、時間待ち等で止まらない構造にします。
前回と同じです。
最新のバージョン(現時点でVet3.31)ではスクリプトファイルの名前が 18f1320_g.lkr に
変わっています。
今回、追加したものです。
タイマー1とCCP1を組み合わせ、正確な1mS割り込みを発生します。(この回路ではクロックが内部発振
ですので、正確ではありませんが。)
割り込み関数内で16ビットカウンタをインクリメントします。
従って、このタイマー単独では最大で約1分となります。
尚、割り込み関連の記述は、ここでは無く、interrupt.c の中で記述されています。
ここでは、タイマーの初期化、スタート、キャンセル、チェック等のサービス関数を記述しています。
タイマーはRAMの許す限り、何個でも指定できます。
各々のタイマーは設定値とスタート時のカウンタの値を保持しています。
メインルーチンで特定のタイマーをスタートさせ、ポーリングでタイムアップをチェックします。
今回、追加したものです。
割り込み関連を記述しています。
C18の場合、複数の割り込み要因でも、割り込み関数は一つで、関数内で要因別フラグをチェックして処理
を分岐します。
一般のCのように個別の割り込み関数が書ければ、timer.c の中に記述したいところです。
処理に入ったら、最初に割り込みフラグをクリアしないといけません。
これを忘れると、永久に割り込みを繰り返すので、そこで止まってしまうように見えます。
CPUによっては、割り込みに入ったという条件で、フラグを自動クリアしてくれるものもあったと思いますが。
今回の場合、割り込み要因はタイマー1ではなく、CCP1です。
タイマーとCCPを組み合わさなければならないので面倒です。
今回、タイマーの基準時間(1mS)を作る為に、CCP割り込みを使用しました。
この時、コンペアモードにspecial event トリガを使用しています。
このモードではタイマーカウントと比較値が一致したとき、タイマーを自動でクリアしてくれます。
従って、誤差の無い、割り込み時間を作る事が出来ます。
ただし、同時にA/D変換器のスタートビットを立ててしまう事がわかりました。
今まで、主にPIC16F876を使用していましたが、28PIN以上のPICは殆ど、CCPを2つ持っていて
、
CCP1側を使えば、A/D変換はスタートしないので、気にしていませんでした。
PIC18F1320はCCPが一つしかなく、A/D変換も同時にスタートしてしまうようです。
次の次の頁(PIC18Fを使う(4))で温度を測定する為にA/D変換を使用しています。
この時、ソフトウエアでA/D変換をスタートさせていますが、1mSの割り込み時にハードウエアでもスタートが
掛かっていることになります。
この例では、動作に支障が無く、製作した、換気扇コントローラもトラブルなく動作しています。
ただし、大半のA/D変換が空打ちになっているので、気に入らない人もいるかもしれません。
(ハードウエアが勝手に動いているだけで、ソフトの処理時間は増えませんが)
その場合、
1 CCPトリガを単純なソフトウエアトリガに変える。
この場合、タイマーは0−FFFFまでフリーランニングしているので、比較値を毎回、書き直すことになります。
割り込みルーチンの最初で、CCPの値を読み出し、タイマー時間分のカウント数を加算して書き戻します。
オーバーフローしても、残りの数値が次回の比較値になるので、そのままで、問題ありません。
割り込んだ時のCCPの値と、読み出した時のCCPの値が同じかどうか、わかりませんが、もし異なるのであれば
加算値を調整します。
シミュレータのストップウオッチ機能で時間の確認をすれば良いと思います。
2 CCP割り込みを使わず、タイマー割り込みにする。
この場合は、割り込みルーチンの最初で、タイマーの初期値を書き込みます。
若干の無駄時間が発生するので、初期値を調整します。
3 A/D変換のスタートを割り込みに任せる。
現在、通常のルーチンと割り込みの両方から、A/Dの起動が掛かっていますが、通常のルーチン側ででA/Dを起動しない
構造とします。
4 28ピン以上のPICを使用する。
この場合、CCPが2つあって、CCP2だけがA/Dを起動します。
従って、CCP1を使えば良いと思います。
以上、気になる人は変更してみてください。
尚、A/D変換を使わない場合は、考慮しなくても良いです。
PICのタイマーは機能が低く、CCPと組み合わせて使用しますが、例えばH8等ではタイマー自体に、比較用のレジスタ
が2組〜4組あるので、タイマーだけで、柔軟な処理が出来ます。
2009年10月10日 追記
私が使用した環境はMPLAB Ver7.60 C18 Ver3.11(評価版)です。
新しいC18 Ver3.31ではリンク時にエラーが発生しました。
電子回路 > PIC18Fを使う > C18のバージョン を読んでください。