目次

LEDを点滅(タイマー割込み利用)

 時間利用の動作制御には、タイマー割込みを使います。

 マイコンを触り始めた頃だと、このページの内容を理解する
 のは、難しいと思うので、一通りのことができるようになった
 時点で、このページに戻った方が理解しやすいでしょう。


 PICは、割込み処理はひとつだけになっているので
 割込み処理コード(割込みハンドラと言います。)
 の中で、どういう種類の割込みが発生したのかを
 判断して、対応した処理を実行します。

 データシートの中にある、割込み信号生成回路をみれば
 どんな割込みができるのかを理解できます。



 個別モジュールごとに割込みを使うか否かと、割込み
 発生時の動作を、別途設定できる仕様です。
 注意するのは、どれかひとつでも、モジュールの割込み
 を使うときは、Global Interruptを許可すること。

 割込み信号生成回路で、最も右にあるANDに、GIEと個別の
 モジュールの割込み信号のOR出力を入力しています。

 図面から、Global Interruptを許可しないと、割込みの
 発生が、CPUに通知されないとわかります。

 具体的な割込みの初期化コードは、以下。

  /* initialize Timer 0 */
  {
    /* ??? */
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;

 mikroCの割込みハンドラは、次のように記述します。

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* ??? */
  }
}

 割込みハンドラは、関数interruptで扱います。

 Global Interruptがひとつだけと割込み信号生成
 回路でわかっているので、割込みハンドラも唯一
 です。

 割込みの発生を通知したモジュールが、フラグを
 セットするので該当モジュールのフラグがセット
 したかスキャンして、複数の割込みに対応します。

 割込みハンドラで使う時間は、極力短くした方がよい
 ので、イベントフラグを使い、main関数に通知して
 時間のかかる処理は、main関数の無限ループの中で
 他の関数に仕事を依頼する方が楽です。

 動作フローで示すと以下。



 イベントフラグをセットするのは、割込みハンドラ
 フラグのリセットは、main関数の無限ループの中で
 として、構造を単純にします。

 関数mainは、次のように記述。

void main(void)
{
  /* user initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* process A */
    if ( FLAGA == ON ) {
      /* clear */
      FLAGA = OFF ;
      /* ???  */
    }
    /* process B */
    if ( FLAGB == ON ) {
      /* clear */
      FLAGB = OFF ;
      /* ???  */
    }
    /* process C */
    if ( FLAGC == ON ) {
      /* clear */
      FLAGC = OFF ;
      /* ???  */
    }
  }
}

 ワンチップマイコンでは、使える内蔵メモリが
 少ないので、共用体を利用して1バイトの中に
 8個のフラグを用意して使えるようにします。

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGA xflags.BIT.B0
#define FLAGB xflags.BIT.B1
#define FLAGC xflags.BIT.B2
#define FLAGD xflags.BIT.B3

 この場合、4フラグを利用していますが
 初期化(ゼロクリア)は、1回で全部の
 フラグを扱えます。

xflags.DR = 0x00 ;

 フラグのセット、リセットは、変数と同様
 代入だけでOK。

FLAGA = ON  ;
FLAGB = OFF ;
FLAGC = OFF ;
FLAGD = ON  ;

 構造体、共用体は、C言語のテキストでは使い処が
 見えにくいため、説明に苦労しているようですが
 ワンチップマイコンのファームウエアで考えると
 わかるようになります。

 PIC16F627Aのタイマーは、3モジュールあり
 タイマー0、タイマー1、タイマー2と命名
 されてます。

 タイマー0のブロック図を見てみます。



 PICのタイマー0は、Watch Dog Timerと兼用で
 どちらを使うかをセレクタで指定可能。



 Watch Dog Timerを使う場合、WDT ENABLE BITをセットし
 同時にPSAを1にします。

 クロックソースを外部、システムクロックの1/4、Watch Dog Timer
 のどれかにします。外部からの場合、RA4(T0CKI)ピンを使います。



 クロックソースを決めたなら、プリスケーラで分周比を決めます。



 タイマー0で利用するカウンタは、8ビット。
 また、割込みはオーバーフローのみというのも
 ブロック図をみるとわかります。



 思い通りにタイマー0を使うには、関係レジスタに
 値を設定しなければ駄目。



 割込み関係は、INTCONレジスタのGIE、TOIEの2つ
 のビットとなります。

 タイマー0の初期設定は、以下。

  /* initialize Timer 0 */
  {
    /*
       4MHz/4 = 1MHz -> 1MHz/4 = 250kHz prescaler = 1:4
       all inputs are pull-up .
    */
    OPTION = 0x01 ;
    /* 256 - 250 = 6 */
    TMR0 = 6 ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;

 システムクロックの利用では、1/4になるので
 プリスケーラ経由でカウンタのクロックを使う
 ようにします。

 プリスケーラは、OPTIONレジスタの中にあるので
 次の分周比を設定。

 OPTIONレジスタのPSAは、Watch Dog Timerを使う場合
 1を設定します。

 クロックソースを、RA4ピンの入力とするなら、T0CSを1に設定。
 T0SEは、反転して入力するのか、そのままかを指定。

 割込みを使う場合オーバーフローにするので、カウンタ
 の値が、255から0に戻るとき、割込みが発生。

 この変化をINTCONのT0IFビットに反映させます。

 カラクリがわかれば、割込みハンドラ関数interrupt
 では、どの割込みが発生しているのかをスキャンし
 フラグのセットで通知する方式が妥当だと理解できる
 でしょう。

 カラクリがわかれば、関数interruptは次のように
 記述することになります。

void interrupt(void)
{
  /* timer0 overflow interrupt */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize */
    TMR0 = 6 ;
    /* set flag */
    FLAGA = ON ;
  }
}

 ここまでの内容を踏まえて、LEDをひとつ点滅する
 処理に、割込みを使ったコードは以下。

#define OFF 0
#define ON  OFF+1

#define STARTV  6
#define STIMMAX 625

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGA xflags.BIT.B0

volatile UBYTE state ;
volatile UWORD stim ;

/* prototype */
void usr_init(void);

void interrupt(void)
{
  /* timer0 overflow interrupt */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize */
    TMR0 = STARTV ;
    /* update counter */
    stim++ ;
    /* judge */
    if ( stim == STIMMAX ) {
      /* clear */
      stim = 0 ;
      /* set flag */
      FLAGA = ON ;
    }
  }
}

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* timer0 interrupt */
    if ( FLAGA == ON ) {
      /* clear flag */
      FLAGA = OFF ;
      /* impress */
      PORTB = state & ON ;
      /* update state */
      state++ ;
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear flag */
  xflags.DR = 0x00 ;
  /* clear state counter */
  state = 0 ;
  /* set sub counter */
  stim = 0 ;
  /* initialize Timer 0 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/16 = 156250Hz prescaler = 1:16
       156250Hz / 250 = 625 Hz
    */
    OPTION = 0x01 ;
    /* 256 - 250 = 6 */
    TMR0 = STARTV ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
}

 割込みを利用すると、コードは増えていきますが
 無駄時間をカウントで扱うことから解放されます。

 割込みを使うと、ひとつのマイコンで複数の仕事を
 扱えるようになります。

 ひとつの仕事のみとなれば、割込みを使わないで
 済みますが、1人の従業員に多くの作業をさせる
 のが、マイコンを使う側の論理です。

 タイマー1のブロック図を見ていきます。



 ブロック図から読み取れることをリスト。

 これらの情報を利用して、意図した動作をさせるために
 レジスタへの設定値を考えます。それには関係レジスタ
 の内容を理解します。

 関係レジスタの内容は、以下。



 T1CONレジスタのビット構成をみると、タイマー1は
 利用するか否かを指定できるよう。

 T1CONレジスタのTMR1ONビットで、モジュールに電源を
 与えるかカットするかを決めていると考えます。

 電源を与えなければ、そのモジュールは動作しないので
 その分だけ消費電力が減ります。

 TK1CKPS1、TK1CKPS1の組み合わせで、プリスケーラの
 分周比を決めることができます。2のベキ乗利用での
 設定になるので、シフト演算子で指定がよいでしょう。

 タイマー1を利用して、プリスケーラを1/2にするなら
 次のコードとなります。

    T1CON = (1 << 4) | 1 ;

 割込みは、PIE1(Peripheral Interrupt Enable)レジスタ
 のTMR1IEビットをセットし、カウンタのオーバーフロー
 で発生するようにします。
 Global Interruptを指定を忘れないよう、注意します。

 関数interruptの記述は、以下。

void interrupt(void)
{
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    FLAGB = ON ;
  }
}

 タイマー1の初期化は次のようにします。

  /* initialize Timer 1 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/8 = 312.5kHz prescaler = 1:8
    */
    T1CON = (3 << 4) | 1 ;
    /* 
      65536 - 62500
    */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;

 タイマー0で実現した内容を、タイマー1で
 置き換えてみます。

#define OFF 0
#define ON  OFF+1

#define STARTV 3036

typedef unsigned char  UBYTE ;

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGB xflags.BIT.B1

volatile UBYTE state ;

/* prototype */
void usr_init(void);

void interrupt(void)
{
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    FLAGB = ON ;
  }
}

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* timer1 interrupt */
    if ( FLAGB == ON ) {
      /* clear flag */
      FLAGB = OFF ;
      /* impress */
      PORTB = state & ON ;
      /* update state */
      state++ ;
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear flag */
  xflags.DR = 0x00 ;
  /* clear state counter */
  state = 0 ;
  /* initialize Timer 1 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/8 = 312.5kHz prescaler = 1:8
    */
    T1CON = (3 << 4) ;
    /* 
      65536 - 62500
    */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
    /* enable */
    T1CON |= 1 ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
}

 カウンタが16ビットになったので、8ビットレジスタの
 再設定には、2ステートメントが必要となりました。
 計算そのものは単純です。

 タイマー2のブロック図を見ていきます。



 ブロック図から読み取れることをリスト。

 これらの情報を利用して、意図した動作をさせるために
 レジスタへの設定値を考えます。それには関係レジスタ
 の内容を理解します。

 関係レジスタの内容は、以下。



 T2CONレジスタのビット構成から、タイマー2は利用するか
 しないを指定できると読めます。

 T2CONレジスタのTMR2ONビットで、モジュールに電源を
 与えるかカットするかを決めていると考えます。

 T2CONレジスタでプリスケーラ、ポストスケーラの分周比を
 一度に指定できるようになっています。

 プリスケーラは、1/1、1/4、1/16の分周比ですが、ビット
 の組み合わせは、00、01、10、11の4通り。この中で10と
 11が1/16の分周比とできます。

 ポストスケーラは、4ビットなので(分周比の値-1)を
 指定します。

 タイマー2の割込みを利用する場合、関数interruptは
 次のように定義すればよいでしょう。

void interrupt(void)
{
  /* timer2 compare match interrupt */
  if ( PIR1.TMR2IF == ON ) {
    /* clear flag */
    PIR1.TMR2IF = OFF ;
    /* ??? */
    /* set flag */
    FLAGC = ON ;
  }
}

 タイマー2の初期化は次のようにします。

  /* initialize Timer 2 */
  {
    /*
       prescalar 
         10MHz/4 = 2.5MHz -> 2.5MHz/16 = 156250Hz prescaler = 1:16
       postscalar 1:5 
    */
    T2CON = (4 << 3) | (1 << 2) | 3 ;
    /* clear counter */
    TMR2 = 0 ;
    /* set reference value 250 */
    PR2 = STARTV ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;

 タイマー0と同じ内容をタイマー2で実現すると、以下。

#define OFF 0
#define ON  OFF+1

#define STARTV  250
#define SCNTMAX 125

typedef unsigned char  UBYTE ;

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGC xflags.BIT.B2

volatile UBYTE state ;
volatile UBYTE scnt ;

/* prototype */
void usr_init(void);

void interrupt(void)
{
  /* timer2 compare match interrupt */
  if ( PIR1.TMR2IF == ON ) {
    /* clear flag */
    PIR1.TMR2IF = OFF ;
    /* update counter */
    scnt++ ;
    /* judge */
    if ( scnt == SCNTMAX ) {
      /* clear */
      scnt = 0 ;
      /* set flag */
      FLAGC = ON ;
    }
  }
}

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* timer2 interrupt */
    if ( FLAGC == ON ) {
      /* clear flag */
      FLAGC = OFF ;
      /* impress */
      PORTB = state & ON ;
      /* update state */
      state++ ;
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear flag */
  xflags.DR = 0x00 ;
  /* clear state counter */
  state = 0 ;
  /* clear sub counter */
  scnt = 0 ;
  /* initialize Timer 2 */
  {
    /*
       prescalar 
         10MHz/4 = 2.5MHz -> 2.5MHz/16 = 156250Hz prescaler = 1:16
       postscalar 1:5 
    */
    T2CON = (4 << 3) | 3 ;
    /* clear counter */
    TMR2 = 0 ;
    /* set reference value 250 */
    PR2 = STARTV ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
    /* enable */
    T2CON |= (1 << 2) ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
}

 ここまでで、関数mainの改変は通知フラグだけで
 よいと理解できると思います。

 どのタイマーを利用するかで、初期化と割込みハンドラの
 記述内容が変わります。関数mainの内容の一部改変だけに
 なっているとわかれば、割込みを使うのは面倒ではないと
 理解できるでしょう。

 方向指示器をタイマー割込みを利用して、書き直します。

 タイマー0による方向指示器

#define OFF 0
#define ON  OFF+1

#define STARTV  6
#define STIMMAX 625

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGA xflags.BIT.B0

volatile UBYTE state ;
volatile UWORD stim ;
volatile UBYTE pat[8] ;

/* prototype */
void usr_init(void);

void interrupt(void)
{
  /* timer0 overflow interrupt */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize */
    TMR0 = STARTV ;
    /* update counter */
    stim++ ;
    /* judge */
    if ( stim == STIMMAX ) {
      /* clear */
      stim = 0 ;
      /* set flag */
      FLAGA = ON ;
    }
  }
}

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* timer0 interrupt */
    if ( FLAGA == ON ) {
      /* clear flag */
      FLAGA = OFF ;
      /* impress */
      PORTB = *(pat+state) ;
      /* update */
      state++ ;
      if ( state == 8 ) { state = 0 ; }
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear flag */
  xflags.DR = 0x00 ;
  /* clear state counter */
  state = 0 ;
  /* set sub counter */
  stim = 0 ;
  /* store bit pattern */
  *(pat+0) = 0x01 ; *(pat+1) = 0x02 ;
  *(pat+2) = 0x04 ; *(pat+3) = 0x08 ;
  *(pat+4) = 0x10 ; *(pat+5) = 0x20 ;
  *(pat+6) = 0x40 ; *(pat+7) = 0x80 ;
  /* initialize Timer 0 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/16 = 156250Hz prescaler = 1:16
       156250Hz / 250 = 625 Hz
    */
    OPTION = 0x01 ;
    /* 256 - 250 = 6 */
    TMR0 = STARTV ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
}

 タイマー1による方向指示器

#define OFF 0
#define ON  OFF+1

#define STARTV 3036

typedef unsigned char  UBYTE ;

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGB xflags.BIT.B1

volatile UBYTE state ;
volatile UBYTE pat[8] ;

/* prototype */
void usr_init(void);

void interrupt(void)
{
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    FLAGB = ON ;
  }
}

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* timer1 interrupt */
    if ( FLAGB == ON ) {
      /* clear flag */
      FLAGB = OFF ;
      /* impress */
      PORTB = *(pat+state) ;
      /* update */
      state++ ;
      if ( state == 8 ) { state = 0 ; }
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear flag */
  xflags.DR = 0x00 ;
  /* clear state counter */
  state = 0 ;
  /* set sub counter */
  stim = 0 ;
  /* store bit pattern */
  *(pat+0) = 0x01 ; *(pat+1) = 0x02 ;
  *(pat+2) = 0x04 ; *(pat+3) = 0x08 ;
  *(pat+4) = 0x10 ; *(pat+5) = 0x20 ;
  *(pat+6) = 0x40 ; *(pat+7) = 0x80 ;
  /* initialize Timer 1 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/8 = 312.5kHz prescaler = 1:8
    */
    T1CON = (3 << 4) ;
    /* 
      65536 - 62500
    */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
    /* enable */
    T1CON |= 1 ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
}

 タイマー2による方向指示器

#define OFF 0
#define ON  OFF+1

#define STARTV  250
#define SCNTMAX 125

typedef unsigned char  UBYTE ;

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define FLAGC xflags.BIT.B2

volatile UBYTE state ;
volatile UBYTE scnt ;
volatile UBYTE pat[8] ;

/* prototype */
void usr_init(void);

void interrupt(void)
{
  /* timer2 compare match interrupt */
  if ( PIR1.TMR2IF == ON ) {
    /* clear flag */
    PIR1.TMR2IF = OFF ;
    /* update */
    scnt++ ;
    /* judge */
    if ( scnt == SCNTMAX ) {
      /* clear */
      scnt = 0 ;
      /* set flag */
      FLAGC = ON ;
    }
  }
}

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* timer2 interrupt */
    if ( FLAGC == ON ) {
      /* clear flag */
      FLAGC = OFF ;
      /* impress */
      PORTB = *(pat+state) ;
      /* update */
      state++ ;
      if ( state == 8 ) { state = 0 ; }
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear flag */
  xflags.DR = 0x00 ;
  /* clear state counter */
  state = 0 ;
  /* set sub counter */
  scnt = 0 ;
  /* store bit pattern */
  *(pat+0) = 0x01 ; *(pat+1) = 0x02 ;
  *(pat+2) = 0x04 ; *(pat+3) = 0x08 ;
  *(pat+4) = 0x10 ; *(pat+5) = 0x20 ;
  *(pat+6) = 0x40 ; *(pat+7) = 0x80 ;
  /* initialize Timer 2 */
  {
    /*
       prescalar 
         10MHz/4 = 2.5MHz -> 2.5MHz/16 = 156250Hz prescaler = 1:16
       postscalar 1:5 
    */
    T2CON = (4 << 3) | 3 ;
    /* clear counter */
    TMR2 = 0 ;
    /* set reference value 250 */
    PR2 = STARTV ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
    /* enable */
    T2CON |= (1 << 2) ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
}


目次

inserted by FC2 system