Forum: Mikrocontroller und Digitale Elektronik Timer0 Interrupt geht nicht


von Hegy (Gast)


Lesenswert?

Hi,

eigentlich ist eine ganz einfache Sache, den Timer0 im 8-Bit Modus zum
überlaufen zu bringen und dann per Interrupt einen Port-Pin kippen.
Aber bei mir geht das nicht mit den Zeiten die ich haben will. Auch im
AVR-Studio 4 (ganz neu installiert) geht das nicht.

Prinzip: Port D4 bis D7 Ausgänge, Timer0 Overflow Inteerrupt
abschalten, alle Interrupts freigeben, sleep()-Funktion aufrufen in
einer while(1)-Endlosschleife. In der sleep()-Funktion wird der
Prescaler auf 256 eingestellt, TOV0 Flag im TIFR0 auf 1 setzen
(Interrupt löschen), in TIMSK0 das TOIE0 Flag auf 1 (Timer Interrupt
enable). Jetzt in "if(waittime)", darin wird immer in TIMSK0 das
TOIE0 Flag auf 1 gesetzt (interrupt enable). Läuft der Timer über, soll
die ISR angesprungen werden. In der ISR wird die Variable 'waittime'
decrementiert und der PortD invertiert. Dann wieder raus in die
if(waittime)-Schleife. Ist waittime auf 0 angekommen soll der Timer0
Overflow Interrupt abgeklemmt werden. Und dann geht's wieder von vorne
los. Ergebnis: Jedesmal, wenn der Timer0 Interrupt aufkreuzt, wird der
PortD invertiert, theoretisch. Tut es auch, aber nicht mit den Zeiten,
wie es sein sollte. Wenn ich die Zeiten mittels TCNT0 Register
variieren will, dann darf ich da nur den Wert 255 reinschreiben oder
eben nix, auch keine 0. Wenn ich das mache, passiert am PortD nix mehr.
Ich habe absolut keine Erklärung dafür. Die sleep-Funktion soll hier
erstmal nur 1 ms verbummeln.

Hier der Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h> 
3
4
void sleep(unsigned long waittime);
5
void wait(void); 
6
7
static volatile unsigned int waittime;
8
9
int main(void)
10
{ 
11
  DDRD = 0xF0; // Port D4...7 Output 
12
  PORTD = 0xFF; // Port D4...7 aus
13
14
  TIMSK0 &= ~(1<<TOIE0); // Timer Overflow Interrupt Enable 0
15
ausschalten
16
17
  sei();
18
19
  while(1) // Warteschleifentest, Parameter in ms
20
    sleep(1000);
21
22
  return 0; // damit der gcc nich rummotzt
23
}
24
25
26
void sleep(unsigned long waittime)
27
{
28
  // Timer 0, 8-Bit initialisieren
29
  //TCNT0 = 255; // 29 Inkrementierungen bis Interrupt -> 29 x 34.722us
30
= 1.00694 ms
31
  TCCR0B = (1<<CS02); // Timer 0, Prescaler = 256 f. Wartezeiten von
32
34.722 us pro TCNT0 Inkermentierung
33
  TIFR0 = (1<<TOV0);
34
  TIMSK0 = (1<<TOIE0);
35
  
36
  waittime = 1; // zu Testzwecken reingedängelt
37
  if(waittime)
38
  {
39
    TIMSK0 |= (1<<TOIE0); // Timer Overflow Interrupt Enable 0
40
einschalten
41
    //asm volatile("NOP");// tu_was_gescheites();
42
  }
43
  else
44
    TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02)); // Timer Stop
45
}
46
47
// Timer 0 Overflow
48
void ISR (_VECTOR(16)) // war ISR(SIG_OVERFLOW0)
49
{
50
  //waittime--;
51
  PORTD = ~PORTD;
52
}

Ich habe den COde übrigens auch schon mit AVRStudio 4 simuliert. Läuft
das TCNT0 über, wird nicht die ISR angesprungen, sondern die erste
Zeile in der main-Funktion (SW-Reset). Das passiert auch, wenn ich die
ISR-Fkt gegen die
1
 ISR(__vector_default)
 austausche.

HW: ATmega48 auf einem STK200
SW: gcc 3.4. bzw. AVR-Studio4 & winavr (heute gezogen)

von Hubert.G (Gast)


Lesenswert?

Probier mal statt while(1)und danach:
for(;;){
   sleep(1000);
   }

dann bleibst du in der for Schleife.

von Hegy (Gast)


Lesenswert?

Meinst du, while(1) sleep(x); ist keine Endlosschleife?

von Hubert.G (Gast)


Lesenswert?

Mir fehlen die geschwungenen Klammern und mache das gewohnheitsmässig
mit for(;;){ dann bleibe ich sicher da drinnen und springe nicht an den
Angang von main.

von Karl H. (kbuchegg)


Lesenswert?

Die Sache mit den Klammern hat was fuer sich, da macht
man zumindest nichts falsch.
Wenn innerhalb der Schleife allerdings nur eine einzelne
Anweisung steht, sind sie syntaktisch nicht notwendig.

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.