|
その3は、今日やるつもりなかったんだけど(笑)、ノートPCにワンセグ機能を内蔵しようと思って改造していたら、部品が足りないことに気がついて、今日の改造は諦めました。
では、その3
まず、ソースリストの頭から
DispDataをcharが4文字入るタイプに変更しました。「char[3]」ってなっているけど、1文字目は「char[0]」、2文字目は「char[1]」なので、「char[3]」だと4文字入ります。なぜ4文字にしたかは後ほど…
あとはこのページは前回と変わらないですね。(←ウソ。DIG0〜2の並びをちょこっと修正しています。)
では次のページ
サブルーチン名が「interrupt」というのが増えていますね。これは特殊なサブルーチンで、メインルーチンに呼び出されることはありません。いつ呼び出されるかというと、割り込みが発生した時に呼び出されます。
今回はタイマー割り込みというのを使っていて、ある一定間隔のタイマーを作って自分自身で割り込みを発生しています。
タイマーにもいろいろ種類がありますが、今回はTMR0を使っています。
TMR0タイマーはTMR0というレジスタがあって、クロックがすすむごとにひとつずつカウントアップしていって、レジスタがオーバーフローしたら割り込みが掛かります。
TMR0レジスタは8ビット長のタイマーなので0〜255までカウントアップしていき、その次はオーバーフローするので割り込みが発生して、TMR0レジスタは0にリセットされます。
256回では長い!!という時は、0からスタートではなく、例えばソフトでTMR0に200とかセットすればもっと短い間隔で割り込みが発生します。
さて、その辺の割り込みの設定方法は後回しにして、この割り込みが発生した時になにをやっているか、ソースリストを追っていくと…
割り込みサブルーチンに入って、しょっぱなでINTCONのT0IFをクリア(0をセット)しています。T0IFとはタイマー0割り込みフラグの事です。
割り込みはタイマー0以外にもたくさんあって、それらを1個だけでなく同時に設定することができるので、割り込みサブルーチンの頭で、どの種類の割り込みが発生したかをこのフラグで判別することができますが、今回はタイマー0割り込みしか使っていないので特にチェックする必要はありません。
ただ、このフラグをクリアしておかないと次の割り込みが発生しなくなっちゃいます。そこで割り込みサブルーチンの先頭でクリアしているというわけです。
次はDigitをSelect文で評価していますが、割り込みが掛かるたびにDigitが0だったら100の桁を、Digitが1だったら10の桁を、Digitが2だったら1の桁を7SegLEDに表示するようにしています。
最初に、Digitが0(100の桁を処理したい)だった場合…
・前回の割り込みはDigit2(1の桁)の処理だったのでDigit2の7SegLEDを消灯。
・PORTBへ7SegLED表示データをセット
・Digit0(100の桁)の7SegLEDを点灯
・次はDigit1の処理にしたいのでDigitに1を足す
これを残りのDigit1(10の桁)とDigit2(1の桁)のケースも記述して、これで割り込み処理はおしまいです。
では次にメインルーチン
CMCONの設定の後に割り込み関係の設定をしています。
TMR0関係の設定はほとんどがOPTIONレジスタとINTCONレジスタです。
OPTIONレジスタのT0CSはタイマー0クロックソースを選ぶビットで、1だと外部のクロックを使用し、0だと内部クロックを使用します。
PSAはプリスケーラーの割り当てです。タイマー0で使うプリスケーラーはウオッチドッグタイマーとしても使えるので、今回はタイマー0で使うと宣言しています。
次のPS2〜PS0(次ページにまたがり)はプリスケーラーの設定です。
プリスケーラーとは分周する装置の事で、タイマー0で使用するクロックだと早すぎる場合、そのクロックをTMR0レジスタに適用するときに2倍の遅さ、4倍の遅さ… とクロックを分周してTMR0へ適用(カウントアップ)してくれます。
PS2:0が「000」だとプリスケーラーは2分周、「001」だと4分周、「010」だと8分周… っで、「111」だと256分周してくれます。とりあえず最大の「111」を設定してあとで調整しましょう。
次にINTCON全体をゼロクリアしてから、まずGIEをセットして割り込みを許可しています。割り込みは色んな割り込みがあり、個別に割り込みの許可・拒否(デフォルト)の設定の必要がありますが、この「GIE」でさらに一括して割り込みを許可あるいはマスクすることができます。GIEで一括許可しても、個別の割り込みを許可しなければ、それらの割り込みは発生しません。
次のT0IEはタイマー0割り込みを許可しています。TMR0を使うということですね。
その次のT0IFは先ほども説明しました。タイマー0割り込みフラグをクリアしてタイマー0割り込みが走るようにしています。
最後にTMR0レジスタを0クリアして、割り込み関係の設定は終わりです。
あとはメインルーチンのWhileループを見てみましょう。中を見るとixという変数を1個ずつ足していっているみたいですね。
その前にByteToStr(ix, DispData)というのがありますが、これはバイトタイプをストリング(文字)タイプに変換する関数です。
ixはバイト宣言していますので数字ですが、Disp7SegLEDサブルーチンの中では文字を判定していますので数字を文字に変換する必要がありますが、このByteToStr関数一発でできます。
ixはバイトタイプですから0〜255までですので、文字に変換しても3文字で済んじゃいそうですが、DispDataは4文字で宣言しましたよね? 実は3文字目の後ろに「これで終わりですよ」っていう文字が1文字付加されているので、必要長+1文字の長さの変数が必要になるんです。
なぜわざわざ数字から文字に変換したかというと10の割り算、100の割り算がめんどくさかったということと、あとは「000」の時に「0」とゼロサプレスさせて表示させたかったので、文字タイプにしたということです。
メインルーチンはこれだけ。ダイナミック点灯のめんどくさい処理は割り込みルーチンで勝手にやってくれますから、メインルーチンではひたすら「DispData」に表示したいデータをセットすることだけを考えていればいいわけです。
らくちんですね〜 (^_^)v (ここまでの仕組みを作るのが大変なんですが…)
プリスケーラーが256の時の動き↓
あちゃー、プリスケーラーが256では遅すぎたようですね。
じゃあPS2:0を「011」にセットしてプリスケーラーを一気に16まで減らしてみましょう
うん、ちょうどいいみたいですd(^-^)ネ!
↓は実際のこのプログラムを入れてみて0〜255を繰り返し表示している動きです。
|