PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega16 - Zwei Timer verwenden. - Nur einer funktioniert



Kesandal
21.06.2011, 20:10
Hallo,

mal wieder ein µC Problem :D


Zunächst mein Quelltext (habe den der einfachheithalber auf ein Minimum reduziert):




#include <avr/io.h>

#define LCD_PORT PORTC

#include "display.inc"
#include <avr/interrupt.h>


int main(){


DDRC=0xff;
DDRA=0x00;
DDRD=(1<<PD5); // sound output

TCCR0=(1<<WGM01)|(1<<CS02)|(1<<CS00); // pr 1024 - ctc => 3600hz

TCCR1A = (1<<COM1A0);
TCCR1B= (1<<WGM12)|(1<<CS10); // pr 1024 - ctc
TIMSK = (1<<OCIE1A)|(1<<OCIE0);



TCNT0=0;

TCNT1=0;


OCR1A=0;

OCR0=200; // *18 = 3600 => 1sekunde


DDRB=0xff;
PORTB=0xff;

sei();

while(1){
}

return 0;
}




ISR(TIMER1_COMPA_vect){
PORTB=0x0f;
}


ISR(TIMER0_COMP_vect){
PORTB=0xf0;


}



Was es tun soll: Ich möchte mit Timer0 und Timer1 arbeiten.

Problem: Es wird nur die ISR von Timer1 aufgerufen. Die Timer0-ISR wird nie aufgerufen.
Kommentiere ich oben die TCCR1[A|B] aus, funktioniert die ISR vom Timer0.


Habe ich irgendwas elementares einfach übersehen? :(



Danke im Voraus
Kesandal

Martinius11
22.06.2011, 00:11
ich hab mal im daten blatt gesucht
Zu TCNT0 steht folgendens wo wahrscheinlich auch das Problem liegt:

The Timer/Counter Register gives direct access, both for read and write operations, to the
Timer/Counter unit 8-bit counter. Writing to the TCNT0 Register blocks (removes) the compare
match on the following timer clock. Modifying the counter (TCNT0) while the counter is running,
introduces a risk of missing a compare match between TCNT0 and the OCR0 Register.

Also setzt TCNT0 = 0; bevor du den Timer startest

mfG _Martinius_

Kesandal
22.06.2011, 00:35
Danke für Deine Antwort..

hmm...
wo starte ich denn den Timer?
Indem ich die TCCR-Register beschreibe?

Gruß
kesandal

Martinius11
22.06.2011, 01:12
hier:


TCCR0=(1<<WGM01)|(1<<CS02)|(1<<CS00); // pr 1024 - ctc => 3600hz

Kesandal
22.06.2011, 08:05
hier:


TCCR0=(1<<WGM01)|(1<<CS02)|(1<<CS00); // pr 1024 - ctc => 3600hz

Habe es ausprobiert.
Die ISR von Timer 0 wird jedoch nach wie vor nicht aufgerufen :(




#include <avr/io.h>
#include <avr/interrupt.h>

int main(){

DDRC=0xff;
DDRA=0x00;
DDRD=(1<<PD5); // sound output

TCNT0=0;
TCNT1=0;

TCCR0=(1<<WGM01)|(1<<CS02)|(1<<CS00); // pr 1024 - ctc => 3600hz

TCCR1A = (1<<COM1A0);
TCCR1B= (1<<WGM12)|(1<<CS10); // pr 1024 - ctc
TIMSK = (1<<OCIE1A)|(1<<OCIE0);



OCR1A=0;
OCR0=200; // *18 = 3600 => 1sekunde

DDRB=0xff;
PORTB=0xff;
sei();
while(1){
}
return 0;
}


ISR(TIMER1_COMPA_vect){
// PORTB=0x0f;
}

ISR(TIMER0_COMP_vect){
PORTB=0xf0;

}

Martinius11
22.06.2011, 13:25
Lösung gefunden du muss noch

TIFR = (1<<OCF0);

einfügen

Kesandal
24.06.2011, 10:07
Auch das funktioniert leider nicht :(


Zum OCF0 bit steht folgendes im Manual:


The OCF0 bit is set (one) when a compare match occurs between the Timer/Counter0 and the
data in OCR0 – Output Compare Register0.

Searcher
24.06.2011, 11:46
Hi,
wenn Timer1 auf CTC eingestellt ist und Du OCR1A auf 0 setzt, tritt der Interrupt eventuell so oft auf, daß immer nur der Interrupt von Timer1 abgearbeitet wird. Dieser steht in der Interrupt Vector Tabelle weit vor dem OVF Timer 0 und wird deshalb immer als erster dran kommen.

Wie sieht es aus, wenn OCR1A nicht 0 ist?

PS Mit welcher Taktfrequenz läuft der µC? Ist der erste Code vom ersten Beitrag genau der Code mit dem Du auch testest? Wie überprüftst Du, daß Timer0 ISR nicht aufgerufen wird? (LEDs?)

Gruß
Searcher

Kesandal
24.06.2011, 13:52
Hallo Searcher,

dein Hinweis brachte mich zur Lösung.

Deine Vermutung hat sich bestätigt :)