Forum: Compiler & IDEs ATMega 8 absturtz bei Timer-Interrupt


von Valentin M. (mrvalle)


Lesenswert?

Hallo,
ich habe ein kleines Programm geschrieben, bei dem ein ATMega 8 als 
Tacho fungieren soll. Dabei verwende ich den Timer1 im Capture-Mode und 
habe an den ICP1 Pin den Reedkontakt (Magnetschalter) zu GND 
angeschlossen. Den Pin habe ich über den internen Pull-Up nach VCC 
gezogen. Außerdem soll jeder Timerüberlauf registriert werden, damit es 
nicht zu falschen Ergebnissen kommt. Wenn die Interrupts nicht global 
aktiviert sind, funktioniert das Programm ganz normal und überträgt zum 
Beispiel eine inkrementierte Variable immer korrekt. Sind die Interrupts 
aber aktiviert, so stürtzt er immer wieder ab (Variable geht wieder in 
Ausgangswert). Von der Zeit her könnte der Absturz mit dem 
Timer-Overflow zusammenhängen (nach ca. 8 Sekunden). Außerdem 
funktioniert das Capture-Interrupt nicht, die ISR löst nicht aus.

Der relevante Code sieht so aus:
1
#define F_CPU 2000000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <stdint.h>
5
6
volatile uint16_t capture; 
7
volatile uint8_t over;  //Zählt die Anzahl der Overflows
8
9
ISR(TIMER1_CAPT_vect){
10
  //Timer1 interrupt, immer wenn der Sensor auslöst
11
  TCNT1 = TCNT1 - ICR1; //Timer zurücksetzten
12
  capture = ICR1; //Capture speichern
13
  
14
}
15
16
ISR(TIMER1_OVF_vect){
17
  //Timer1 overflow
18
  over = over + 1; //Registriert den overflow
19
}
20
21
int main(void)
22
{
23
  
24
  TCCR1A = 0b00000000; //Timer initialisieren
25
  TCCR1B = 0b10000100; //Prescaler 256
26
  TIMSK  = 0b10001000; //Overflow Interrupt und Capture Interrupt  aktivieren
27
  PORTB  = 0b00000001;
28
  uint8_t i; 
29
  sei(); //Interrupts global aktivieren
30
  
31
    while(1)
32
    {
33
        //Gelegentliche übertragung der Daten an Raspberry Pi, KEIN PROBLEM
34
    }
35
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Valentin M. schrieb:
> TIMSK  = 0b10001000; //Overflow Interrupt und Capture Interrupt
> aktivieren

Mit dieser Schreibweise hast du dich selber reingelegt. Weder aktivierst 
du den TOIE1 noch den Input Capture, stattdessen aktivierst du OCIE2 und 
OCIE1B.
Schreib doch lieber:
1
TIMSK = (1 << TICIE1) | (1 << OCIE1); // wäre 0b00100100
Das ist wesentlich übersichtlicher - nicht jeder blättert im Datenblatt, 
ob deine binären Werte auch stimmen.

von Werner M. (Gast)


Lesenswert?

Valentin M. schrieb:
> Von der Zeit her könnte der Absturz mit dem
> Timer-Overflow zusammenhängen (nach ca. 8 Sekunden). Außerdem
> funktioniert das Capture-Interrupt nicht, die ISR löst nicht aus.

Geht das im Simulator genauso schief?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Matthias Sch. schrieb:
> TIMSK = (1 << TICIE1) | (1 << OCIE1); // wäre 0b00100100

Muss natürlich TOIE1 heissen statt OCIE1

von Dieter F. (Gast)


Lesenswert?

Das Datenblatt ist Dir bekannt?

Du hast nicht Input Capture sondern den Noise Canceller aktiviert. Macht 
aber nichts ...

Unschön - und wahrscheinlich Ursache für den Reset ist, dass Du den 
Output  Compare Interrupt und nicht den Timer Overflow Interrupt 
aktiviert hast - un diesen nicht mit einer ISR behandelst. Der 
gleichfalls aktivierte Output Compare Interrupt für Timer 2 schlägt 
glücklicherweise nicht an, da Timer 2 nicht gestartet wird.

Schau Dir doch mal das GCC-Tutorial hier an

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR

da lernst Du auch gleich, wie man die Register-Einträge für sich selbst 
(und andere) lesbar programmiert.

Ich hasse diese Hinweise auf das Datenblatt auch - aber nur so lernt man 
das ...

von Valentin M. (mrvalle)


Lesenswert?

Vielen Dank für eure Hilfe, es Funktionert jetzt so wie ich es will :)
Ich hab übrigens ins Datenblatt geschaut, hat mir aber nicht sehr 
geholfen.

von Dieter F. (Gast)


Lesenswert?

Valentin M. schrieb:
> Ich hab übrigens ins Datenblatt geschaut, hat mir aber nicht sehr
> geholfen.

Das wundert mich aber jetzt schon - woher weisst Du denn sonst, welches 
Bit in welchem Register Du setzen musst?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.