Forum: Mikrocontroller und Digitale Elektronik Timerinterrupt beim 644PA


von R. B. (britzi)


Lesenswert?

Hallo zusammen,

ich möchte dass meine Steuerung, sofern sie den Kontakt zum Computer 
verliert in einen sicheren Zustand geht.

Um dies zu erreichen möchte ich den Timer2 des ATmega 644PA nutzen.
Der Computer soll dabei per UART spätestens alle 30 Sekunden eine 
Variable zurücksetzen müssen, damit das System nicht in den sicheren 
Zustand geht.
Die UART-Funktionen funktionieren schon alle.

Mit fehlt nur noch der Timer.
Die anderen Timer sind schon für PWM in Betrieb, daher muss ich leider 
mit dem 8-bit Timer vorlieb nehmen.

Dieser ist, sofern ich das Datenblatt richtig verstehe sowieso immer am 
laufen und zählt immer die 8 bit voll und beginnt dann von vorne.
Ich möchte einfach bei jedem Überlauf eine Zählvariable incrementieren, 
die dann, wenn sie einen bestimmten Wert erreicht, meine maximale 
akzeptable Dauer ohne Signal vom PC darstellt.

Das hier ist mein Codeversuch:
1
        uint8_t  sicherheitsflag=0;
2
 volatile   uint16_t  zeit=0;
3
       uint8_t  systemAus=0;
4
5
void init_saeftyTimer()
6
{
7
  TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20); // 18,4320MHz / 1024 = 18kHz      
8
  //Überlauf nach: 0,0142857143 Sekunden
9
  //30 Sekunden = 2100 Überläufe  
10
  // Interrupt TOV2
11
}
12
13
ISR(TIMER2_OVF_vect_num)  // Interrupt-Service-Routine
14
{
15
  zeit++;
16
}
17
18
void saeftyTimer()
19
{
20
  if (sicherheitsflag==1)
21
  {
22
    zeit=0;
23
    sicherheitsflag=0;
24
  }
25
  if (zeit>=2100)
26
  {
27
    systemAus=1;
28
    zeit=0;
29
  }
30
}

Allerdings meckert er bei der ISR:
"expected declaration specifiers or '...' before numeric constant"

Was ist mein Fehler?
Und ist der Ansatz sonst so ok?

Vielen Dank :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

R. B. schrieb:

> Die anderen Timer sind schon für PWM in Betrieb, daher muss ich leider
> mit dem 8-bit Timer vorlieb nehmen.

Nein.  Auch ein PWM-Timer kann durchaus normale Timerinterrupts
machen, insbesondere kann er noch einen Interrupt beim Erreichen
des maximalen Zählerstands triggern.  Der stört die PWM überhaupt
nicht, und für sowas Grobschlächtiges wie deine 30 s reicht das
wohl allemal.

> ISR(TIMER2_OVF_vect_num)

Du hast den Unterschied zwischen TIMER2_OVF_vect_num und TIMER2_OVF_vect
nicht verstanden.

von R. B. (britzi)


Lesenswert?

Jörg Wunsch schrieb:

> Nein.  Auch ein PWM-Timer kann durchaus normale Timerinterrupts
> machen, insbesondere kann er noch einen Interrupt beim Erreichen
> des maximalen Zählerstands triggern.  Der stört die PWM überhaupt
> nicht, und für sowas Grobschlächtiges wie deine 30 s reicht das
> wohl allemal.

Das ergibt Sinn :-)


> Du hast den Unterschied zwischen TIMER2_OVF_vect_num und TIMER2_OVF_vect
> nicht verstanden.

Ganz ehrlich... ich kenne den Unterschied leider nicht und habe auch im 
Datenblatt nichts dazu gefunden.

Ich hatte da auch erst TIMER2_OVF_vect stehen, aber da gibts dann 
zumindest auch Warnungen:

return type defaults to 'int' [enabled by default]
type of '__vector_11' defaults to 'int' [enabled by default]
control reaches end of non-void function [-Wreturn-type]

Liegt das daran, dass ich ein uint16 genommen habe, der ja ein 
spezieller Integer ist?

von Thomas E. (thomase)


Lesenswert?

R. B. schrieb:
> return type defaults to 'int' [enabled by default]
Du hast interrupt.h nicht eingebunden. Dann weiss der Compiler nicht, 
was das ist.

ISR(TIMER2_OVF_vect) ist der richtige Aufruf.

mfg.

von R. B. (britzi)


Lesenswert?

Thomas Eckmann schrieb:
> R. B. schrieb:
>> return type defaults to 'int' [enabled by default]
> Du hast interrupt.h nicht eingebunden. Dann weiss der Compiler nicht,
> was das ist.
>
> ISR(TIMER2_OVF_vect) ist der richtige Aufruf.
>
> mfg.

Danke :-)

Was für ein blöder Fehler, nun funktioniert es :-)

von R. B. (britzi)


Lesenswert?

Es funktioniert leider doch nicht :-(

Der Code erzeugt zwar keine Fehler, aber der Timer läuft anscheinend 
nicht.

Zumindest wird die ISR nie aufgerufen.

Ich probiere hier schon seit Stunden rum, aber es läuft nicht.

Woran liegt es?

Ich finde das Datenblatt in Bezug auf die Timer leider leicht verwirrend 
:-(

Es ist doch so, dass der Timer immer läuft, oder nicht?
So verstehe ich zumindest das Datenblatt...
Ich habe ja nur einen Prescaler konfiguriert.


Vielen Dank :-)

von Falk B. (falk)


Lesenswert?

@ R. B. (britzi)

>Der Code erzeugt zwar keine Fehler, aber der Timer läuft anscheinend
>nicht.

>Zumindest wird die ISR nie aufgerufen.

>Ich probiere hier schon seit Stunden rum, aber es läuft nicht.

>Woran liegt es?

Posten deinen aktuellen Code als Anhang.

>Es ist doch so, dass der Timer immer läuft, oder nicht?

Nö, man kann ihn auch anhalten.
Oder die Interrupts deaktivieren.

von R. B. (britzi)


Lesenswert?

Der Code ist noch länger.

Das hier ist ein Minimalbeispiel:
1
#include <avr/io.h>
2
#include "DAC_SPI.h"
3
#include <avr/interrupt.h>
4
#include "globale.h"
5
6
7
// Defines für Gruene Statuslampe
8
#define  ledgruen_aus    PORTB |=(1<<PB1)
9
#define  ledgruen_an    PORTB &= ~(1<<PB1)
10
11
uint8_t sicherheitsflag;
12
volatile uint16_t saeftyzeit;
13
14
void init_saeftyTimer()
15
{
16
  TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20); //18,4320MHz /1024 = 18 kHz
17
  // Überlauf nach 0,0142857143 Sekunden
18
  // 30 Sekunden = 2100 Überläufe
19
  DDRB |= (1<<DDB1); //Gruene Statuslampe
20
  sicherheitsflag=0;
21
  saeftyzeit=0;
22
  ledgruen_an;
23
}
24
  
25
ISR(TIMER2_OVF_vect)
26
{
27
  saeftyzeit++;
28
  put_string0("ISR"); //Um über UART zu sehen, ob die ISR aufgerufen wird
29
  put_string1("ISR"); //Zweiter UART
30
}
31
  
32
void saeftyTimer()
33
{
34
  if (sicherheitsflag>=1) //Rücksetzen durch PC
35
  {
36
    saeftyzeit=0;
37
    sicherheitsflag=0;
38
  }
39
  if (saeftyzeit>=210) // Wenn 30s rum ausmachen! //Zeit bewusst auf 3s zum Testen gesetzt
40
  {
41
    write_to_dac0(0,0);  //System ausschalten
42
    write_to_dac0(1,0);
43
    saeftyzeit=0;
44
    ledgruen_aus;
45
  }
46
}
47
48
int main ()
49
{
50
   init_saeftyTimer(); //LED wird Grün, aber geht nie aus :-(
51
   sei();
52
  
53
   while(1)
54
    {
55
     saeftyTimer();
56
    }
57
}


Vielen Dank :-)

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ R. B. (britzi)


#include <avr/io.h>
#include "DAC_SPI.h"
#include <avr/interrupt.h>
#include "globale.h"



>void init_saeftyTimer()
>{
>  TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20); //18,4320MHz /1024 = 18 >kHz
>  // Überlauf nach 0,0142857143 Sekunden
>  // 30 Sekunden = 2100 Überläufe
>  DDRB |= (1<<DDB1); //Gruene Statuslampe
>  sicherheitsflag=0;
>  saeftyzeit=0;
>  ledgruen_an;
>}

Wo wird der TImer overflow freigeschaltet?
Das fehlt

TIMSK2 |= (1<<TOIE2);

von R. B. (britzi)


Lesenswert?

Falk Brunner schrieb:

> Wo wird der TImer overflow freigeschaltet?
> Das fehlt
>
> TIMSK2 |= (1<<TOIE2);

Super!

Vielen vielen Dank :-)
Das hab ich einfach im Datenblatt übersehen.

Ich habs auch gleich nachgeschlagen. ;-)


Schönes Wochenende :-)

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.