mikrocontroller.net

Forum: Compiler & IDEs Interrupt Probleme


Autor: harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, folgendes Programm sollte eigentlich eine LED mit einem
Sekundentakt ein bzw. auschalten. Der Timer wurde so gesetzt, dass er
mit einem 1024 des Systemtakt aufwärtszählt. Leider bleibt die LED
immer an. An was kann das liegen ? Ich habe auch schon die
Vergleichswerte in der Interruptroutine erhöht - führt jedoch auch zu
keinem sichtbaren Unterschied.

Bin für jede Hilfe dankbar.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr\signal.h>

volatile unsigned short ledon = 1;

void main(void)
{

outp (0x02,DDRB);

outp ((1<<CS02) | (0<<CS01) | (1<<CS00), TCCR0);

sbi(TIMSK,TOIE0);/* enable TIMER0 OVI */

  //timer_enable_int(1 << TOIE0);

sei ();

while (1) {}

}



SIGNAL(SIG_OVERFLOW0) {
    if (ledon < 4000) {
      ledon ++;
      cbi(PORTB,1); // -> LED ON
    }
    else
    {
      ledon ++;
      sbi(PORTB,1); // -> LED OFF
      if (ledon > 8000)
        ledon = 0;
    }

}



::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Beobachtungen:

-> Interrupt wird genau einmal aufgerufen, jedoch anschliessend nicht
mehr ( meiner Meinung nach )

-> die Interruptroutine werden häufiger als jede 1/4000 sekunde
aufgerufen ( jedoch auch bei Anpassung der Vergleichswerte keine
sichtbare Veränderung des Programms )

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Interrupt wird genau einmal aufgerufen, jedoch anschliessend nicht
> mehr ( meiner Meinung nach )

Hast Du auch wirklich lange genug gewartet? ;-)

Du schreibst nicht, welchen Takt Du benutzt, gehen wir mal von 4 MHz
aus.

$ echo 'scale=5; (4000*256*1024)/4000000' | bc
262.14400

Das wäre die halbe Periode Deiner LED, als die Einschaltdauer, mehr
als 4 Minuten...

Generelle Bemerkungen:

> #include <avr\signal.h>

Bitte Vorwärtsschrägstriche benutzen, sonst geht's nur unter
DOS^H^H^HWindows.

> volatile unsigned short ledon = 1;

Das `volatile' wäre hier gar nicht notwendig, da die Variable ja nur
innerhalb der ISR benutzt wird.

> void main(void)

Das widerspricht dem C-Standard und wäre nur mit der Compiler-Option
-ffreestanding erlaubt.  Die wiederum verhindert andere Optimierungen
auf Bibliotheksebene, die manchmal sinnvoll sein können.

int main(void)

ist besser.

> outp (0x02,DDRB);

inp() und outp() bitte nicht mehr benutzen.

>     if (ledon < 4000) {
>       ledon ++;

Ziemlich umständlich geschrieben meiner Meinung nach.

Hier meine Version (ungetestet).  Zeit ist nicht exakt eine Sekunde,
aber das hängt am Ende von Deinem CPU-Takt ab.

#include <inttypes.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#define LEDPIN PB2
#define CPUCLK 4000000UL

static void
ioinit(void)
{
  DDRB = _BV(LEDPIN);
  /*
   * LED am Anfang einschalten, falls Ausgang H-aktiv ist:
   */
  /* PORTB = _BV(LEDPIN); */

  TCCR0 = _BV(CS02) | _BV(CS00);  /* CPUCLK / 1024 */
  TIMSK = _BV(TOIE0);
  sei();
}

SIGNAL(SIG_OVERFLOW0)
{
  static uint8_t cnt;

  if (++cnt == (uint8_t)(CPUCLK / (1024UL * 256))) {
    cnt = 0;
    PORTB ^= _BV(LEDPIN);
  }
}

int
main(void)
{

  ioinit();

  for (;;)
    ;

  /* NOTREACHED */
  return 0;
}

Mögliche Verfeinerung:

In dieser einfachen Applikation kann es sich lohnen, statt einer
Speicherstelle ein Register für cnt zu benutzen.  Die Deklaration
von cnt innerhalb der Interruptroutine ersetzen durch

register uint8_t cnt asm("r2") = 0;

auf globalem Niveau.

Autor: harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

dein Programm funktioniert prächtig. Lediglich PB2 muss zu PB1 geändert
werden. Was die Wartezeit betrifft hattest du Recht - ich habe die
Werte in meinem Programm angepasst und siehe da es funktioniert doch
:). Ich habe vergessen dass der Timer auf 256 zählt. Ziemlich
bescheuert eigentlich, aber ich habe im Moment noch keine serielle
Schnittstelle, deshalb fällt das Debuggen ziemlich schwer.

Ich habe mir beinahe gedacht, dass eine Bemerkung zum Aufbau des
Quellcodes kommt. Gewöhnlicherweise programmiere ich nicht so
umständlich.

Wieso steht jeweils _bv vor der Benutzung einiger Konstanten ?


vielen Dank für deine Hilfe !!!

mfG Harald

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Lediglich PB2 muss zu PB1 geändert werden.

Ja sorry, das hatte ich vermasselt, nicht richtig geguckt.

> Wieso steht jeweils _bv vor der Benutzung einiger Konstanten

(Es ist übrigens _BV() -- C unterscheidet zwischen Groß- und
Kleinschreibung!)

Wofür der Name BV steht, weiß keiner mehr so richtig. ;-)  ``bit
value'' oder sowas.  Es setzt die als Paramter übergebenen Bitnummer
in einen Integer-Wert um, den man einem Register zuweisen kann, als
Bitmaske benutzen o. ä.  Das ist nichts anderes als das Herumschieben
eines 1-bits:

#define _BV(x) (1 << (x))

es sieht nur (meiner Meinung nach) ein bißchen übersichtlicher aus im
Quellcode.  Wenn Du portabel zu anderen C-Compilern bleiben willst,
darfst Du es aber nicht benutzen, da es diesen Makro dort nicht gibt.

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.