目次>6章 第3ステップ(実用品)>永久回転こま>ソース
永久回転こま(ソース)
<PIC16F648A> PICC
更新日2007.12.8
以下のソースを取り込んで、コンパイル→PIC書き込み→実行して下さい。
PICC−Liteを使用しました。
// ========================== ここから ==============================
// PIC16F627A(実使用は648A)
// CLOCK : INT 4MHz
// PIC26F648Aでコマを制御する
//
// TMR0を0.256mS毎にカウントアップし、
// RB0INT割込み(磁界検出)時にTMR0の値を「T0_save」に保存した後、TMR0をクリアする。
// ここからTMR0が「T0_save/2」経過した時点でRB1をONにする。
// RB1をONにしてから、TMR0が「T0_save/4」経過した時点でRB1をOFFにする。
//
//
//
//
// RB0:RB0INT 磁界検出コイルをオペアンプで増幅した出力
// RB1:コマを制御する電磁石(FETで制御)
//
#include "pic.h"
__CONFIG(INTIO & WDTDIS & PWRTDIS & LVPDIS & BORDIS & MCLRDIS);
static unsigned int T0_save;
static unsigned int T0_save_2;
static unsigned int T0_save_4;
static unsigned int T0_save_8;
static unsigned int T0_save_16;
static unsigned int T0_work;
static unsigned int RB1_on_cnt;
static unsigned int RB1_off_cnt;
static unsigned int RB1_off2_cnt;
static bit T0_over;
static bit T0_2round;
// =================== 割り込み処理 ====================
static void interrupt intr(void) {
if (INTF) {
INTF = 0; // RB0INT割り込みクリア
T0_save = TMR0;
TMR0 = 0;
if (T0_2round) {
T0_save = T0_save | 0x0100;
T0_2round = 0;
}
T0_save_2 = T0_save >>1; // TMR0/2
T0_save_4 = T0_save_2 >>1; // TMR0/4
T0_save_8 = T0_save_4 >>1; // TMR0/8
T0_save_16 = T0_save_8 >>1; // TMR0/16
RB1_on_cnt = T0_save_2 - T0_save_8; // TMR0/2 - TMR0/8
RB1_off_cnt = T0_save_2 + T0_save_4 - T0_save_16; // TMR0/2 + TMR0/4 - TMR0/16
RB1_off2_cnt = RB1_off_cnt + T0_save_16; // TMR0/2 + TMR0/4 + TMR0/16
} else
if (T0IF) {
T0IF = 0; // TMR0割り込みクリア
if (T0_2round) {
T0_over = 1;
} else {
T0_2round = 1;
}
}
}
// ==================== PICの初期化 ===========================
static void pic_init() {
OPTION = 0xC7; // プリスケーラ:256
PORTA = 0;
CMCON = 0x07; // コンパレータ未使用
TRISA = 0xFF; // PORTA:in
TRISB = 0xF9; // RB1,2:out
PORTB = 0x00;
TMR0 = 0;
INTCON = 0xA0; // TMR0 enable
T0_over = 0;
T0_2round = 0;
RB1_on_cnt = 0;
RB1_off_cnt = 0;
}
// =============== RB2のLEDを0.5秒間隔で点滅する ================
static void RB2_onoff() {
char i;
char j;
for (j=10 ; j>0 ; j--) {
for (i=4 ; i>0 ; i--) { // 0.5秒待つ (131mS×4=524mS)
while(!T0_over) {} // 0.256mS×512=131mS
TMR0 = 0;
T0_over = 0;
T0_2round = 0;
}
if (RB2) {
RB2 = 0;
} else {
RB2 = 1;
}
}
}
// ==================== メイン処理 ===========================
main() {
pic_init(); // PICの初期化
RB2_onoff(); // RB2のLEDを0.5秒間隔で点滅する
INTF = 0;
INTE = 1;
while(1) {
T0_work = TMR0;
if (T0_2round) {
T0_work = T0_work | 0x0100;
}
if ((T0_work > RB1_on_cnt) && (T0_work < RB1_off_cnt)) {
INTE = 0;
RB1 = 1;
} else {
if (RB1) {
RB1 = 0;
}
if (T0_work > RB1_off2_cnt) {
if (!INTE) {
INTF = 0;
INTE = 1;
}
}
}
if (T0_over) {
RB1 = 0;
RB2 = 0;
INTE = 1;
SLEEP(); // ■ SLEEP
RB2 = 1;
TMR0 = 0;
T0_over = 0;
T0_2round = 0;
RB1_on_cnt = 0;
RB1_off_cnt = 0;
}
}
}
// =========================== ここまで ===============================