目次
前
次
充電用タイマー
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 ;
}
目次
前
次