PIC12F675の例題2として、TMR0割り込みを使ってLEDを1秒ごとに点滅させます。
PIC12F675は、8bitタイマーTMR0と16bitタイマーTMR1を持っています。今回はTMR0を使います。
内蔵クロック4MHzを使いますので、命令サイクルは、1/4MHz×4 = 1us となります。
TMR0のプリスケーラを1:32にすれば、1us×32×256 = 8192us = 8.192 ms ごとにオーバーフローが発生し、割り込みがかかります。
割り込みは、1秒間に122回かかりますので、122をカウンタにセットして割り込みの度にディクリメントし、カウンタが0になったら1秒とします。
実際には、8.192ms × 122 = 999.4msです。誤差は1%以下です。
回路は、前の記事と同じです。
プログラムです。
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
// CONFIG
#pragma config FOSC = INTRCIO //内蔵クロック4MHzを使う
#pragma config WDTE = OFF //
#pragma config PWRTE = ON //
#pragma config MCLRE = OFF //
#pragma config BOREN = OFF //
#pragma config CP = OFF //
#pragma config CPD = OFF //
#pragma config FOSC = INTRCIO //内蔵クロック4MHzを使う
#pragma config WDTE = OFF //
#pragma config PWRTE = ON //
#pragma config MCLRE = OFF //
#pragma config BOREN = OFF //
#pragma config CP = OFF //
#pragma config CPD = OFF //
#define _XTAL_FREQ 4000000
unsigned cnt1s;
unsigned flag_1s;
unsigned flag_1s;
/* 割り込み処理 */
void interrupt isr(){
INTCONbits.T0IF = 0; //TMR0割り込みフラッグクリア
cnt1s--; //cnt1s ディクリメント
if(cnt1s == 0){ //1s経過したら
cnt1s = 122; //カウンタ再セット
flag_1s = 1; //フラッグを立てる
}
}
void interrupt isr(){
INTCONbits.T0IF = 0; //TMR0割り込みフラッグクリア
cnt1s--; //cnt1s ディクリメント
if(cnt1s == 0){ //1s経過したら
cnt1s = 122; //カウンタ再セット
flag_1s = 1; //フラッグを立てる
}
}
void main() {
CMCON = 0x07 ; // コンパレータは使わない
ANSEL = 0b00000000 ; // すべてデジタI/O
TRISIO = 0b00000000 ; // ピンは全て出力に割当てる(GP3は入力のみとなる)
GPIO = 0x00 ; // 出力ピンの初期化
INTCONbits.T0IE = 1; // TMR0割り込み許可
INTCONbits.GIE = 1; // 全割り込み許可
CMCON = 0x07 ; // コンパレータは使わない
ANSEL = 0b00000000 ; // すべてデジタI/O
TRISIO = 0b00000000 ; // ピンは全て出力に割当てる(GP3は入力のみとなる)
GPIO = 0x00 ; // 出力ピンの初期化
INTCONbits.T0IE = 1; // TMR0割り込み許可
INTCONbits.GIE = 1; // 全割り込み許可
/* TMR0関係設定 */
OPTION_REGbits.T0CS = 0; // TMR0のソースは、内部命令サイクル
OPTION_REGbits.PSA = 0; // プリスケーラをTMR0に設定
OPTION_REGbits.PS2 = 1; // プリスケーラ 1:32
OPTION_REGbits.PS1 = 0;
OPTION_REGbits.PS0 = 0;
cnt1s = 122; // 8.192ms×122 = 999.4ms
flag_1s = 0; // 1sec経過フラッグ
while(1) {
if(flag_1s){ //1s経過フラッグが立ったら
flag_1s = 0; // 1s経過フラッグクリア
GPIO2 = 1 - GPIO2; // LED ON/OFF
}
}
}
OPTION_REGbits.T0CS = 0; // TMR0のソースは、内部命令サイクル
OPTION_REGbits.PSA = 0; // プリスケーラをTMR0に設定
OPTION_REGbits.PS2 = 1; // プリスケーラ 1:32
OPTION_REGbits.PS1 = 0;
OPTION_REGbits.PS0 = 0;
cnt1s = 122; // 8.192ms×122 = 999.4ms
flag_1s = 0; // 1sec経過フラッグ
while(1) {
if(flag_1s){ //1s経過フラッグが立ったら
flag_1s = 0; // 1s経過フラッグクリア
GPIO2 = 1 - GPIO2; // LED ON/OFF
}
}
}
-----------------------------
各レジスタの設定ですが、例えば
OPTION_REGbits.T0CS = 0; は、T0CS = 0;でもOKです。
なぜ、長い記述にしたかといいますと、XC8コンバイラは、プログラム編集中にリアルタイムでディバック、サポートをしてくれます。
ですから、OPTION_REGbits. まで入力すると各ビットの名称を候補としてウインドウに表示してくれます。
その候補の中から選べば、間違いはありません。この便利な機能を使うために、レジスタ・ビット名が長くなっています。記述は長くなるのですが、後で見てもどのレジスタか分かりやすくなります。