PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Overflow Timer1 beim Nano



DanielSan
15.09.2017, 16:29
Hallo,

ich versuche mit dem Nano und dem Timer1 einen Overflow interrupt nach ca. 32,768ms auszulösen.

Meine Annahmen:
- System Clock Frequenzey = 16.000.000 Hz
- Timer Resolution = 16 bit
- Prescaler = Clk/8

Mein Code sieht so aus:

int timer1_led = 12;

ISR(TIMER1_OVF_vect)
{
digitalWrite(timer1_led, !digitalRead(timer1_led));
}

void setup() {
pinMode(timer1_led, OUTPUT);

// ######### Timer 1
//Prescaler = 8
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
TCNT1 = 0;
TIMSK1 |= (1 << TOIE1);

sei();
}

void loop() {

while (1)
{
}
}

Grundsätzlich funktioniert der Code auch, die Led wird getoggelt. Leider passt die Frequenz nicht. Mein Logicanalyzer sagt, Led = HIGH für 2ms und Led = LOW für 2ms. Das ganze hab ich noch mit dem Simulator im AVR Studio 7 überprüft. Gleiches Ergebnis.

Ich dachte ich hätte das mit den Timern so langsam verstanden... scheint noch nicht so zu sein.

Um rauszufinden ob ich einen Denkfehler habe oder mein Program falsch ist schreibe ich noch mal kurz was ich erwartet hätte.

Der Nano läuft mit 16 Mhz. Der Timer1 hat 16 bit, zählt also bis 65536 bis er den Overflowinterrupt auslöst. Mit dem Prescaler von 8 benötigt er dafür 32,768ms [Zeit = ( 2^16*8 )/16.000.000]. Dann springt er in die Interruptroutine und toggelt die Led.

Wo liegt mein Fehler? Fehlt noch ein Register was ich setzen muss? TCCR1A z.B.? Falls ja was muss ich da einstellen?

Vielen Dank.
Gruß Daniel

- - - Aktualisiert - - -

Na bitte...

Ich hab den Fehler selbst gefunden. Hier der korigierte Code:

int timer1_led = 12;

ISR(TIMER1_OVF_vect)
{
digitalWrite(timer1_led, !digitalRead(timer1_led));
}

void setup() {
pinMode(timer1_led, OUTPUT);

// ######### Timer 1
TCCR1A = 0;
//Prescaler = 8
TCCR1B = (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
TCNT1 = 0;
TIMSK1 = (1 << TOIE1);

sei();
}

void loop() {

while (1)
{
}
}



Der "|" hat das Fehlverhalten verursacht. Was genau das bedeutet muss ich noch nachlesen. Aber nicht mehr heute! :-)

oberallgeier
15.09.2017, 17:24
Wo hast Du denn den Code gefunden ??


.. ich versuche mit dem Nano und dem Timer1 einen Overflow interrupt nach ca. 32,768ms auszulösen.

..
void setup() {
pinMode(timer1_led, OUTPUT);

// ######### Timer 1
//Prescaler = 8
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
TCNT1 = 0;
TIMSK1 |= (1 << TOIE1);

sei();
}
..

Ich hab den Fehler selbst gefunden. Hier der korigierte Code:
..
Der "|" hat das Fehlverhalten verursacht. Was genau das bedeutet muss ich noch nachlesen. Aber nicht mehr heute! :-)

Nu fällt´s mir schwer zu helfen, denn arduinoisch kann ich nicht. Und bei mir toggelts halt mit dem Code - simples C. Weils schnell gehen sollte mit Soft-Blinken auf PB5 (user definded LED); natürlich gehts auch mit Hardware-PWM auf PB1 (die ist auf meinem Clone-Testboard aber ohne LED ;-) )


// ================================================== =========================== =
// == Timer Aufgabe: Soft-PWM ansteuern
// Datenblatt Atmel-8271J-AVR- ATmega-Datasheet_11/2015
// - - - - - - - - - - - - - - - -
void TC1TMR_init(void) // Init Timer/Counter 1 für 2 ms Servoperiode
{ //


// - - - - - - - - - - - - - - - -
// TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10); // Das ist Quatsch
TCCR1B |= (1<<WGM12); // => CTC, TOP = OCR1A Doc Seite 133
TCCR1B |= (1<<CS11); // übliche Schreibweise für clk/8 => 2,000 MHz 134
//TCCR1B |= (1<<CS12); // Prescaler clk/256 => 136
// Wenn CS12 genommen wird, tickert der Interrupt mit 16MHz/256 => 62,5 kHz.
// Dann kann mit
// OCR1A = 1907; // => alle 32,774 ms 1 Interrupt gemessen werden

// Bei dem von dir gewählten clk/8 bzw. 2 MHz müssen wir OCR1A höher ansetzen
OCR1A = 61035; // => alle 32,768 ms 1 Interrupt gemessen werden
// das ist schon etwas langsamer als Dein Wunsch
// TCNT1 = 0; // Diese Festlegung versteh ich nicht ! ? ! ?
TIMSK1 |= (1 << TOIE1);
TIMSK1 |= (1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt enabled
// - - - - - - - - - - - - - - - -
}
// ================================================== =========================== =


// ================================================== =========================== =
// === ISR für TIMER1_COMPA_vect ==================== =
// Es wird NUR
// - - - - - - - - - - - - - - - -
ISR (TIMER1_COMPA_vect) // Servo[Svpt] wählen + dessen Rampe starten
{ //
ToggleBit ( PORTB, PB5 ); // User defined LED
// - - - - - - - - - - - - - - - -
return; //
// - - - - - - - - - - - - - - -
} // Ende ISR (TIMER1_COMPA_vect)
// ================================================== =========================== =