目次>9章 PIC18F1320編 > TMR0割込みを使う(8ビットモードと16ビットモード)

TMR0割込みを使う

− 8ビットモードと16ビットモード −

更新日2008.12.21

ここでは、PIC18のTMR0割込みを使って見ます。
PIC18のTMR0割込みは、PIC16と同様の8ビットモードに加え、16ビットモードが追加されています。
この2つの使い方の違いを見て行きましょう。

このページの目次
1.実験回路
2.プログラムの仕様
3.PIC18の割込み
4.TMR0割込みで使うレジスタ
5.TMR0割込み(8ビットモード)
6.TMR0割込み(16ビットモード)
7.PIC18の勧め(6)

1.実験回路

1秒毎にLEDを点滅させて見るで使った回路と同じで、2つのLEDをRB0/RB1に接続します。

680Ωの抵抗2本は、300Ω〜1KΩ程度の範囲であれば何でもOKです。

2.プログラムの仕様

RB0/RB1のLEDを1秒間隔で交互に点滅させます。
1秒の時間はTMR0割り込みにより作成します。TMR0割込みは、8ビットモードと16ビットモードの2種類を使って見ます。


3.PIC18の割込み

PIC18の割込みは、基本的にPIC16と同様です。
違いは、下の図のように割込みベクタのアドレスが変わっている点です。

ただし、PIC18では割込みに2つの優先順位を持たせる事が可能で、この新しい機能を使う場合は色々と違いがあります。それは別のページで実験して見る事にします。

今回は、割込みをPIC16互換で使用します。


4.TMR0割込みで使うレジスタ

TMR0割込みで使うレジスタをPIC16と対比すると下のようになります。

PIC16PIC18用途など
TMR0TMR0L8ビットのカウンタで、1命令サイクル毎にカウントアップし続け、最大値の255からオーバフローして0になる時TMR0割込みが発生
INTCONINTCONビットの意味は同じだがビットの名前が変わった
T0IE→TMR0IE
T0IF→TMR0IF
OPTION_REGT0CONプリスケーラ選択とTMR0クロック選択に加え、以下のビットが追加された
TMR0ON:TMR0有効/無効ビット
T08BIT:8/16ビットモード選択ビット
TMR0L
Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0
0〜255のカウンタ

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

このレジスタの内容は設定可能で、例えば、TMR0Lに200がセットされていると、56命令サイクル (255−200+1)でTMR0割込みが発生します。
今回は、クロックとして10MHzを使用していますので、1命令サイクルは0.4μSです。
従って、22.4μS(0.4μS×56命令サイクル)でTMR0割込みが発生します。

【補足】
実際に設定する値は、オーバフロー後、次に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)される。

5.TMR0割込み(8ビットモード)

8ビットモードで動作させるには、T0CONのT08BITを1にします。

それ以外のレジスタ設定は以下のようにしました。
TMR0L128
プリスケーラ256
クロックが10MHzですので、TMR0割込み周期は
1命令の時間1/10×4=0.4uS
TMR0割込み周期0.4uS×256×128=13.1072mS
従って、1秒間のTMR0割込み回数は
TMR0割込み回数1000mS/13.1072mS≒76
(TMR0割込み76回で約1秒)
となります。


プログラム

8ビットモードのプログラムはこちらです。

プログラムの処理で、今回のポイントをいくつか説明します。

<初期処理>
初期処理では、T0CON,TMR0L,INTCONの設定を行います。
; ******** 初期処理 *****************************
init
	;省略
	;
	MOVLW	0xC7
	MOVWF	T0CON		;TMR0 enable,8bit,presc256
	MOVLW	TMR0_i
	MOVWF	TMR0L
	BSF	INTCON,TMR0IE	;TMR0割込み許可
	BSF	INTCON,GIE	;全割込み許可
			

<割込み処理>
割込み処理の開始アドレスを、08hに合わせます。
また、割込みの入り口と出口でレジスタの退避・復元を行いますが、通常は下のように3つのレジスタを対象にします。
; ******** 割込み処理 ****************************
	ORG	0x0008			;割込みベクタ
	MOVFF	STATUS,STATUS_TEMP 	;save STATUS
	MOVFF	WREG,WREG_TEMP		;save WREG
	MOVFF	BSR,BSR_TEMP		;save BSR
	;
	;省略
	;
	MOVFF	BSR_TEMP,BSR		;restore BSR
	MOVFF	WREG_TEMP,WREG		;restore WREG
	MOVFF	STATUS_TEMP,STATUS 	;restore STATUS
	RETFIE
			

MOVFF命令は、PIC18で追加された命令で、以下の利点があります。
・STATUSレジスタを更新しない(PIC16のレジスタ退避・復元のような面倒な事が不要)
・命令のアドレス部が12ビットであり、バンクを考慮せずに全RAM領域にアクセスできる

<GPR(汎用レジスタ)の定義>
データメモリはバンクを意識したアクセスが必要ですが、バンク0の前半はバンクを意識せずに使えます。(アクセスバンク)
また、割込みで使うレジスタ退避用の領域は、今回はMOVFF命令のみで使いますので、バンクを考慮せずに全RAM領域にアクセスできます。
従って、下のようなメモリ割り当てにしました。メモリに余裕があればレジスタ退避領域もバンク0の前半に割り当ててかまいません。
(今回はメモリに十分余裕がありますが意図的にこのような割り当てにしました。)
; ******** GPR *******************************
	CBLOCK	0x080
	WREG_TEMP		;WREG save area
	STATUS_TEMP 	;STATUS save area
	BSR_TEMP		;BSR save area
	ENDC

	CBLOCK	0x000
	CNT1S
	flag
	ENDC
			

6.TMR0割込み(16ビットモード)

次は16ビットモードで動かして見ましょう。

8ビットと16ビットの違い

8ビットと16ビットの違いは、表現できる数が異なる点です。
8ビットで表せる数: 0〜255
16ビットで表せる数: 0〜65535
従って、16ビットモードの場合は、最大値の65535から0に戻る時にTMR0割込みが発生します。
TMR0割込みの最大値は以下のようになります。(クロック10MHz,プリスケーラ256の場合)
8ビットモード: 0.4uS×256×25626.2144mS
16ビットモード: 0.4uS×256×655366710.8864mS

16ビットモードで使うレジスタ

16ビットモードで動作させるには、T0CONT08BIT0にします。

こうする事でTMR0レジスタは16ビットモードになりますが、データメモリ(レジスタ)は8ビット単位でしかアクセスできません。
そこで、下図のようにTMR0レジスタを上位8ビットと下位8ビットに分けてアクセスするようになっています。

上位8ビットはTMR0Hを、下位8ビットはTMR0Lレジスタを介してアクセスします。

ただし、TMR0レジスタの上位8ビットとTMR0Hレジスタは単純には連携していません。

まず、簡単なTMR0の下位8ビットとTMR0Lですが、こちらは単純で、プログラムからTMR0LレジスタをREAD/WRITEすれば、そのままTMR0の下位8ビットにREAD/WRITEされます。(下図の水色)

一方、TMR0の上位8ビットのREAD/WRITE(下図の黄色の矢印)は、プログラムでのTMR0Hレジスタに対するREAD/WRITE(緑の矢印)に連動しません。
TMR0の上位8ビットとTMR0Hレジスタ間のデータ転送は、TMR0LレジスタへのREAD/WRITEに連動して行われます。(赤と黄色の矢印)

TMR0への書き込み手順
  1. TMR0Hレジスタにデータを書き込む
  2. TMR0Lレジスタにデータを書き込む


TMR0からの読み出し手順
  1. TMR0Lレジスタからデータを読み込む
  2. TMR0Hレジスタからデータを読み込む

16ビットのTMR0レジスタに意図した値が書き込めるように、また正しい値が読み出せるようにするためこのような動作になっています。


今回のプログラムでのレジスタの設定

16ビットモードで動作させるために、T0CONT08BIT0にします。

そして、TMR0レジスタへの設定値は、プリスケーラを256とすると、
オーバフローまでのカウント値: 1秒/0.4u秒/2569765
TMR0設定値: 65536−976555771
この、TMR0設定値を16進数に変換
55771 → 0D9DBh
従ってレジスタ設定は以下のようになります。
TMR0H0D9h
TMR0L0DBh
プリスケーラ256


プログラム

16ビットモードのプログラムはこちらです。

基本的な流れは8ビットモードのプログラムと同じです。


7.PIC18の勧め(Vol.6)

その7. TMR0は16ビットモードがサポートされた
従来の8ビットモードでは、長い時間(例えば1秒とか)を得るためにTMR0割込みを一定回数カウントするような事が必要でした。
PIC18では、16ビットモードがサポートされ、長い時間も1回のTMR0割込みで得る事ができます。
その8. MOVFF命令はバンクの意識が不要
TMR0割込みとは関係ありませんが、PIC18で追加された命令の一つであるMOVFF命令は、転送元・転送先のアドレスを12ビットで表現しており、全てのデータメモリに対してバンクを考慮せずにアクセスできます。