Forum: Mikrocontroller und Digitale Elektronik Hilfe TIMER4_OVF_vect wird nicht ausgeführt


von Marcel P. (Gast)


Lesenswert?

Hallo Profis,

ich verzweifle gerade ein bisschen an meinem Bastel-Projekt.
Ich habe hier einen ATMega2560 (ja, auf einem Arduino) den ich mit 
AVR-GCC  und dem Atmel Stuido 7 programmiere.

Um eine Lüfterdrehzahl zu überwachen habe ich mir mit Timer4 und INT4 
eine Impulsmessung gebastelt. Der Zähler läuft einfach im Standard-Mode 
immer komplett durch und durch INT4 wird er immer auf 0 gesetzt, so das 
er nie sein TOP erreicht, solange ein Drehzahlsignal da ist.

Das Funktioniert auch, und die errechnete Drehzahl stimmt auch alles.

Halte ich den Lüfter mit dem Finger an bzw ziehe das Drehzahlsignal ab, 
dann wird allerdings der TIMER4-OVF_vect nicht aufgerufen ! Überprüft 
habe ich das, indem ich einen Pin beim aufruf toggle und mit dem 
Osziloskop visualisiere.

Das Toggeln an sich funktioniert, wenn ich es irgendwo anders aufrufe, 
also liegts nicht am Ausgabepin. Der Timer läuft auch über, was ich mir 
durch die serielle Ausgabe von TCNT4 angesehen habe.
Aber der verdammte Interrupt wird nicht ausgelösst !

in der main() habe ich natürlich sei() aufgerufen und wird auch nirgends 
in der ganzen Software wieder deaktiviert...

Jemand eine Idee oder hab ich was vergessen ? Oder fehlen noch Infos ?

Hier mal meine Init und die ISR's:
1
void io_init(){
2
  
3
  DDRB |= ( 1 << PB7 );      // PB7 - Sys_LED (arduino 13)
4
  DDRC |= ( 1 << PC0 ) | ( 1 << PC1 ) | ( 1 << PC2 ) | ( 1 << PC3 ) | ( 1 << PC4 ) | ( 1 << PC5 );  // PB0 bis PB5 Stepper-Interface (arduino 32 bis 37)
5
  PORTC |= ( 1 << PC0 ) | ( 1 << PC1 );    // Disable Stepper
6
  
7
  DDRE &= ~( 1 << PE4 );    // Tacho-Input for Motor-Fan
8
  PORTE |= ( 1 << PE4 );    // Enable Pullup
9
  EICRB |= ( 1 << ISC40);    // Any edge of INTn generates asynchronously an interrupt request
10
  EIMSK |= ( 1 << INT4 );    // Enable INT4 Interrupt
11
  
12
  DDRF |= ( 1 << PF0 );    // Debug Output-Pin
13
  
14
  
15
}

1
void timer4_init() {
2
  TCCR4B |= ( 1 << CS42 ) | ( 1 << CS40 )  ; // Timer 4 mit Prescaler 1024 starten
3
  TIMSK4 |= (1<<TOIE4);    // erlaube Timer4 Overflow Interrupt
4
}

1
ISR (TIMER4_OVF_vect) {                 // Timeout, also kein puls registriert. Lüfter steht / Signal unterbrochen.
2
  debugPIN_tgl;
3
  ui8_fan_measure_running = 0;
4
  ui16_rpm_fan = 0;      
5
}

1
ISR(INT4_vect) {
2
3
  if ( !ui8_fan_measure_running ) {
4
    TCNT4 = 0;
5
    ui8_fan_measure_running = 1;
6
  }
7
  else {
8
    ui8_fan_measure_running = 0;
9
    uint32_t temp;
10
    temp = TCNT4 * 64;  // Pulse Lenght in uSeconds
11
    ui16_rpm_fan = 1000000 / temp * 15;    // Sekunde / Pulslänge * 60 ist RPM. nur mal 15, da 4 Pulse pro umdrehung
12
  }
13
}

Vielen Dank schonmal !

von Rudolph R. (rudolph)


Lesenswert?

Marcel P. schrieb:
> ISR (TIMER4_OVF_vect) {                 // Timeout, also kein puls
> registriert. Lüfter steht / Signal unterbrochen.
>   debugPIN_tgl;
>   ui8_fan_measure_running = 0;
>   ui16_rpm_fan = 0;
> }

Was ist "debugPIN_tgl;"?
Ein Makro?
Eine gängige Konvention ist eigentlich, Makros mit Grossbuchstaben zu 
versehen und zusätzlich wäre es ja hilfreich zu wissen, was sich 
dahinter verbirgt.

Die Deklaration der Variablen fehlt noch.
Sind die "volatile"?

von Marcel P. (Gast)


Lesenswert?

Verzeihung, Ja, debugPIN_tgl ist ein Macro:
1
#define debugPIN_tgl PORTF ^= ( 1 << PF0 )

hier die Variablen welche in ISR gebraucht werden.
1
volatile uint16_t ui16_rpm_fan;
2
volatile uint8_t ui8_fan_measure_running;

von Mitlesa (Gast)


Lesenswert?

Aus dem Datenblatt:

"The corresponding Interrupt Vector (see “Interrupts” on page 101)
is executed when the TOVn Flag, located in TIFRn, is set."

von Marcel P. (Gast)


Lesenswert?

Mitlesa schrieb:
> Aus dem Datenblatt:
>
> "The corresponding Interrupt Vector (see “Interrupts” on page 101)
> is executed when the TOVn Flag, located in TIFRn, is set."

Danke... das weiss ich...  TOV4 in TIFR4 wird auch gesetzt wenn der 
Zaehler überläuft. Aber es wird der Interrupt nicht ausgelöst, durch 
welchen TOV4 automatisch wieder zurück gesetzt wird !

Datasheet Page 163: TOVn is automatically cleared when the 
Timer/Countern Overflow Interrupt Vector is executed.

Der Interrupt ist ja hier auch in timer4_init() aktiviert:
1
  TIMSK4 |= (1<<TOIE4);    // erlaube Timer4 Overflow Interrupt

und in der main wird durch sei() auch erlaubt.
Alle anderen Timer im CTC-Mode laufen und die Interrupts werden ja auch 
ausgeführt. Nur der dämliche Timer4 nicht...

von Rudolph R. (rudolph)


Lesenswert?

Marcel P. schrieb:
> #define debugPIN_tgl PORTF ^= ( 1 << PF0 )

Okay, hat mit dem Problem nichts zu tun, aber ich würde ja
1
PINF = (1<<PF0)

benutzen.

Mitlesa schrieb:
> is executed when the TOVn Flag, located in TIFRn, is set."

Das sollte beim Überlauf ja eigentlich automatisch passieren.

von Marcel P. (Gast)


Lesenswert?

Rudolph R. schrieb:
> Okay, hat mit dem Problem nichts zu tun, aber ich würde ja
> PINF = (1<<PF0)
>
> benutzen.

Wieso ?
Ich schreibe da ja auf einen Ausgang und nicht auf einen Eingang, also 
PORTx und nicht PINx !?

von Arduinoquäler (Gast)


Lesenswert?

Ich nehme an dass dieser Code - Teil
1
ISR(INT4_vect) {
2
  if ( !ui8_fan_measure_running ) {
3
    TCNT4 = 0;
4
    ui8_fan_measure_running = 1;
5
  }

dir dauernd das Timer4 Register nullsetzt und du damit nie
in den Überlauf kommst.

Hab jetzt nicht nachgeschaut, aber kann es sein dass dieser
Interrupt explizit gelöscht werden muss? (sonst würde er
beim Verlassen der ISR sofor wieder zuschlagen)

von Rudolph R. (rudolph)


Lesenswert?

Marcel P. schrieb:
>> Okay, hat mit dem Problem nichts zu tun, aber ich würde ja
>> PINF = (1<<PF0)
>>
>> benutzen.
>
> Wieso ?
> Ich schreibe da ja auf einen Ausgang und nicht auf einen Eingang, also
> PORTx und nicht PINx !?

Kapitel 13.2.2 vom Datenblatt: "Toggling the Pin".
"Writing a logic one to PINxn toggles the value of PORTxn, independent 
on the value of DDRxn. Note that the SBI
instruction can be used to toggle one single bit in a port."

von Marcel P. (Gast)


Lesenswert?

@Arduinoquäler
genau, da setze ich zurück...
Solange da ein Lüftersignal ankommt, wird der auch immer schön 
ausgeführt bei jedem Flankenwechsel.
Gelöscht werden muss da nichts.

Es funktioniert alles, ausser der Tatsache das der OVF-Interrupt nicht 
gestartet wird....

@rudolph

Ach, faszinierend, das war mir gänzlich unbekannt. Ich kannte das eben 
nur so wie ich gemacht habe. Da es so immer funktioniert hat, habe ich 
mir nie Gedanken über Alternativen gemacht oder danach gesucht. Danke 
dafür !

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


Lesenswert?

Hatten wir nicht neulich sowas schon mal? Es stellte sich raus, das die 
Kiste so mit Interrupts höherer Priorität beschäftigt war, das es nie 
dazu kam, das der fragliche ausgeführt wurde. Check doch mal, wie es 
damit bei dir aussieht.

von Marcel P. (Gast)


Lesenswert?

o.O
ich hab mal die anderen Timer deaktiviert (die machen ganz anderen Kram) 
und siehe da... ZACK.. es geht !

Verdammt.. dann ist mein µC zu beschaeftigt mit Interrupts. Da muss ich 
da das ganze wohl mal überarbeiten.

Vielen Dank @mschoeldgen

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


Lesenswert?

Marcel P. schrieb:
> dann ist mein µC zu beschaeftigt mit Interrupts.

Man kommt da gar nicht so einfach drauf, weil die AVRs die 
Hauptschleife, wenn auch schnarchlangsam, abarbeiten, es wird mindestens 
ein Befehl im Hauptprogramm ausgeführt, bevor der nächste anstehende IRQ 
ausgeführt wird.

Aber ist ja schön, das es gefunden wurde. Im anderen Thread haben eine 
ganze Menge Leute eine ganze Menge gerätselt, weil alles bestens aussah 
im geposteten Code - genau wie bei dir.

von Marcel P. (Gast)


Lesenswert?

Ja, aber genau das ist es was dann fehlt.. Erfahrung...
Ich glaube ich wäre da so nie drauf gekommen.

Jetzt muss ich mal sehen, wie ich das zufriedenstellend lösen kann...

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.