プロメモグラム

誰が見てもわかるような文章を目指す

PICでTIMER0を使う(PIC18F25K22 , XC8)

基本的にどのPICでも使用方法は同じであるが、変数名が若干違ったりするので、注意が必要。 結局頑張って使うPICのデータシートを読むしか無いのかな。英語わからないけど……

具体的手順

  • TIMERの設定レジスタに値を代入(TMR0CON)
  • タイマー割り込みを許可
  • 割り込み発生時の関数を定義

以上の順序で設定をしていこう。

TIMERの設定レジスタに値を代入

代入する値の詳細は↓のデータ参照

[cpp] T0CON = 0bxxxxxxxx; [/cpp]

タイマー割り込みを許可

[cpp] TMR0IF = 0; //TIMER0のフラグをリセット TMR0IE = 1; //TIMER0による割り込みを許可 PEIE = 1; //割り込みを許可 GIE = 1; //全体の割り込みを許可 [/cpp]

割り込み発生時の関数を定義

割り込みにはタイマー割り込みだけでなく、SPIやUSARTの送受信等さまざまな割り込みが存在しているが、すべての割り込み時に この関数が呼び出されることになる。 今回は他の割り込みを使用しないのでそのまま処理を書き始めても問題ないが、他に割り込みさせる場合はTMR0IFが 1になっていることを確認するなどの方法で場合分けする必要がある。

[cpp] void interrupt isr(void) { TMR0IF = 0; //TIMER0のフラグをリセット

/* 処理 */

} [/cpp]

その他関係するレジスタ

TMR0レジスタ…このレジスタをサイクルごとにインクメントして、オーバーフローして値が0に戻った時に割り込み が発生している模様。だいたいのPICでは8ビットである(0~255) もし16bitモードにしているのであれば、TMR0HレジスタとTMR0Lレジスタを使用する。 INTCON…割り込みを制御している。PEIEやGIE、TMR0IFで直接ビット指定できるので気にするな。

データ

TMR0CON

bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
TMR0ON T08BIT T0CS T0SE PSA T0PS2 T0PS1 T0PS0
  • TMR0ON…タイマーを有効/無効(有効:1 , 無効:0)
  • T08BIT…1:カウンターの桁数を指定(16bit : 0 , 8bit :1)
  • 8bitだと0~255、16bitだと0~65535までクロックごとにインクリメント
  • T0CS…TIMER0のクロックセレクト。(T0CKI pinを使用:1 , 内部クロックを使用:0)
  • T0CKI pinはRA4です。(PIC18F25K22)
  • T0SE…T0CKIpinにおけるTIMER0の検出方法(立ち下がりエッジ:1 , 立ち上がりエッジ:0)
  • 検出時にカウンターをインクリメントする。立ち上がりエッジはLOWからHIGHに電圧が変化したときにインクリメント。 立ち下がりはその逆。
  • PSA…TIMER0のプリスケーラアサインメントビット
  • プリスケーラとは分周のこと、1/2に分周するなら2回に一度だけエッジを取り出す。 分周することによってより長い時間間隔で割り込みを行えるってはっきり分かんだね。 1 : プリスケーラを使用しない。 0 : プリスケーラを使用する。
  • T0PS…プリスケーラをどの割合で行うか
  • 111:クロックの1/256の周波数。つまり周期が256倍。 110:1/128 101:1/64 100:1/32 011:1/16 010:1/8 001:1/4 000:1/2

追記:任意の秒数で割り込み

8bitなら

[latex] 周期 = クロック周期 cdot プリスケール(分周)値 cdot 2^8 [/latex]

16bitなら

[latex] 周期 = クロック周期 cdot プリスケール(分周)値 cdot mathrm{2}^{16} [/latex]

この式で割り込む周期を求められるが、右辺の2のn乗の部分をTMR0レジスタの初期値を変更することで変えられる。 この数字は0からスタートして256でオーバーフローして割り込みするわけだから、初期化時と割り込みフラグをリセットする前に TMR0レジスタに何か値をいれれば任意にできる。未知数Xとして方程式とけばいいだけ。

せっかくHTMLで書いたのに間違えてビジュアルモードに書いてたからulタグとかめちゃくちゃだよ