TOPMPLAB C18編(PIC18F1320)> LEDを点滅させる(TMR0割り込み)

LEDを点滅させる

−TMR0割り込み−(C18)
(PIC18F1320)

更新日2009.3.28

前のページと同様0.5秒毎にLEDを点滅させますが、待ち時間はTMR0割込みにより作ります。

実験回路
・・
今回の実験回路は前のページと同じです。
クロックは内部クロックを使い8MHz動作としました。

LEDと直列の抵抗は、300〜800Ω程度の範囲であれば明るさが変わるだけで点滅の確認はできます。

内部クロックを使いますのでOSC(15,16番)ピンは使いません。

また、MCLRを無効にしてMCLR(4番)ピンも使わない設定にしました。

ブレッドボードに組んだ状態
右のピンヘッダ周りは、回路図には有りませんがICSP(In-Circuit Serial Programming)用です。秋月のPICライタなどを使う場合は不要です。

プログラム

今回のプログラムはこちらです。

2つのLEDを0.5秒毎に交互に点滅させるもので、0.5秒の時間はTMR0割込みにより作成します。
TMR0は8ビットモードとしました。
プログラムの構造は、導入編の基本3パターンの中の、PIC16互換割込みを使うパターンをベースにしています。

今回のプログラムのポイントであるTMR0割込みについて以下に説明します。

TMR0割込みルーチンの定義
このプログラムのTMR0割込みに関する部分を抜き出すと、以下のようになっています。

void timer_isr (void);         // (1)

#pragma code low_vector=0x8    // (2)
void low_interrupt (void) {
    _asm
        GOTO timer_isr
    _endasm
}
#pragma code

#pragma interruptlow timer_isr // (3)
void timer_isr (void) {
    INTCONbits.TMR0IF = 0;
    // TMR0割込み処理      // (4)
}
			
(1) TMR0割込みルーチンの名前を定義
(2) 割込みベクタ「0x8」を定義し、アセンブラのGOTO命令でTMR0割込みルーチンに飛ばす
(3) TMR0割込みルーチンの定義
(4) ここにTMR0割込み発生時の処理を記述する
TMR0割込みで使うレジスタ
レジスタ用途など
TMR0L8ビットのカウンタで、1命令サイクル毎にカウントアップし続け、最大値の255からオーバフローして0になる時TMR0割込みが発生
INTCON割込みを有効にするビットと割込み発生時に設定されるビットから成る
T0CONTMR0の動作を規定するレジスタで、以下のような設定が可能
・TMR0有効/無効
・TMR0クロック選択
・8/16ビットモード選択
・プリスケーラ選択
TMR0L
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
0〜255のカウンタ

8ビットのカウンタで、1命令サイクル毎に+1されます。(プリスケーラで変更できます)
そして、最大値の255から0に戻る時にTMR0割込みが発生します。

このレジスタの内容は設定可能で、例えば、TMR0Lに200がセットされていると、56命令サイクル (255−200+1)でTMR0割込みが発生します。

今回は、TMR0Lをフリーランさせます。(値を変更せず、プリスケーラやクロックで調整する)

【補足】
実際に設定する値は、オーバフロー後、次にTMR0Lに値を設定するまでの実行命令数を考慮する必要があります。(オーバフローしてもカウントアップは継続するため。)
更に、TMR0Lに値を設定した場合、その直後の2命令サイクル分はカウントアップが停止します。
また、プリスケーラを割り当てている場合は、TMR0を更新するタイミングでプリスケーラがクリアされます。

このような動作になるため、正確な時間が必要な場合は、TMR0Lをフリーランさせます。(値を変更せず、プリスケーラやクロックで調整する)



INTCON
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
GIEPEIETMR0IEINT0IERBIETMR0IFINT0IFRBIF

TMR0割込みで使うビットは以下の3つです。
その他のビットは、0にしておきます。
赤は今回の設定値です。

GIE全割込み禁止ビット
1:割込み許可(個々の割込み有効・無効ビットに従う)
0:全ての割込み禁止
TMR0IETMR0割込み有効・無効ビット
1:TMR0割込み有効
0:TMR0割込み無効(禁止)
TMR0IFTMR0オーバフロー発生フラグ
1:TMR0オーバフローが発生した(割込み処理ルーチン内でクリアが必要)
0:TMR0オーバフローは発生していない

T0CON
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
TMR0ONT08BITT0CST0SEPSAT0PS2T0PS1T0PS0

赤は今回の設定値です。

TMR0ON1:TMR0有効
0:TMR0停止
T08BIT1:8ビットモード
0:16ビットモード
T0CSTMR0クロックソース選択
1:T0CKIピン
0:命令サイクル
T0SETMR0クロックソースがT0CKIピンの時、パルスの立ち上がり・立下りのどちらでカウントするかを選択
1:立下り
0:立ち上がり
PSAプリスケーラ使用有無
1:使用しない
0:使用する
T0PS2-0 プリスケーラ使用時の倍率指定
T0PS2-0倍率
0002
0014
0108
01116
10032
10164
110128
111256
例えば、倍率64を設定すると、64命令サイクル毎にTMR0Lがカウントアップ(+1)される。


0.5秒の時間
TMR0の時間に関する設定は以下のようにしました。
TMR0L0(フリーラン)
プリスケーラ64

クロックが8MHzですので、TMR0割込み周期は
1命令の時間1/8×4=0.5uS
TMR0割込み周期0.5uS×256×64=8.192mS

従って、0.5秒間のTMR0割込み回数は
TMR0割込み回数500mS/8.192mS≒61
(TMR0割込み61回で約0.5秒)

となります。

TMR0割込みルーチンでは、TMR0割込みを61回カウントしたらフラグ(flag.flag500mS)を立て、メインルーチンでこのフラグを判定してLEDをON/OFFさせています。