FC2カウンター

現在の訪問者数

現在の閲覧者数:

カレンダー

04 | 2009/05 | 06
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 - - - - - -

プロフィール

剣菱P

Author:剣菱P
剣菱Pと申します。
性別:男
年齢:27
二兎を追って一兎も得られないタイプ

マイコンやプログラミング、ニコニコ動画、雑記等
方向性は見えずとも、ちょっとずつ更新していく予定です!

リンクフリーです。
こんなブログでよかったらよろしくお願いしま~す。

公開メール kenbishiP@gmail.com

検索フォーム

最新記事

最新コメント

カテゴリ

メールフォーム

名前:
メール:
件名:
本文:

月別アーカイブ

最新トラックバック

リンク

ブロとも一覧

ブロとも申請フォーム

ランキング

ランキング参加中です。気が向いたらクリックしてあげてください。


にほんブログ村 その他趣味ブログへ
にほんブログ村 その他趣味ブログ 趣味の工作へ

スポンサーサイト


上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


PIC タイマー0 割り込み


前回 タイマー0の基本的な設定を話したので、
具体的な使い方を

タイマー0はインターバルタイマーとして使用されることが多いようです。
つまり時間を決めて周期的に何かさせたい時などに使うようですね。

以前 delay関数を使ってLEDを周期的に点滅させました。
LEDを点滅させることが目的ならばdelay関数で十分かもしれませんが、
実際はもっといろいろとやりたいことがあるはずです。

delay関数は関数なので当然CPUを使って処理を行うため、時間を数えるのに精一杯で、数えている間は他のことが出来ません。
それに対し、タイマー0は独立した装置なのでCPUの処理とは別のバックヤードで数を数えさせることが出来るのです。

delay関数の場合
CPU「1,2,3・・・・」
他の仕事「あの・・・ ちょっとこっちの作業やっといてくれますか?」
CPU「5,6・・・ あ? うっせーぞ、今数数えてんだよ! 数え間違えちまうじゃねーか!」

ま、実際CPUが仕事を断ったりはしませんけどねwww

タイマー0の場合

タイマ「1,2,3,・・・」
仕事「CPUさん これお願いします。」
CPU「おk やっときます」
タイマ「99、100 CPUさん100数えましたよ」
CPU「お、ありがと じゃあちょっと別の仕事するか。」
CPU「よし、おわり。タイマ君また100数えておいて、それまでこっちの仕事やっとくから」
タイマ「了解です」


今の会話でタイマ君が100数えたことをCPUに報告に来ました。
これを割り込みといいます。
数を数え終わった時に報告しに来るわけですが、どのようにして数を数え終わったことを判断するのでしょう。

まず、前に言ったとおり、タイマー0は8ビットタイマなので0~255までしか数を数えられません。
 00000000
 00000001
 00000010
 00000011
    ・
    ・
    ・
 11111110
 11111111
00000000
となるのですが、はみ出た9個目の数は認識不能なのでタイマーから見ると255の次に0になったように見えます。
この255から0になった瞬間が実は数を数え終わったとみなす瞬間、つまり割り込みをかける瞬間なのです。 ちなみにこのオーバーフローした一桁にも使い道があります。この9桁目を監視して、この桁が1になった瞬間に割り込みが発生したとみなせるわけです。
「8桁しかないのにどうやって9桁目を監視するんだ?」
9桁目だけ特別に他の名前で存在しているのです。あとで出てきます。

前回タイマー0に関係するレジスタには
・OPTION_REG
・INTCON
・TMR0


があるといいましたが、OPTIONレジスタしか説明しませんでした。

INTCONレジスタは割り込みのための設定をするレジスタです。
割り込みはタイマー0だけでなく他にもかけて来るやつがいます。それらの割り込みを許可するかどうかこのINTCONレジスタで設定します。ここで割り込みの許可を出さないと、CPUさんは相手にしてくれません。







76543210
GIEEEIET0IEINTERBIET0IFINTFRBIF


GIE:これは全体の割り込みを許可するビットです。
    割り込みにはさまざまな要因がありますが、このGIEが全体の割り込みの許可/禁止を仕切っています。
    よってここを許可してやらないと割り込みがかかりません。
    0で禁止
    1で許可

T0IE:タイマー0の割り込み許可です。
     GIEは全体の許可で、さらに格割り込み要素にも別個で許可を与えなくてはなりません。
     タイマー0の割り込み許可はこのT0IEです。

T0IF:タイマー0の割り込みフラグ
     割り込みが発生したことをCPUに知らせるためのビットです。
     割り込みが発生すると自動的に1になります。
     タイマー0は255数えると次に0になりますが、この時、桁があふれ出し(オーバーフロー)9ビット目が1になっていました。
     このT0IFはつまりこの9ビット目なのです。オーバーフローする瞬間に1になります。
     1になっていると割り込み発生とみなされるので、一度割り込みが発生した後は自分で0を
     書き込んであげないと、次に数を数える前にまた割り込みになってしまいます。


TMR0レジスタは実は特に説明することもありません。このレジスタが数を数えている本体だからです。ここに今数えている数が入っています。


さて、では早速プログラム


#include <pic.h>
__CONFIG(HS & WDTDIS & PWRTDIS & UNPROTECT);

unsigned int counter = 0;

void main(){
   TRISA = 0x00;
   TRISB = 0x00;
   PORTA = 0x00;
   PORTB = 0x00;

   T0CS = 0;             //内部クロック選択
   PSA = 0;              //プリスケーラ使用
   PS2 = 1;              //111なので 1:256
   PS1 = 1;
   PS0 = 1;
   TMR0 = 0x3c;           //タイマーセット
   T0IF = 0;               //タイマー0割り込みフラグクリア

   T0IE = 1;              //タイマー0割り込み許可
   GIE = 1;               //全体割り込み許可

 
   while(1);
}

interrupt timer0()
{
   T0IF = 0;               //タイマー0割り込みフラグクリア
   TMR0 = 0x3c;             //タイマー再セット

   if((++counter)==100){
      PORTB = ~PORTB;         //ポートB反転
      counter = 0;

   }
}


pic_timer0-2.jpg
ちなみにこんな感じです↑

はじめの数行は前回説明したところを具体的にプログラムで書いたものです。コメントにあるとおりです。
クロックの選択、プリスケーラを使用するか、プリスケーラはいくつにするか。これらを設定した後、
何クロックカウントするかを設定し、割り込みフラグをクリアして、割り込みを許可すればおkです。

今回は1秒ごとにLEDを点滅させるプログラムにしてみました。
つまりタイマーで1秒を計らなければなりません。しかし、20MHzのクロックで動かしているため
プリスケーラを256にしても最長で13mSくらいしか数えられません。
そこで、タイマーで10mSを数えこれを100実行した時にLEDの値を反転させることにしました。

では、10mSを計測するにはどうすればいいでしょうか。
まず10mSを計るためにクロックの波を何回数えればいいかを考えます。

20MHzの4分の1のクロックを使用するので5MHz
一つの波の周期は1/5000000 = 200[nS]
10mSの間に200nSが何回はいるかを数えればいいので

(10*10^-3) / (200*10^-9) = 50000
50000回波を数えれば10mSの時間が稼げることになります。
ですが、何度も言うようにタイマー0は8ビットタイマーなので256しか数えられません。
ここでプリスケーラーを使って数えられる数を増やしてやります。
256にかけて50000を上回れるプリスケール値は256だけです。それ以下では足りません。
プリスケーラで256倍してやれば256×256=65536回分の波がカウントできることになります。
ただし、これは元のクロックの65536分の長さを計れるというだけで、実際には256カウントしか出来ません。つまり例えば、100回分の長さというものを正確に出すことは出来ません。
256、512、768という風に256刻みでしかカウントできないのです。
「いち、にい、さん」と数えていたのを
「いーーーーーーーーーーーーーーーーーーち、にーーーーーーーーーーーーーーーーーい、さーーーーーーーーーーーーーーーーーーん」と数えているに過ぎません。


ま、ともかくプリスケーラの設定は終わりました。
次にタイマーに設定する値を割り出します。必要なのは50000カウント、実際には256刻みにカウントするので、何回カウントすれば言いかといえば
50000 ÷ 256 = 195.3 ≒ 195
195カウントすれば10mSの時間を稼げることがわかりました。が、
ここで一つ重症なことが、

タイマー0はアップカウントしか出来ないのです。
つまりTMR0レジスタに入れた値から1つずつ値が増えていくのです。
一つずつ増えていき255まで増えた、その次に0に戻って割り込みが発生するのです。
つまり、例えば100数えたければTMR0には155を入れなくてはなりません。
155からカウントを開始して255まで数えると100になるのです。

今回は195カウントなので
255-195= 60
60を16進数にすると0x3C。よってTMR0レジスタには0x3Cを入れます。

次にT0IF = 0;で割り込みフラグをクリアします。これが1になっているとカウント終了とみなされて割り込みが発生します。
そして、TOIEとGIEの割り込み許可を行えば完成です。
あとはwhile(1)で無限ループ待機です。他に仕事があれば、ここにそれを書きます。

無限ループを回っている間もカウンターはせっせと数えていますそして195カウントしたところで
オーバーフローを起こし割り込みフラグT0IFが1になります。この瞬間割り込みが発生します。

その割り込みの内容は
つぎのinterrupt timer0関数内に記述してあります。
PIC C Liteでは割り込み関数はinterruptをつけて表現します。関数名自体は自分でつけてかまいません。
ここで一つ注意しなければならないのがPIC C Liteでは割り込み関数は一つしか記述できないということです。interruptは一つしかつけられません。でも割り込み要因はタイマー0以外にもあります。
その時はどうすればいいかというと、割り込み関数の中でどの割り込みフラグが立っているかを確認すればおkです。こんかいはタイマー0しか使ってないのでそこらへんは無視します。

さて、ではこの関数内でなにを記述したかというと
まずはT0IF = 0;で フラグを元に戻します。これをしないとまたすぐにここに戻ってきてしまいます。
次にTMR0 = 0x3C;でタイマー0の値を再セットします。タイマーはオーバーフローして0に戻ってしまったのでまた値を入れなおさなければなりません。

そしてcounterという変数を用意して割り込みが入った回数を数えます。100回割り込みが入ったところでポートBの値を反転します。
こうすることで10mS×100=1SでLEDが点滅します。

これが具体的なタイマー0の使用例です。



クリックお願いします



スポンサーサイト


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。