サンプルプログラム
今回のサンプルプログラムは、「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関数の引数は以下の表のようになります。
割り込み処理の内容はISR関数に上の表の引数を入れること(サンプルプログラム参照)で実行ができます。ここで引数を間違うと割り込み処理ができないので注意が必要です。(コンパイルが通る場合もあるので注意)
以上でタイマー割り込みの設定は終わりです。次回は割り込み処理の引数(マクロ名)の探し方を紹介したいと思います。