目次

Clock Generator

 Clock Generatorは、PIC12F629を利用して実現します。

 回路図は、以下。



 内蔵4MHzをタイマー0に入力し、500Hzを生成します。
 この500Hzを分周して10Hz、1Hzを作り出します。

 タイマー割込みでは、1MHzを8分周後、さらに250分周
 して500Hzを生成します。



 割込み関係コードは、以下。

#define CNTBEGIN 6

void interrupt(void)
{
  /* generate 500Hz */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize (/250) */
    TMR0 = CNTBEGIN ;
    /* set flag */
    eflag = ON ;
  }
}

 タイマーハンドラは、500Hzごとにイベントフラグeflag
 で、main関数に指定時間経過を通知します。

 10Hzは500Hzを50分周して生成しますが、25分周して20Hzにします。
 20Hzで、出力ピンに0か1を印加します。
 1Hzは500Hzを250分周して2Hzにします。
 2Hzで、出力ピンに0か1を印加します。

 mainの中にある無限ループ内で、次のコードで10Hz、1Hzを生成。

    if ( eflag == ON ) {
      /* clear flag */
      eflag = OFF ;
      /* counter increment */
      xcnt++ ;
      ycnt++ ;
      /* generate 20Hz */
      if ( xcnt == XCNTMAX ) {
        xcnt = 0 ;
        cnt10 = cnt10 + 1 ;
      }
      /* generate 2Hz */
      if ( ycnt == YCNTMAX ) {
        ycnt = 0 ;
        cnt++ ;
      }
      /* impress */
      OUT10 = cnt10 & ON ;
      OUT1  = cnt & ON ;
    }

 20Hz、2Hzで担当するカウンタのLSBを出力して
 いきます。

 マニュアルクロックは、プッシュスイッチの状態を
 読込んで、反転出力します。

 チャタリングが発生しますが、出力にキャパシタを
 接続して、波形をなまらせます。



 該当コードは、以下としました。

      /* get and mask */
      tmp = GPIO & (1 << 5);
      /* shift */
      tmp >>= 5 ;
      /* impress */
      OUTM = !(tmp & ON) ;

 ソースコードは、以下。

/* redefine data type */
typedef unsigned char UBYTE ;
typedef unsigned int  UWORD ;

#define OFF 0
#define ON  OFF+1

#define MASK0F 0x0f

#define OUT10 GPIO.B0
#define OUT1  GPIO.B1
#define OUTM  GPIO.B2

#define CNTBEGIN 6
#define XCNTMAX  25
#define YCNTMAX  250

volatile UBYTE eflag ;
volatile UBYTE tmp   ;
volatile UBYTE xcnt  ;
volatile UBYTE ycnt  ;
volatile UBYTE cnt10 ;
volatile UBYTE cnt   ;

/* function prototype */
void  init_usr(void);

/* interrupt handler */
void interrupt(void)
{
  /* generate 500Hz */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize (/250) */
    TMR0 = CNTBEGIN ;
    /* set flag */
    eflag = ON ;
  }
}

void main(void)
{
  /* user initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* generate 10Hz and 1Hz */
    if ( eflag == ON ) {
      /* clear flag */
      eflag = OFF ;
      /* counter increment */
      xcnt++ ;
      ycnt++ ;
      /* generate 20Hz */
      if ( xcnt == XCNTMAX ) {
        xcnt = 0 ;
        cnt10 = cnt10 + 1 ;
      }
      /* generate 2Hz */
      if ( ycnt == YCNTMAX ) {
        ycnt = 0 ;
        cnt++ ;
      }
      /* impress */
      OUT10 = cnt10 & ON ;
      OUT1  = cnt & ON ;
    }
    /* manual clock generator */
    {
      /* get and mask */
      tmp = GPIO & (1 << 5);
      /* shift */
      tmp >>= 5 ;
      /* impress */
      OUTM = !(tmp & ON) ;
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* I/O state */
  GPIO = 0x00 ;
  /* I/O directions */
  TRISIO = 0x38 ; /* bit0,1,2 as output , others as input */
  /* disable compare module */
  CMCON = 0x07 ;
  /* pull-up */
  WPU = 0x30 ;
  /* initialize Timer 0 */
  {
    /*
       4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
    */
    OPTION_REG = 0x02 ;
    /* 256 - 6 = 250 */
    TMR0 = CNTBEGIN ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear flag */
  eflag = OFF ;
  /* others */
  xcnt  = 0 ;
  ycnt  = 0 ;
  cnt10 = 0 ;
  cnt   = 0 ;
}

 基板上に実装すると、以下。



 ヘッダピンをたてて、インバータに
 2ピンワイヤーケーブルで接続します。

 他にもマイコンを利用することがあるとして、GPIO4ピンから
 クロックを出力します。



 GPIO4ピンからのクロック出力を加えると、次のソースコード
 になります。

/* redefine data type */
typedef unsigned char UBYTE ;
typedef unsigned int  UWORD ;

#define OFF 0
#define ON  OFF+1

#define MASK0F 0x0f

#define OUT10 GPIO.B0
#define OUT1  GPIO.B1
#define OUTM  GPIO.B2
#define OUTX  GPIO.B4

#define CNTBEGIN 6
#define XCNTMAX  25
#define YCNTMAX  250

volatile UBYTE eflag ;
volatile UBYTE tmp   ;
volatile UBYTE xcnt  ;
volatile UBYTE ycnt  ;
volatile UBYTE zcnt  ;
volatile UBYTE cnt10 ;
volatile UBYTE cnt   ;

/* function prototype */
void  init_usr(void);

/* interrupt handler */
void interrupt(void)
{
  /* generate 500Hz */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize (/250) */
    TMR0 = CNTBEGIN ;
    /* set flag */
    eflag = ON ;
  }
}

void main(void)
{
  /* user initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* generate 10Hz and 1Hz */
    if ( eflag == ON ) {
      /* clear flag */
      eflag = OFF ;
      /* counter increment */
      xcnt++ ;
      ycnt++ ;
      zcnt++ ;
      /* generate 20Hz */
      if ( xcnt == XCNTMAX ) {
        xcnt = 0 ;
        cnt10 = cnt10 + 1 ;
      }
      /* generate 2Hz */
      if ( ycnt == YCNTMAX ) {
        ycnt = 0 ;
        cnt++ ;
      }
      /* impress */
      OUT10 = cnt10 & ON ;
      OUT1  = cnt & ON ;
      OUTX  = zcnt & ON ;
    }
    /* manual clock generator */
    {
      /* get and mask */
      tmp = GPIO & (1 << 5);
      /* shift */
      tmp >>= 5 ;
      /* impress */
      OUTM = !(tmp & ON) ;
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* I/O state */
  GPIO = 0x00 ;
  /* I/O directions */
  TRISIO = 0x28 ; /* bit0,1,2,4 as output , others as input */
  /* disable compare module */
  CMCON = 0x07 ;
  /* pull-up */
  WPU = 0x20 ;
  /* initialize Timer 0 */
  {
    /*
       4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
    */
    OPTION_REG = 0x02 ;
    /* 256 - 6 = 250 */
    TMR0 = CNTBEGIN ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear flag */
  eflag = OFF ;
  /* others */
  xcnt  = 0 ;
  ycnt  = 0 ;
  zcnt  = 0 ;
  cnt10 = 0 ;
  cnt   = 0 ;
}


目次

inserted by FC2 system