目次

モーターを回す(割込み利用)

 複数のモータを一度に動かすことを扱いますが、DUTY比と
 回転方向を同時に変更できるようにします。

 利用するシステムは、以下。



 スイッチには、次の機能を持たせます。

 ポートBの下位4ビットを入力に、上位4ビットを出力に設定。

  TRISB = 0x0f ;

 PWMで回転を制御するには、DUTY比を変えます。

 DUTY比は0%から99%になるので、内部カウンタを用意して
 タイマー割込みが発生するたびに、増やしていきます。

 カウンタを定義しておけば、割込みハンドラは次のように
 記述できます。

#define PCNTMAX 100

typedef unsigned char UBYTE ;

UBYTE pcnt ;

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* increment */
    pcnt++ ;
    /* judge */
    if ( pcnt == PCNTMAX ) {
      pcnt = 0 ;
    }
  }
}

 DUTY比は、1サイクルにおける'1'の数と考えれば
 カウンタの最大値が100なら、次のようにピン出力
 を指定すればよくなります。

  /* compare */
  lout = OFF ;
  if ( pcnt < lcntx ) {
    lout = ON ;
  }
  /* impress */
  PORTB.F4 = lout ;

 このカラクリでみると、回転数を変えるということは
 変数lcntxの値を増減させることと等価になります。

 スイッチでモータの回転数を増減するには、スイッチの
 0から1(1から0)の変化を捉えて、対応する変数値
 を増減するとなります。

 4つのスイッチの変化を、フラグで表現すると動作を
 制御できます。

  /* endless loop */
  while (ON) {
    /* run or stop */
    if ( RFLAG == ON ) {
      /* clear flag */
      RFLAG = OFF ;
      /* update */
      if ( state == RUN ) {
        state = IDLE ;
      } else {
        state = RUN ;
      }
    }
    /* direction */
    if ( DFLAG == ON ) {
      /* clear flag */
      DFLAG = OFF ;
      /* change */
      dcnt++ ;
      /* get LSB */
      dcnt &= ON ;
    }
    /* increment */
    if ( PFLAG == ON ) {
      /* clear flag */
      PFLAG = OFF ;
      /* change */
      lcnt++ ;
      /* judge */
      if ( lcnt > LCNTMAX ) {
        lcnt = LCNTMAX ;
      }
    }
    /* decrement */
    if ( MFLAG == ON ) {
      /* clear flag */
      MFLAG = OFF ;
      /* change */
      if ( lcnt > 0 ) {
        lcnt-- ;
      }
    }
  }

 上のコードから、フラグを用意することになるので定義します。

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 RFLAG xflags.BIT.B0
#define DFLAG xflags.BIT.B1
#define PFLAG xflags.BIT.B2
#define MFLAG xflags.BIT.B3

 スイッチの変化があったことは、シフトレジスタを利用して検出します。

  if ( TFLAG == ON ) {
    /* clear flag */
    TFLAG = OFF ;
    /* shift */
    rsft <<= 1;
    dsft <<= 1;
    psft <<= 1;
    msft <<= 1;
    /* update */
    if ( PORTB.F0 == SWON ) { rsft |= ON ; }
    if ( PORTB.F1 == SWON ) { dsft |= ON ; }
    if ( PORTB.F2 == SWON ) { psft |= ON ; }
    if ( PORTB.F3 == SWON ) { msft |= ON ; }
    /* judge */
    if ( rsft == 0x01 ) { RFLAG = ON ; }
    if ( dsft == 0x01 ) { DFLAG = ON ; }
    if ( psft == 0x01 ) { PFLAG = ON ; }
    if ( msft == 0x01 ) { MFLAG = ON ; }
  }

 シフトレジスタを利用するときは、タイマー割込みでチャタリングを
 除去できる程度のインターバルを用意して対応します。

 割込みハンドラで、次のようにタイマー割込み発生を扱います。

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* increment */
    pcnt++ ;
    /* judge */
    if ( pcnt == PCNTMAX ) {
      pcnt = 0 ;
    }
  }
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    TFLAG = ON ;
  }
}

 main関数をまとめてみます。

void main(void)
{
  /* initialize */
  usr_init();
  /* endless loop */
  while (ON) {
    /* switch handling */
    if ( TFLAG == ON ) {
      /* clear flag */
      TFLAG = OFF ;
      /* shift */
      rsft <<= 1;
      dsft <<= 1;
      psft <<= 1;
      msft <<= 1;
      /* update */
      if ( PORTB.F0 == SWON ) { rsft |= ON ; }
      if ( PORTB.F1 == SWON ) { dsft |= ON ; }
      if ( PORTB.F2 == SWON ) { psft |= ON ; }
      if ( PORTB.F3 == SWON ) { msft |= ON ; }
      /* judge */
      if ( rsft == 0x01 ) { RFLAG = ON ; }
      if ( dsft == 0x01 ) { DFLAG = ON ; }
      if ( psft == 0x01 ) { PFLAG = ON ; }
      if ( msft == 0x01 ) { MFLAG = ON ; }
    }
    /* run or stop */
    if ( RFLAG == ON ) {
      /* clear flag */
      RFLAG = OFF ;
      /* update */
      if ( state == RUN ) {
        state = IDLE ;
      } else {
        state = RUN ;
      }
    }
    /* direction */
    if ( DFLAG == ON ) {
      /* clear flag */
      DFLAG = OFF ;
      /* change */
      dcnt++ ;
      /* get LSB */
      dcnt &= ON ;
      /* standby stop */
      PORTB.F4 = OFF ;
      PORTB.F5 = OFF ;
    }
    /* increment */
    if ( PFLAG == ON ) {
      /* clear flag */
      PFLAG = OFF ;
      /* change */
      lcnt++ ;
      /* judge */
      if ( lcnt > LCNTMAX ) {
        lcnt = LCNTMAX ;
      }
    }
    /* decrement */
    if ( MFLAG == ON ) {
      /* clear flag */
      MFLAG = OFF ;
      /* change */
      if ( lcnt > 0 ) {
        lcnt-- ;
      }
    }
    /* motor control */
    if ( state == IDLE ) {
      PORTB.F4 = OFF ;
      PORTB.F5 = OFF ;
    } else {
      /* set value */
      lout = OFF ;
      if ( pcnt < lcntx ) { lout = ON ; }
      /* impress */
      if ( dcnt ) {
        PORTB.F5 = lout ;
        PORTB.F4 = OFF  ;
      } else {
        PORTB.F5 = OFF  ;
        PORTB.F4 = lout ;
      }
    }
  }
}

 回転数を扱う変数は、2種用意します。
 ひとつだけだと、回転数を変えたときに挙動がおかしくなります。
 2種の変数を用意したなら、割込みハンドラは、次のように変更。

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* increment */
    pcnt++ ;
    /* judge */
    if ( pcnt == PCNTMAX ) {
      pcnt = 0 ;
      lcntx = lcnt ;
    }
  }
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    TFLAG = ON ;
  }
}

 初期設定を考えていきます。

 シフトレジスタ
  4つのシフトレジスタをゼロクリアします。

    rsft = 0 ;
    dsft = 0 ;
    psft = 0 ;
    msft = 0 ;

 フラグ類
  フラグ類は、共用体で定義してあるので1行ですみます。

    xflags.DR = 0 ;

 状態変数
  状態変数は、モータを回すか、止めるかなので
  パワーオンでは、止めた状態にします。

    state = IDLE ;

  文字列を利用してわかりやすくしておきます。

 PWM関係変数
  4つの変数をゼロクリアします。

    pcnt = 0 ;
    lcnt = 0 ;
    lcntx = 0 ;
    lout = OFF ;

 タイマー0
  タイマー0は、PWMのDUTY比を担当するので1kHz程度で
  カウンタを動かせるようにパラメータを設定します。
  また、オーバーフロー割込みを指定。

    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/8 = 312.5kHz prescaler = 1:8
    */
    OPTION_REG = 0x02 ;
    /* 256 - 250 = 6 */
    TMR0 = SINTX ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;

 タイマー1
  タイマー1は、スイッチのチャタリング除去のための
  タイミングを生成するので、10Hz程度で周期を扱うと
  します。
  タイマー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 ;

 まとめると、以下。

#define OFF 0
#define ON  OFF+1

#define IDLE 0
#define RUN  IDLE+1

#define SWON  0
#define SWOFF SWON+1

#define PCNTMAX 100
#define LCNTMAX 100

#define STARTV 62500

#define SINTX 6

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 RFLAG xflags.BIT.B0
#define DFLAG xflags.BIT.B1
#define PFLAG xflags.BIT.B2
#define MFLAG xflags.BIT.B3
#define TFLAG xflags.BIT.B4

typedef unsigned char UBYTE ;

volatile UBYTE rsft ;
volatile UBYTE dsft ;
volatile UBYTE psft ;
volatile UBYTE msft ;

volatile UBYTE state ;

volatile UBYTE dcnt ;
volatile UBYTE pcnt ;
volatile UBYTE lcnt ;
volatile UBYTE lcntx ;
volatile UBYTE lout ;

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* 256 - 250 = 6 */
    TMR0 = SINTX ;
    /* increment */
    pcnt++ ;
    /* judge */
    if ( pcnt == PCNTMAX ) {
      pcnt = 0 ;
      lcntx = lcnt ;
    }
  }
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    TFLAG = ON ;
  }
}

/* prototype */
void usr_init(void);

void main(void)
{
  /* initialize */
  usr_init();
  /* endless loop */
  while (ON) {
    /* switch handling */
    if ( TFLAG == ON ) {
      /* clear flag */
      TFLAG = OFF ;
      /* shift */
      rsft <<= 1;
      dsft <<= 1;
      psft <<= 1;
      msft <<= 1;
      /* update */
      if ( PORTB.F0 == SWON ) { rsft |= ON ; }
      if ( PORTB.F1 == SWON ) { dsft |= ON ; }
      if ( PORTB.F2 == SWON ) { psft |= ON ; }
      if ( PORTB.F3 == SWON ) { msft |= ON ; }
      /* judge */
      if ( rsft == 0x01 ) { RFLAG = ON ; }
      if ( dsft == 0x01 ) { DFLAG = ON ; }
      if ( psft == 0x01 ) { PFLAG = ON ; }
      if ( msft == 0x01 ) { MFLAG = ON ; }
    }
    /* run or stop */
    if ( RFLAG == ON ) {
      /* clear flag */
      RFLAG = OFF ;
      /* update */
      if ( state == RUN ) {
        state = IDLE ;
      } else {
        state = RUN ;
      }
    }
    /* direction */
    if ( DFLAG == ON ) {
      /* clear flag */
      DFLAG = OFF ;
      /* change */
      dcnt++ ;
      /* get LSB */
      dcnt &= ON ;
      /* standby stop */
      PORTB.F4 = OFF ;
      PORTB.F5 = OFF ;
    }
    /* increment */
    if ( PFLAG == ON ) {
      /* clear flag */
      PFLAG = OFF ;
      /* change */
      lcnt++ ;
      /* judge */
      if ( lcnt > LCNTMAX ) {
        lcnt = LCNTMAX ;
      }
    }
    /* decrement */
    if ( MFLAG == ON ) {
      /* clear flag */
      MFLAG = OFF ;
      /* change */
      if ( lcnt > 0 ) {
        lcnt-- ;
      }
    }
    /* motor control */
    if ( state == IDLE ) {
      PORTB.F4 = OFF ;
      PORTB.F5 = OFF ;
    } else {
      /* set value */
      lout = OFF ;
      if ( pcnt < lcntx ) { lout = ON ; }
      /* impress */
      if ( dcnt ) {
        PORTB.F5 = lout ;
        PORTB.F4 = OFF  ;
      } else {
        PORTB.F5 = OFF  ;
        PORTB.F4 = lout ;
      }
    }
  }
}

void usr_init(void)
{
  /* stop motor */
  PORTB.F4 = OFF ;
  PORTB.F5 = OFF ;
  /* direction */
  TRISB = 0x0f ;
  /* clear flags */
  xflags.DR = 0 ;
  /* clear shift register */
  rsft = 0 ;
  dsft = 0 ;
  psft = 0 ;
  msft = 0 ;
  /* set state value */
  state = IDLE ;
  /*  PWM duty ratio */
  pcnt = 0 ;
  lcnt = 0 ;
  lcntx = 0 ;
  lout = OFF ;
  /* initialize Timer 0 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/8 = 312.5kHz prescaler = 1:8
    */
    OPTION_REG = 0x02 ;
    /* 256 - 250 = 6 */
    TMR0 = SINTX ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* 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 ;
}

 ひとつのマイコンで2モータを制御するシステムを考えます。



 トグルスイッチを用意して、どちらのモータに対する
 指定なのかを判断できるようにします。

    /* run or stop */
    if ( RFLAG == ON ) {
      /* clear flag */
      RFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* update */
        if ( lstate == RUN ) {
          lstate = IDLE ;
        } else {
          lstate = RUN ;
        }
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* update */
        if ( rstate == RUN ) {
          rstate = IDLE ;
        } else {
          rstate = RUN ;
        }
      }
    }
    /* direction */
    if ( DFLAG == ON ) {
      /* clear flag */
      DFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* change */
        ldcnt++ ;
        /* get LSB */
        ldcnt &= ON ;
        /* standby stop */
        PORTB.F6 = OFF ;
        PORTB.F7 = OFF ;
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* change */
        rdcnt++ ;
        /* get LSB */
        rdcnt &= ON ;
        /* standby stop */
        PORTB.F4 = OFF ;
        PORTB.F5 = OFF ;
      }
    }
    /* increment */
    if ( PFLAG == ON ) {
      /* clear flag */
      PFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* change */
        lcnt++ ;
        /* judge */
        if ( lcnt > LCNTMAX ) {
          lcnt = LCNTMAX ;
        }
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* change */
        rcnt++ ;
        /* judge */
        if ( rcnt > LCNTMAX ) {
          rcnt = LCNTMAX ;
        }
      }
    }
    /* decrement */
    if ( MFLAG == ON ) {
      /* clear flag */
      MFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* change */
        if ( lcnt > 0 ) {
          lcnt-- ;
        }
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* change */
        if ( rcnt > 0 ) {
          rcnt-- ;
        }
      }
    }
    /* left motor control */
    if ( lstate == IDLE ) {
      PORTB.F6 = OFF ;
      PORTB.F7 = OFF ;
    } else {
      /* set value */
      lout = OFF ;
      if ( pcnt < lcntx ) { lout = ON ; }
      /* impress */
      if ( ldcnt ) {
        PORTB.F6 = lout ;
        PORTB.F7 = OFF  ;
      } else {
        PORTB.F6 = OFF  ;
        PORTB.F7 = lout ;
      }
    }
    /* right motor control */
    if ( rstate == IDLE ) {
      PORTB.F4 = OFF ;
      PORTB.F5 = OFF ;
    } else {
      /* set value */
      lout = OFF ;
      if ( pcnt < rcntx ) { lout = ON ; }
      /* impress */
      if ( rdcnt ) {
        PORTB.F5 = lout ;
        PORTB.F4 = OFF  ;
      } else {
        PORTB.F5 = OFF  ;
        PORTB.F4 = lout ;
      }
    }

 2つのモータのDUTY比を更新するので、割込みハンドラも
 変更します。

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* 256 - 250 = 6 */
    TMR0 = SINTX ;
    /* increment */
    pcnt++ ;
    /* judge */
    if ( pcnt == PCNTMAX ) {
      pcnt = 0 ;
      lcntx = lcnt ;
      rcntx = rcnt ;
    }
  }
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    TFLAG = ON ;
  }
}

 まとめると、以下。

#define OFF 0
#define ON  OFF+1

#define IDLE 0
#define RUN  IDLE+1

#define SWON  0
#define SWOFF SWON+1

#define PCNTMAX 100
#define LCNTMAX 100

#define STARTV 62500

#define SINTX 6

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 RFLAG xflags.BIT.B0
#define DFLAG xflags.BIT.B1
#define PFLAG xflags.BIT.B2
#define MFLAG xflags.BIT.B3
#define TFLAG xflags.BIT.B4

typedef unsigned char UBYTE ;

volatile UBYTE rsft ;
volatile UBYTE dsft ;
volatile UBYTE psft ;
volatile UBYTE msft ;

volatile UBYTE lstate ;
volatile UBYTE rstate ;

volatile UBYTE ldcnt ;
volatile UBYTE rdcnt ;
volatile UBYTE pcnt ;
volatile UBYTE lcnt ;
volatile UBYTE lcntx ;
volatile UBYTE rcnt ;
volatile UBYTE rcntx ;
volatile UBYTE lout ;

void interrupt(void)
{
  /* timer0 overflow */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* 256 - 250 = 6 */
    TMR0 = SINTX ;
    /* increment */
    pcnt++ ;
    /* judge */
    if ( pcnt == PCNTMAX ) {
      pcnt = 0 ;
      lcntx = lcnt ;
      rcntx = rcnt ;
    }
  }
  /* timer1 overflow interrupt */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = STARTV % 256 ;
    TMR1H = STARTV / 256 ;
    /* set flag */
    TFLAG = ON ;
  }
}

/* prototype */
void usr_init(void);

void main(void)
{
  /* initialize */
  usr_init();
  /* endless loop */
  while (ON) {
    /* switch handling */
    if ( TFLAG == ON ) {
      /* clear flag */
      TFLAG = OFF ;
      /* shift */
      rsft <<= 1;
      dsft <<= 1;
      psft <<= 1;
      msft <<= 1;
      /* update */
      if ( PORTB.F0 == SWON ) { rsft |= ON ; }
      if ( PORTB.F1 == SWON ) { dsft |= ON ; }
      if ( PORTB.F2 == SWON ) { psft |= ON ; }
      if ( PORTB.F3 == SWON ) { msft |= ON ; }
      /* judge */
      if ( rsft == 0x01 ) { RFLAG = ON ; }
      if ( dsft == 0x01 ) { DFLAG = ON ; }
      if ( psft == 0x01 ) { PFLAG = ON ; }
      if ( msft == 0x01 ) { MFLAG = ON ; }
    }
    /* run or stop */
    if ( RFLAG == ON ) {
      /* clear flag */
      RFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* update */
        if ( lstate == RUN ) {
          lstate = IDLE ;
        } else {
          lstate = RUN ;
        }
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* update */
        if ( rstate == RUN ) {
          rstate = IDLE ;
        } else {
          rstate = RUN ;
        }
      }
    }
    /* direction */
    if ( DFLAG == ON ) {
      /* clear flag */
      DFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* change */
        ldcnt++ ;
        /* get LSB */
        ldcnt &= ON ;
        /* standby stop */
        PORTB.F6 = OFF ;
        PORTB.F7 = OFF ;
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* change */
        rdcnt++ ;
        /* get LSB */
        rdcnt &= ON ;
        /* standby stop */
        PORTB.F4 = OFF ;
        PORTB.F5 = OFF ;
      }
    }
    /* increment */
    if ( PFLAG == ON ) {
      /* clear flag */
      PFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* change */
        lcnt++ ;
        /* judge */
        if ( lcnt > LCNTMAX ) {
          lcnt = LCNTMAX ;
        }
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* change */
        rcnt++ ;
        /* judge */
        if ( rcnt > LCNTMAX ) {
          rcnt = LCNTMAX ;
        }
      }
    }
    /* decrement */
    if ( MFLAG == ON ) {
      /* clear flag */
      MFLAG = OFF ;
      /* left motor */
      if ( PORTA.F4 == ON ) {
        /* change */
        if ( lcnt > 0 ) {
          lcnt-- ;
        }
      }
      /* right motor */
      if ( PORTA.F4 == OFF ) {
        /* change */
        if ( rcnt > 0 ) {
          rcnt-- ;
        }
      }
    }
    /* left motor control */
    if ( lstate == IDLE ) {
      PORTB.F6 = OFF ;
      PORTB.F7 = OFF ;
    } else {
      /* set value */
      lout = OFF ;
      if ( pcnt < lcntx ) { lout = ON ; }
      /* impress */
      if ( ldcnt ) {
        PORTB.F6 = lout ;
        PORTB.F7 = OFF  ;
      } else {
        PORTB.F6 = OFF  ;
        PORTB.F7 = lout ;
      }
    }
    /* right motor control */
    if ( rstate == IDLE ) {
      PORTB.F4 = OFF ;
      PORTB.F5 = OFF ;
    } else {
      /* set value */
      lout = OFF ;
      if ( pcnt < rcntx ) { lout = ON ; }
      /* impress */
      if ( rdcnt ) {
        PORTB.F5 = lout ;
        PORTB.F4 = OFF  ;
      } else {
        PORTB.F5 = OFF  ;
        PORTB.F4 = lout ;
      }
    }
  }
}

void usr_init(void)
{
  /* stop motor */
  PORTB.F4 = OFF ;
  PORTB.F5 = OFF ;
  PORTB.F6 = OFF ;
  PORTB.F7 = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x0f ;
  /* clear flags */
  xflags.DR = 0 ;
  /* clear shift register */
  rsft = 0 ;
  dsft = 0 ;
  psft = 0 ;
  msft = 0 ;
  /* set state value */
  lstate = IDLE ;
  rstate = IDLE ;
  /* PWM duty ratio */
  pcnt = 0 ;
  lcnt = 0 ;
  lcntx = 0 ;
  rcnt = 0 ;
  rcntx = 0 ;
  lout = OFF ;
  /* initialize Timer 0 */
  {
    /*
       10MHz/4 = 2.5MHz -> 2.5MHz/8 = 312.5kHz prescaler = 1:8
    */
    OPTION_REG = 0x02 ;
    /* 256 - 250 = 6 */
    TMR0 = SINTX ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* 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 ;
}

 使っているフラッシュROMと内蔵メモリの容量は、それぞれ32%、10%と
 なっているので、最大容量まで余裕があります。

 イベントフラグを利用し、対応する処理を入れていけば、より
 複雑なシステムを構築できるようになります。

 割込みの基本は、タイマー割込みなので、ワンチップマイコンは
 複数個のタイマーを用意していることが多いです。


目次

inserted by FC2 system