目次

充電用タイマー

 8ピンのPICを貰ったので、充電用タイマーを作りました。  アナログスイッチを利用し、4ビットで1から15までを  設定します。PICは、ビット3から0までの論理値を入力  し、指定時間だけ出力をHとします。  回路は、非常に簡単です。  プログラムは、タイマー割込みをひとつだけ利用して  10ms、60秒ごとにイベントフラグをセットします。  10msは、スイッチのチャタリング除去で使います。  60秒は、1分経過でカウンタを更新します。  フラグ通知で、シフトレジスタにスイッチの状態を  入れて、立下りエッジをとらえます。RUNスイッチが  押されたなら、4ビット値を入力し、COUTをHレベル  とします。  また、1から15時間が、分のカウントでいくらに  なるか計算します。  COUTをLレベルに戻すには、別のフラグを使います。  60秒ごとに時間カウンタを  減らすタイミングに利用します。  プログラムのソースコードは以下。 /* redefine data type */ typedef unsigned char UBYTE ; typedef unsigned int UWORD ; typedef unsigned long ULONG ; #define OFF 0 #define ON OFF+1 #define MASKFF 0xff #define MASK30 0x30 #define MASK0F 0x0f #define MASK03 0x03 volatile UBYTE tflag ; volatile UBYTE sflag ; volatile ULONG timcnt ; volatile UBYTE timv ; volatile UBYTE scnt ; volatile UWORD lastcnt ; volatile UBYTE trg_sft ; /* function prototype */ void init_usr(void); UBYTE get_tcnt(void); /* interrupt handler */ void interrupt(void) { /* generate 1ms */ if ( INTCON.T0IF == ON ) { /* clear flag */ INTCON.T0IF = OFF ; /* initialize */ TMR0 = 6 ; /* increment */ timcnt++ ; /* get lower 8 bits */ timv = timcnt & MASKFF ; /* judge */ if ( (timv & 15) == 10 ) { /* set flag each 10ms */ sflag = ON ; } if ( timv == 250 ) { /* increment */ scnt++ ; /* past 60 seconds */ if ( scnt == 240 ) { scnt = 0 ; tflag = ON ; } } } } void main(void) { /* user initialize */ init_usr(); /* endless loop */ while ( ON ) { /* switch handling */ if ( sflag == ON ) { /* clear flag */ sflag = OFF ; /* get pin state */ trg_sft <<= 1 ; trg_sft &= MASK03 ; if ( GPIO.B4 == OFF ) { trg_sft |= ON ; } /* judge */ if ( trg_sft == 0x01 ) { /* get last count */ lastcnt = 60 * get_tcnt(); /* enable */ GPIO.B5 = ON ; } } /* 60 seconds pass handling */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* decrement */ lastcnt-- ; /* judge */ if ( lastcnt == 0 ) { GPIO.B5 = OFF ; } } } } /* define function body */ void init_usr(void) { /* I/O state */ GPIO = 0x00 ; /* I/O directions */ TRISIO = 0x1c ; /* bit2,4 as input , others as output */ /* disable compare module */ CMCON = 0x07 ; /* pull-up */ WPU = 0x14 ; /* initialize Timer 0 */ { trg_sft = 0 ; /* 4MHz/4 = 1MHz -> 1MHz/4 = 250kHz prescaler = 1:4 all inputs are pull-up . */ OPTION_REG = 0x01 ; /* 256 - 250 = 6 */ TMR0 = 6 ; /* enable timer0 overflow interrupt */ INTCON.T0IE = ON ; } /* enable general interrupt */ INTCON.GIE = ON ; /* clear flags */ tflag = OFF ; sflag = OFF ; /* clear */ timcnt = 0 ; scnt = 0 ; lastcnt = 10 ; } UBYTE get_tcnt(void) { UBYTE loop ; UBYTE result ; UBYTE xgpio ; /* clear */ result = 0 ; /* loop */ for ( loop = 0 ; loop < 4 ; loop++ ) { /* address */ xgpio = GPIO ; xgpio &= ~MASK03 ; xgpio |= ((3-loop) & MASK03); GPIO = xgpio ; /* shift */ result <<= 1 ; /* get target bit state */ if ( GPIO.B2 == ON ) { result |= ON ; } } return result ; }  ソースコードは、MikroCの評価版を利用しています。  利用したPIC12F629は、最大容量が2kバイトなので  評価版で充分でした。  PIC12Fシリーズの中で、A/Dコンバータを持ったデバイス  では、電源ONでピンはA/Dコンバータ接続に設定されてる  ので、これをデジタル入出力に切り替えないと、正しく  動きません。  PIC12F683を利用したときは、次のソースコードになります。 /* redefine data type */ typedef unsigned char UBYTE ; typedef unsigned int UWORD ; typedef unsigned long ULONG ; #define OFF 0 #define ON OFF+1 #define MASKFF 0xff #define MASK30 0x30 #define MASK0F 0x0f #define MASK03 0x03 volatile UBYTE tflag ; volatile UBYTE sflag ; volatile ULONG timcnt ; volatile UBYTE timv ; volatile UBYTE scnt ; volatile UWORD lastcnt ; volatile UBYTE trg_sft ; /* function prototype */ void init_usr(void); UBYTE get_tcnt(void); /* interrupt handler */ void interrupt(void) { /* generate 1ms */ if ( INTCON.T0IF == ON ) { /* clear flag */ INTCON.T0IF = OFF ; /* initialize */ TMR0 = 6 ; /* increment */ timcnt++ ; /* get lower 8 bits */ timv = timcnt & MASKFF ; /* judge */ if ( (timv & 15) == 10 ) { /* set flag */ sflag = ON ; } if ( timv == 250 ) { /* increment */ scnt++ ; /* past 60 seconds */ if ( scnt == 240 ) { scnt = 0 ; tflag = ON ; } } } } void main(void) { /* user initialize */ init_usr(); /* endless loop */ while ( ON ) { /* switch handling */ if ( sflag == ON ) { /* clear flag */ sflag = OFF ; /* get pin state */ trg_sft <<= 1 ; trg_sft &= MASK03 ; if ( GPIO.B4 == OFF ) { trg_sft |= ON ; } /* judge */ if ( trg_sft == 0x01 ) { /* get last count */ lastcnt = 60 * get_tcnt(); /* enable */ GPIO.B5 = ON ; } } /* 60 seconds pass handling */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* decrement */ lastcnt-- ; /* judge */ if ( lastcnt == 0 ) { GPIO.B5 = OFF ; } } } } /* define function body */ void init_usr(void) { /* select digital inputs */ ANSEL = 0x00 ; /* I/O state */ GPIO = 0x00 ; /* I/O directions */ TRISIO = 0x1c ; /* bit2,4 as input , others as output */ /* disable compare module */ CMCON0 = 0x07 ; /* pull-up */ WPU = 0x14 ; /* initialize Timer 0 */ { trg_sft = 0 ; /* 4MHz/4 = 1MHz -> 1MHz/4 = 250kHz prescaler = 1:4 all inputs are pull-up . */ OPTION_REG = 0x01 ; /* 256 - 250 = 6 */ TMR0 = 6 ; /* enable timer0 overflow interrupt */ INTCON.T0IE = ON ; } /* enable general interrupt */ INTCON.GIE = ON ; /* clear flags */ tflag = OFF ; sflag = OFF ; /* clear */ timcnt = 0 ; scnt = 0 ; lastcnt = 10 ; } UBYTE get_tcnt(void) { UBYTE loop ; UBYTE result ; UBYTE xgpio ; /* clear */ result = 0 ; /* loop */ for ( loop = 0 ; loop < 4 ; loop++ ) { /* address */ xgpio = GPIO ; xgpio &= ~MASK03 ; xgpio |= ((3-loop) & MASK03); GPIO = xgpio ; /* shift */ result <<= 1 ; /* get target bit state */ if ( GPIO.B2 == ON ) { result |= ON ; } } return result ; }
目次

inserted by FC2 system