文字数の関係の記事を2つに分けています。今回は前回の続きです。

サンプルプログラム

 今回のサンプルプログラムは、「frequency」変数に入力した周波数(パルス)数でステッピングモータを回転させるプログラムです。回転数に応じてduty比を変化させており、2相励磁となっています。

 

#include <avr/io.h>

#include <avr/interrupt.h>//割り込みのライブラリ

 

void setSquareWave(int freq); //矩形波の周波数設定

 

volatile uint8_t vect = 0;//角度

volatile uint8_t duty_h = 0;//duty125以上

volatile int frequency = 500;

 

volatile double duty = 0;

uint8_t PD[5] = {0x08, 0x20, 0x00, 0x40, 0x08};//ステッピングモータ励磁状態の配列

uint8_t PB[5] = {0x00, 0x00, 0x08, 0x00, 0x00};//この値をPORTに入れる

 

int main(void)

{

         DDRD = 0x68;//PWMピンを出力設定

         DDRB = 0x0F;

               

         //矩形波生成タイマー設定

         TCCR1A = 0x03; //PWM出力なし位相/周波数基準 OCR1A max

         TCCR1B = 0x1B; // 64分周

         TIMSK1 = 0x00; //割り込み停止

         setSquareWave(frequency);//周波数セット

         sei();//割り込み開始

       

    while (1)

    {

    }

}

 

void setSquareWave(int freq) {

  if (freq < 500) duty = 80; //duty比設定//90

  else if (freq < 1000) duty = 120;//120

  else if (freq < 1500) duty = 190;//150

  else duty = 230;//200

 

  if (freq != 0) { //動作

    TIMSK1 = 0x00;  //割り込み禁止

    //TCCR1B = 0x1B;//64分周 /2 250,000回カウント

    OCR1A = (unsigned int)(250000 / freq) ; //割り込み周波数

        if(duty <= 125){ //duty比が低い時(実質1相励磁)

                OCR1B = OCR1A * (duty / 125.0);

                duty_h = 0;//duty

        }else {//duty比が高い時(2相励磁)

                OCR1B = OCR1A * ((duty -125.0) / 125.0);

                duty_h = 1;//duty

        }

   

    TIMSK1 = 0x05;//OVFと比較Bの割り込み許可

   

    DDRC = 0x00;//出力オフ(Hi-Z)

 

  } else  { //停止

    TIMSK1 = 0x00;  //割り込みなし

    PORTD &= ~0x68;

    PORTB &= ~0x08;//出力L

    DDRC = 0x0F;//出力ダウン

  }

}

 

ISR(TIMER1_OVF_vect) { //オーバーフロー割り込み

        vect++; //進める

        if (vect > 4) vect = 1; //OVF

        PORTD |= PD[vect];

        PORTB |= PB[vect]; //出力

 

}

 

ISR(TIMER1_COMPB_vect) { //矩形波割り込み

        if(duty_h){

                PORTD &= ~PD[vect - 1];//1つ前の出力OFF

                PORTB &= ~PB[vect - 1];//1相励磁

        }else{

                PORTD &= ~PD[vect];//出力OFF

                PORTB &= ~PB[vect];//1相励磁

        }

       

}

 基本的なレジスタ設定はPWM出力に準じています。また、ステッピングモータのduty比の設定は溢れ割り込みと比較一致割り込みを組み合わせることで実現しています。ステッピングモータの励磁状態は配列に入れた値を使うことで処理の簡略化を実現しています。

そして、割り込みを使用するにあたって注意しなければならないのが、割り込み用のライブラリである<avr/interrupt.h>を読み込まなければならないことと、割り込み処理はISR(*****)」の関数を使う必要があるということです。また、ISR関数の引数(*****)(マクロともいう)は割り込みの種類ごとに異なるので注意しなければなりません。Atmega328Pにおけるタイマー割り込みの場合はISR関数の引数は以下の表のようになります。

8

割り込み処理の内容はISR関数に上の表の引数を入れること(サンプルプログラム参照)で実行ができます。ここで引数を間違うと割り込み処理ができないので注意が必要です。(コンパイルが通る場合もあるので注意)

以上でタイマー割り込みの設定は終わりです。次回は割り込み処理の引数(マクロ名)の探し方を紹介したいと思います。