mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR, 16-Bit Timer tickt nicht


Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

viel rumprobiert, gemacht, getan, nix......dabei ist's nicht viel. Ein
16-Bit Timer soll ein/zwei LEDs zum blinken bewegen, nur versuchsweise.
Soweit ich weiß, wird die ISR nicht abgearbeitet.

Der kurze Code dazu, der nicht geht und ich nicht weiß warum nicht.
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
// Quarz 4MHz, CTC-Modus, ATmega48

int main(void)
{
  //TCCR1B = (1<<WGM12) | (1<<CS10);             // Prescaler = 1
  //TCCR1B = (1<<WGM12) | (1<<CS11);             // Prescaler = 8
  TCCR1B = (1<<WGM12) | (1<<CS11) | (1<<CS10); // Prescaler = 64
  //TCCR1B = (1<<WGM12) | (1<<CS12);             // Prescaler = 256
  //TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS10); // Prescaler = 1024
  
  OCR1A  = 2000;
  TIFR1  = 1<<ICF1;
  TIMSK1 = (1<<OCIE1A) | (1<<TOIE1);
  DDRB = 0x07; // Port PB0, PB1, PB2 Output
  PORTB = 0xFF; // Port PB0, PB1 aus
   
  wdt_disable();

  sei();

  while(1)
    PORTB = 0xFD; // eine LED an

  return 0;
}

ISR(SIG_OUTPUT_COMPARE1A)
{
  PORTB = ~PORTB;
}

totmüde
  Hegy

Autor: ruepel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieht eigentlich von der ISR - Initialisierung ganz ok aus.
Das TOIE1 ist ueberfluessig.

Es geht nicht, weil in Deiner while-Schleife in Zeile 25/26 der PortB
sofort nach dem Ausfuehren des Interrupts wieder mit 0xFD gesetzt
wird.
Wenn Du Zeile 26 weglaesst und hinter das while in Zeile 25 ein
Semikolon machst, koennte es evtl. gehen. Probiert habe ich's aber
nicht.

Autor: Dominik T. (dom) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du den Overflow - Interrupt durch setzen des Bits TOIE1 aktivierst,
solltest du auch eine dazugehörige Interrupt-Service-Routine
implementieren. Es könnte ja sein, dass der Timer oberhalb des
Compare-Wert startet, da du ihn ja nicht initialisierst. Dann will er
irgendwann in den Overflow Interrupt und landet im Nirvana.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der landet nicht im Nirvana, sondern im Spurious Interrupt Handler, der
einen Reset verursacht...

Ansonsten hat ruepel recht. Wenn man PORTB ständig mit 0xFD beschreibt,
dann ist PORTB nur dann, wenn der Interrupt auftritt, für ein paar
wenige Taktzyklen geändert. Das ist zu wenig, um es optisch erfassen zu
können.

Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ihr lieben (frei nach DJ Taucher),

ich hab's jetzt raus, so geht's. Den Fehler mit der
PORTB-Invertierung innerhalb der while-Schleife (Zeile 25/26) habe ich
gesehen, als dieses Posting gerade hier war, löschen kann ich es nicht
und auch nicht im nachhinein ändern. Aber der Tip mit der
Timer-Zählvariablen Initialisierung (TCNT1 = 0;) habe ich noch
nachgelegt und den Prescaler nochmal angepast, die Interruptfreigabe
durch TOIE1 rausgenommen und so läufts. Meßwerte unten drunter!

Ich packe es mal als Beispielcode hier hin, für den Fall, daß
irgendjemand in der Zukunft auch so'n Problem hat. Ich habe gesucht,
gesucht und nix gefunden :( .. und auf die Gefahr, daß es hier auch
wieder verschwindet, weil es ja evtl. doch in die Rubrik Codesammlung
gehört.
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
  // Timer Register
  TCNT1  = 0;  // Timer Startwert
  TCCR1B = (1<<WGM12) | (1<<CS11);  // Prescaler = 8
  OCR1A  = 5000; // Timer1 bis 5000 zählen lassen, dann Interrupt
  TIFR1  = 1<<ICF1;
  TIMSK1 = 1<<OCIE1A;

  // Port Register
  DDRB  = 0x07;  // Port PB0, PB1, PB2 Output
  PORTB = 0xFF;  // Port PB0....7 aus

  sei();

  PORTB = 0xFD;  // eine LED einschalten
  while(1)
    ;

  return 0;
}


ISR(SIG_OUTPUT_COMPARE1A)
{
  PORTB = ~PORTB;
}

Was passiert ist, daß eine LED an Port B im 50Hz-Takt blinkt. Ok, es
sind nicht exakt 50Hz, es sind (gemessen mit Keithley 2000 Multimeter)
49.99300 Hz (20,00281 ms Periodenzeit), mit einem 4MHz-Quarz an einem
ATmega48. So, feddich.

Danke an euch, endlich ist das Problem gelöst.

 - Hegy

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.