mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer0 Interrupt geht nicht


Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr/io.h>
#include <avr/interrupt.h> 

void sleep(unsigned long waittime);
void wait(void); 

static volatile unsigned int waittime;

int main(void)
{ 
  DDRD = 0xF0; // Port D4...7 Output 
  PORTD = 0xFF; // Port D4...7 aus

  TIMSK0 &= ~(1<<TOIE0); // Timer Overflow Interrupt Enable 0
ausschalten

  sei();

  while(1) // Warteschleifentest, Parameter in ms
    sleep(1000);

  return 0; // damit der gcc nich rummotzt
}


void sleep(unsigned long waittime)
{
  // Timer 0, 8-Bit initialisieren
  //TCNT0 = 255; // 29 Inkrementierungen bis Interrupt -> 29 x 34.722us
= 1.00694 ms
  TCCR0B = (1<<CS02); // Timer 0, Prescaler = 256 f. Wartezeiten von
34.722 us pro TCNT0 Inkermentierung
  TIFR0 = (1<<TOV0);
  TIMSK0 = (1<<TOIE0);
  
  waittime = 1; // zu Testzwecken reingedängelt
  if(waittime)
  {
    TIMSK0 |= (1<<TOIE0); // Timer Overflow Interrupt Enable 0
einschalten
    //asm volatile("NOP");// tu_was_gescheites();
  }
  else
    TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02)); // Timer Stop
}

// Timer 0 Overflow
void ISR (_VECTOR(16)) // war ISR(SIG_OVERFLOW0)
{
  //waittime--;
  PORTD = ~PORTD;
}

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
 ISR(__vector_default) 
 austausche.

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

Autor: Hubert.G (Gast)
Datum:

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

dann bleibst du in der for Schleife.

Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meinst du, while(1) sleep(x); ist keine Endlosschleife?

Autor: Hubert.G (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.