目次>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; } } } // =========================== ここまで ===============================