目次
前
電源タイマー
自作の夜間点滅器がありますが、午前0時から翌朝6時くらいまでは
点滅不要なので、電源タイマーを作成しました。PIC16F629を使います。
点滅器は半田付けしてあるので、接続する電源制御だけを考えます。
夕方暗くなったことを検出して、4時間電源を入れることに。
ハードウエアのブロック図は、以下。
回路図は、以下。
3V動作リレーがあるので、電源制御はリレーに任せます。
ファームウエアの構成を考えます。
- 明→暗を検出したなら、2へ
- カウンタに最大値を設定と同時に、リレーをオンにしたなら、3へ
- タイマー割込みからのイベントフラグをとらえて、カウンタをデクリメント、4へ
- カウンタ値が正なら3へ、ゼロならリレーをオフして5へ
- 1にもどる
大まかなコードを書きます。
while ( ON ) {
/* timer handling (1000ms) */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* interval handling */
if ( timcnt > 0 ) { timcnt-- ; }
/* shift */
sft <<= 1 ;
/* mask */
sft &= MASK03 ;
/* update state */
TRISIO.B5 = ON ; /* B5 is input */
if ( GPIO.B5 == OFF ) { sft |= ON ; }
/* judge */
if ( sft == 0x01 ) { eflag = ON ; }
}
/* start timer */
if ( eflag == ON ) {
/* clear flag */
eflag = OFF ;
/* set count */
timcnt = TIMCNTMAX ;
}
/* output handling */
if ( timcnt > 0 ) {
/* B0 is output */
TRISIO.B0 = OFF ;
/* relay on */
if ( GPIO.B0 == OFF ) { GPIO.B0 = ON ; }
} else {
/* B0 is output */
TRISIO.B0 = OFF ;
/* relay off */
GPIO.B0 = OFF ;
}
}
1000msの経過を、タイマー割込みでイベント通知することにし
それに対応した処理を記述してあります。
内蔵の4MHzを利用し、タイマー0でオーバーフロー割込みを使います。
1000msを生成するために、次のように考えました。
- タイマー0の入力クロックは4MHz/4=1MHzなので、プリスケーラで分周
- プリスケーラで16分周すれば、62.5kHzとする
- 62.5kHzを250分周すると、250Hz(8ビットカウンタの範囲で扱える)
- 250Hzを、250分周し1Hzとする
- 1Hzでイベントフラグによる通知とする
割込み処理を定義します。
void interrupt(void) {
/* generate 1000ms */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = 6 ;
/* increment */
timv++ ;
/* judge */
if ( timv == 250 ) {
/* clear */
timv = 0 ;
/* set flag */
tflag = ON ;
}
}
}
まとめます。
typedef unsigned char UBYTE ;
typedef unsigned int UWORD ;
#define OFF 0
#define ON OFF+1
#define MASKFF 0xff
#define MASK30 0x30
#define MASK0F 0x0f
#define MASK03 0x03
#define TIMCNTMAX 14400
volatile UBYTE tflag ;
volatile UBYTE eflag ;
volatile UBYTE sft ;
volatile UBYTE timv ;
volatile UWORD timcnt ;
/* function prototype */
void init_usr(void);
/* interrupt handler */
void interrupt(void) {
/* generate 1000ms */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = 6 ;
/* increment */
timv++ ;
/* judge */
if ( timv == 250 ) {
/* clear */
timv = 0 ;
/* set flag */
tflag = ON ;
}
}
}
void main(void) {
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* timer handling (1000ms) */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* interval handling */
if ( timcnt > 0 ) { timcnt-- ; }
/* shift */
sft <<= 1 ;
/* mask */
sft &= MASK03 ;
/* update state */
TRISIO.B5 = ON ; /* B5 is input */
if ( GPIO.B5 == OFF ) { sft |= ON ; }
/* send trigger */
if ( sft == 0x01 ) { eflag = ON ; }
}
/* start timer */
if ( eflag == ON ) {
/* clear trigger flag */
eflag = OFF ;
/* set count */
timcnt = TIMCNTMAX ;
}
/* output handling */
if ( timcnt > 0 ) {
/* B0 is output */
TRISIO.B0 = 0 ;
/* relay on */
if ( GPIO.B0 == OFF ) { GPIO.B0 = ON ; }
} else {
/* B0 is output */
TRISIO.B0 = 0 ;
/* relay off */
GPIO.B0 = OFF ;
}
}
}
/* define function body */
void init_usr(void)
{
/* I/O state */
GPIO = 0x00 ;
/* I/O directions */
TRISIO = 0x18 ; /* bit3,5 as input , others as output */
/* disable compare module */
CMCON = 0x07 ;
/* pull-up */
/* WPU = 0x10 ; */
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz -> 1MHz/16 = 62.5kHz prescaler = 1:16
*/
OPTION_REG = 0x03 ;
/* 256 - 250 = 6 */
TMR0 = 6 ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flags */
tflag = OFF ;
eflag = OFF ;
/* clear */
sft = 0 ;
timcnt = 0 ;
timv = 0 ;
}
目次
前