1

AVR – MEGA8のタイマ/カウンタ0割り込み

今日もatmega8。SIG_OVERFLOW0でのタイマ/カウンタ割込みをやってみたよDSC00830.jpg

PB0のLED点滅はタイマー割り込みで行う。同時にmain()の中のループで、UARTで文字列を送信する。→ソースコード(AVR-GCC)動画(2.1MB)

タイマ/カウンタ0は8bit。mega8には他に16bitのタイマ/カウンタ1(PWM付き)と8bitのタイマ/カウンタ2(PWM付き)があり、3つとも別のタイミングで割り込みを発生させる事ができる。

でもまだ1と2は使ってない。

タイマ0の精度として、TCCR0レジスタで分周率を設定する。

HERO’s Downloadさんより

■やり方

タイマ/カウンタ0の設定関数

/* タイマ/カウンタ0オーバーフロー割り込み設定  */
void overflow0_init(){
TCNT0 = 0; // タイマ0初期値
TCCR0 = (0<<CS02)|(0<<CS01)|(1<<CS00); // 分周率設定 前置分周無し
sbi(TIMSK,TOIE0); // タイマ/カウンタ0オーバーフロー割り込み許可
}

これをmain()から呼び出す。

int main(void){
port_init(); // PORT設定
usart_init(MYUBRR); // USART設定
overflow0_init(); // タイマ/カウンタ0設定
sei(); // 割り込み許可
for(;;){
uart_send_str(&qute;hoge\0&qute;);
}
}

sei(); を忘れずに。

んで割り込み部分

volatile unsigned int led0;
/* タイマ/カウンタ0オーバーフロー割り込み */
SIGNAL(SIG_OVERFLOW0){
led0++;
if(led0 > 1500) LED_SET(); // LED点灯
else LED_CLR(); // LED消灯
if(led0 == 3000){
led0 = 0; // カウント初期化
}
nop(1); // これ入れないと固まる
}

よくわからないけど、nop(int count); という自分で用意した関数を呼び出さないと、main()の中の処理を巻き込んで止まる。

多重割り込みとか?

一応nopの中身

/* No Operation */
void nop(int count){
int i;
for(i = 0; i < count*100; i++){
}
}

そういえばDigi-Key、mega8値上がりしてますか?mega48のが安くなってますね。mega88と同じぐらいの値段。次実装するとしたらmega88かな

PWM6個あるし

2

AVR – MEGA8の外部入力割り込み

90S2313での外部入力割り込みに続いて、ATMEGA8でも外部入力割り込み SIG_INTERRUPT0, SIG_INTERRUPT1 を使った。

DSC00816.jpg

INT0、INT1への割り込みをSIG_INTERRUPT0、SIG_INTERRUPT1でそれぞれ受け取り、立ち上がりエッジ/立ち下がりエッジで2つのLEDを点灯/消灯させる。→ソースコード(AVR-GCC)動画(3MB)

90S2313は立ち上がり/立ち下がりのどちらかしか検出できなかったのでプログラムでなんとかしていたが、mega8は論理変換を検出(つまり両エッジ)できるので全然簡単になっている。というかそれ以外全部同じだったので一発で動いた。

データシートの翻訳版より

MCUCR(MCU制御レジスタ)の割り込み発生条件制御ビット表

■やり方

INT0を設定する関数を作った。

/* INT0設定 */
void interrupt0_init(void){
cbi(DDRD,PD2); // INT0入力設定
sbi(GICR,INT0); // INT0割り込み許可
sbi(GIFR,INT0); // INT0割り込み要求フラグON
/* 両エッジ検出 */
sbi(MCUCR,ISC00);
cbi(MCUCR,ISC01);
/* 立ち上がりエッジ検出
sbi(MCUCR,ISC01);
sbi(MCUCR,ISC00);
*/
/* 立ち下がりエッジ検出
sbi(MCUCR,ISC01);
cbi(MCUCR,ISC00);
*/
}

main()で呼び出して、すぐsei();して有効にしておく。

そして割り込み部分。

/* INT0 外部割り込み */
SIGNAL(SIG_INTERRUPT0){
if(bit_is_set(PIND,PD2)){ // 立ち上がりの時
LED1_SET(); // LED1点灯
}
else{ // 立ち下がりの時
LED1_CLR(); // LED1消灯
}
}

INT1の方も全く同様に書いてある。