Forum: Mikrocontroller und Digitale Elektronik Timer Interrupt wird nicht ausgelöst?


von dude (Gast)


Lesenswert?

Hallo,

ich bin dabei mich mit dem timer des atmega 328p zu befassen. Ich will 
spätzer daraus eine Uhr bauen zu lernzwecken. Bin jetzt an einem Punkt, 
wo ich einfach mal Hilfe brauche.

Ich habe an meinem µController vier 7-Segmentanzeigen. Die ich wunderbar 
ansteuern kann. Jetzt möchste ich, dass die Ziffern der 7 Segmentanzeige 
wenn der Timer zum 50zigsten Mal seinen maximalwert erreicht hat 
umgeschaltet wird. Die Ziffern habe ich in einem Array. Jedoch bleiben 
meine 7-Segmentanzeigen dauerhaft auf 0 0 0 0, wenn ich das ganze mit 
dem Timer versuche. In der Hauptschleife wird die Bedingung 
if(extraTime>50) nie erfüllt bzw. der Interrupt wird gar nicht 
aufgerufen?

Jemand eine Idee?
1
/*
2
 * Uhr.c
3
 *
4
 * 
5
 *  Author: xxxx
6
 */ 
7
#ifndef F_CPU
8
#define F_CPU 8000000UL
9
10
11
  //Externer Quarztakt
12
#endif
13
#include <avr/io.h>
14
#include <util/delay.h>    //Warteschleifen
15
#include <avr/interrupt.h>  //Interruptheader
16
int extraTime=0;
17
18
//Konsanten
19
const char sieben_seg_ziffer[10] = {0b01000100,0b11001111,0b01010010,0b11000010,0b11001001,0b11100000,0b01100000,0b11001110,0b01000000,0b11000000};//Ziffern 0 bis 9 der 7-Seganzeige
20
  
21
22
23
ISR(TIMER0_COMPA_vect)
24
{
25
  extraTime++;
26
}
27
28
  
29
30
int main(void)
31
{
32
33
  
34
  TCCR0A |= (1<<WGM01);//CTC Mode aktivieren
35
  OCR0A = 156;//Max Wert bis Interrupt auslöst
36
  TIMSK0 |=  (1<<OCIE0A);
37
  sei();
38
  
39
  TCCR0A |= (1<<CS00)|(1<<CS02);//Setting Prescaler clk/1024
40
  
41
  
42
  
43
  DDRD   = 0b11111111;                      //Ausgang; Siebensegmentanzeige
44
  DDRC   = 0b11111111;            //Ausgang; Die vier Anoden der 7-Segmentanzeigen
45
  
46
  
47
  //vier 7-Segmentanzeigen aktivieren
48
  PORTC|=(1<<PC0);
49
  PORTC|=(1<<PC1);
50
  PORTC|=(1<<PC2);
51
  PORTC|=(1<<PC3);
52
  
53
54
  
55
  while(1)
56
    {
57
    
58
    int i=0;
59
  
60
    do 
61
    {
62
      PORTD=sieben_seg_ziffer[i];
63
    
64
      if(extraTime>50)
65
      {
66
        i++;
67
        extraTime=0;
68
      }
69
      } while (i<10);
70
    
71
72
  }
73
}

von Karl H. (kbuchegg)


Lesenswert?

dude schrieb:


> int extraTime=0;

volatile int extraTime = 0;


FAQ: Was hat es mit volatile auf sich

von dude (Gast)


Lesenswert?

Danke für den Hinweis. Mit volatie int extraTimer habe ich jetzt 
ausgeschlossen, dass irgendwas wegoptimiert wurde. Trotzdem wird wie es 
aussieht die Bedinung if(extraTime>50) nicht erfüllt, da die Anzeige bei 
0 0 0 0 bleibt. hhhmm irgendwo ist noch ein bock...

von Dude (Gast)


Lesenswert?

Ich finde den Fehler nicht...... -.-

Ich habe das Gefühl, dass der timer interrupt gar nicht auflöst, da die 
Bedingung in der if Abfrage nicht erfüllt wird.

von OldMan (Gast)


Lesenswert?

Als erstes würde ich Dir vorschlagen, dass Du mal eine "Debug"-Funktion 
mittels einer LED in die ISR einbaust.
Suche Dir einen freien PORT mit passendem PIN
und daran schliesst Du eine LED an. Vergiss nicht den Port als Ausgang 
zu definieren.

Die ISR erweiterst Du wie folgt
1
ISR(TIMER0_COMPA_vect)
2
{
3
  PORTx ^= 0x80;      // Bspw. an PORTx (der freie Port) mit dem Bit7 wackeln
4
  extraTime++;
5
}
Dann siehst Du, ob Deine ISR überhaupt funktioniert.
D.h., die LED sollte flackern. Notfalls mal eine Scope anschliessen,
dann siehst Du auch die Taktrate Deines ISR. D.h., Du kannst am Scope 
sehen, wieviel Zeit vergeht bis der ISR wieder aufgerufen wird.

Als weiteres würde ich die Variable extraTime als char bzw. uint8_t 
definieren. Denn int ist 16-Bit. Damit gibt es immer Probleme, denn 
ein AVR ist ein 8-bittiger Prozessor. Auch wenn sie als volatile 
definiert ist.
Gewöhne Dir bitte an die Typdeklarationen zu benutzen die hier üblich 
sind.
Also: nicht char sonder als int8_t bzw. unsigned char als uint8_t zu 
deklarieren, usw.. Damit wird es Dir letzten Endes leicher und 
verständlicher gemacht. Weil Du genau weisst, wieviel Bits deine 
Variable definitiv hat.

Und als letzte Info: Nimm den #include <util/delay.h>  raus und setze 
die Optimierung auf -O0, sprich schalte sie aus.

Wenn alles läuft kannst Du später die Optimierung wieder aktivieren.

von OldMan (Gast)


Lesenswert?

dude schrieb:
> sei();
>
>   TCCR0A |= (1<<CS00)|(1<<CS02);//Setting Prescaler clk/1024

Nachtrag:

Die Interrupts sollte man immer erst dann freigeben, wenn
alle Register vollständig initialisiert sind.
D.h., Dein sei() sollte nach dem setzen des Prescalers erfolgen.

Viel Erfolg!

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.