//3分タイマー //12F683 3mintimer1 // Programed by HAL 茨城県立日立工業高等学校 //2015.4.21 version1.0 roll out // ボタン押すとカウンタリセット // ボタン長押しでスリープモード。再び押すと再起動 // 2015.4.21 12F683用に改修 コンパイラもHitech-Cに変更 // 拡張子を.cに変更してソースに加える #include #define _XTAL_FREQ 4000000 // OSC:4MHz #define TRUE 1 #define FALSE 0 __CONFIG(BORDIS & MCLRDIS & PWRTEN & WDTDIS & INTIO ); //関数宣言 void beep(char); //ビープ関数 void delay_ms(unsigned int); //引数が大きく取れるミリ秒ディレイ関数 void led(char); //LED表示関数(3ビットで指定) //グローバル変数宣言 int COUNT = 0; //秒数カウンタ int COUNT_ms = 0; //1/1000秒カウンタ int TRIGER_COUNT; //トリガーフラグをリセットするまでのカウンタ int fade; //スリープまでのフェードカウンタ char LEDON,LEDOF; //0.5秒ごとのLED状態保持 bit TRIGER_FLAG; //ボタンが押されたときにtrueになる bit LOOP; //通常ループ中はtrue。リセットやスリープになるときfalse // 割り込み処理 static void interrupt intr(void) { // Timer0 interrupt タイマ0割り込み関数 ************************************************* //1msごとにこの関数が呼び出される // 割り込み時間=(256-TMR0)*プリスケーラ*(1/クロック周波数)*4 // (256-6)*4*(1/4000000)*4 = 1ms if(T0IF){ COUNT_ms++; //1ms毎にカウントアップ if( COUNT_ms == 1 ){ //0~500ms間はLEDOFの内容を表示 led(LEDOF); } if( COUNT_ms == 500 ){ //500~1000ms間はLEDONの内容を表示 led(LEDON); } if( COUNT_ms >= 977){ //1000ms秒経過したら COUNT_ms = 0; //ミリ秒カウンタリセット COUNT++; //1秒カウンタをインクリメント } //1秒でトリガーフラグをリセット if( TRIGER_FLAG == TRUE ){ TRIGER_COUNT++; if( TRIGER_COUNT >= 1000 ){ TRIGER_COUNT = 0; TRIGER_FLAG = FALSE; } } T0IF = 0; // TMR0割り込みフラグクリア } //外部割り込み(ポート2トリガー割り込み) if(INTF){ COUNT=0; //カウンタを0秒に戻す TRIGER_FLAG = TRUE; //トリガーが押されたフラグON beep(1); //ボタンが押されたらビープ delay_ms(10); //チャタリング防止ディレイ INTF=0; //外部割り込みフラグクリア } } // メインループ **************************************************************************** main() { //レジスタ設定 OSCCON = 0b01100001; // 内蔵OSC 4MHz ANSEL = 0b00000000; // I/Oデジタル ADCON0 = 0; // ADC off CMCON0 = 0x07; // コンパレータ未使用 TMR0=6; // タイマ割り込み値調整 OPTION = 0b00000001; // プリスケーラ:1/4 TRISIO = 0b000100; // I/O set //A0....(OUT) LED 0 //A1....(OUT) LED 1 //A2....(IN) tact SW (pull up) //A3....(NON) NOMCLR //A4....(OUT) LED 2 //A5....(OUT) Buzzer GPIO=0xff; // CCP1CON = 0b00001100; // PWMモードにする // T2CON = 0b00000110; // プリスケール1/16 // T2CON = 0b00000110; // プリスケール1/16 // PR2 = 155; // PWM周期 //変数宣言 signed int i,j; //ループ用汎用変数(マイナス(i<=0)を判定するためにsigned宣言) //グローバル変数初期化 COUNT = 0; // COUNT_ms = 0; TRIGER_FLAG = FALSE; TRIGER_COUNT = 0; //割り込み許可 // PEIE=1; // GPIE=1; INTE=1; // 外部割り込み許可 //メインループ while(1){ GIE=1; // グローバル割り込み許可 T0IE=0; // タイマ0でスリープが復帰しないように,タイマ0割り込み禁止 asm("sleep"); // スリープモードにする(トリガー割り込みで復帰) T0IE=1; // タイマ0割り込み許可 //電源投入時いったん点灯 GPIO=0x00; //ポートオールON delay_ms(10); COUNT=0; //秒数カウンタを0に //beep(1); fade=0; //長押しカウンタリセット LOOP=TRUE; //通常ループ継続フラグ //通常ループ while( LOOP == TRUE ){ //LOOPフラグが真の間ループ //長押しでスリープへ if( GPIO2 == 0){ fade++; if( fade >= 9999 ){ fade = 0; LOOP = FALSE; GIE=0; // グローバル割り込み禁止 GPIO=0xff; //LED消灯 delay_ms(1000); //チャタリング防止ディレイ INTF=0; // 外部割り込みフラグクリア(すぐに再起動防止) } } else{ fade = 0; //ボタンが放されていたら長押しカウンタリセット } //0~59秒間の表示値セット if( COUNT >= 0 && COUNT <= 59 ){ LEDON=0b000; LEDOF=0b001; } //60~119秒間の表示値セット if( COUNT >= 60 && COUNT <= 119 ){ LEDON=0b001; LEDOF=0b011; } //120~180秒間の表示値セット if( COUNT >= 120 && COUNT <= 129 ){ LEDON=0b011; LEDOF=0b111; } //3分たったら if( COUNT == 180 ){ LEDON=0b000; LEDOF=0b111; GIE=0; //割り込み禁止 beep(8); //ビープならす LOOP = FALSE; //スリープモードへ } }//counter loop delay_ms(10); } } //main() loop //関数群**************************************************************** //beep (n=cycle) void beep(char n) { int i,j; for(j=1;j<=n;j++) { for (i=0;i<=200;i++){ GPIO5=0; __delay_us(200); GPIO5=1; __delay_us(200); } delay_ms(200); } } //LED表示関数(引数が3ビット,0で表示,1で消灯) void led(char data) { GPIO = ((data & 0b100) >> 2 ) | (data & 0b010) | ((data & 0b001) << 4 ); delay_ms(1); } // ミリ秒ディレイ関数(引数が0-65535(unsigned int)で指定可) ************************************************* // 引数:ms=delay [ms] (unsigned int) // 返値:なし // 機能:ミリ秒ディレイ // __delay_ms(n)のnは25まで(20MHzで39,10MHzで78,8MHzで98まで(合計サイクルが197,120まで))で定数しかセットできないのでもっと大きい値をセットできるdelaymsを作った void delay_ms(unsigned int ms){ while(ms>=25){ __delay_ms(25); ms-=25; } for (;ms>0; ms--) __delay_ms(1); }