トップページ     電子回路のページのトップ

 PIC18Fを使う(2)


 今回の内容

 前回、液晶に2つのメッセージを交互に表示するテストプログラムを作成しました。
 動作は前回と全く同じで、簡単です。
 しかし、ソフト的には全く異なり、複雑になっています。
 前回は、実行時間のほとんどをディレールーチンが使っていたので、この間、他の事は何も出来ませんでした。
 今回、新たにタイマールーチンを作成し、メインルーチンから複数のタイマーをスタートさせ、タイムアップを チェックする構造にしました。
 初期化が済めば、メインルーチンは1mS以内で回りますので、他の処理を追加する事が出来ます。

テストプログラム

プロジェクト

 左は今回のプロジェクトの内容です。
 動作は前回と全く同じです。
 ソースファイルが2つ増えています。
 今回は、タイマー1とCCP1を組み合わせ、CCP1でタイマー割り込みを発生します。

   ファームウエアのダウンロード (ZIP圧縮されています。)

コンパイラのバージョンにより、プロジェクトに若干の変更が必要になります。


global.h

 タイマー関係の定数、変数、関数の宣言が追加されています。


cnf1320.c

 前回と同じです。


delay.c

 表示時間はタイマーで設定するので、この関数は使用しなくなりましたが、液晶の初期化等でまだ使用しています。


lcdlib4l.c

 前回と全く同じです。


main.c

 今回、メイン関数は複雑になりました。
 液晶表示のタイミングを8つのステートに分け、順次、次のステートに移り、リング状に進みます。
 特定のステートでタイマーをスタートさせ、次のステートに移ってタイムアップをチェックし、タイムアップで さらに次のステートに移ります。
 タイムアップしなければ、ステートはそのままで、メインルーチンは何もしないで回ります。
 メインルーチンが時間待ちで止まることはありません。
 従って、メインルーチンに他の処理を追加する事が出来ます。
 追加した他の処理も液晶表示と同様、時間待ち等で止まらない構造にします。


18f1320i.lkr

 前回と同じです。
 最新のバージョン(現時点でVet3.31)ではスクリプトファイルの名前が 18f1320_g.lkr に 変わっています。


timer.c

 今回、追加したものです。
 タイマー1とCCP1を組み合わせ、正確な1mS割り込みを発生します。(この回路ではクロックが内部発振 ですので、正確ではありませんが。)
 割り込み関数内で16ビットカウンタをインクリメントします。
 従って、このタイマー単独では最大で約1分となります。
 尚、割り込み関連の記述は、ここでは無く、interrupt.c の中で記述されています。
 ここでは、タイマーの初期化、スタート、キャンセル、チェック等のサービス関数を記述しています。
 タイマーはRAMの許す限り、何個でも指定できます。
 各々のタイマーは設定値とスタート時のカウンタの値を保持しています。
 メインルーチンで特定のタイマーをスタートさせ、ポーリングでタイムアップをチェックします。

interrupt.c

 今回、追加したものです。
 割り込み関連を記述しています。
 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のバージョン を読んでください。


トップページ  「電子回路」のトップ