mikrocontroller.net

Forum: Compiler & IDEs ATmega32 mit Timer0 als Basetime


Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

versuche den Timer 0 im CTC mode zu betreiben.
Folgendes Problem: Die globale Variable uiTimer0High wird im 1ms-Takt
inkrementiert und soll später alle 500ms eine Aktion initiieren. Weil
nichts geht prüfe ich erst mal das MSB ab um zu sehen, ob sie
hochzaehlt, was sie aber nicht macht. Sie wäre ein guter
Zufallsgenerator, aber zaehlt nicht vernünftig hoch? Auf anderen
Controllern läuft sowas, wieso nicht bei Atmels????
Port B0 kommt jede ms ein Puls!

volatile uint16_t uiTimer0High;

INTERRUPT(SIG_OUTPUT_COMPARE0);
void SIG_OUTPUT_COMPARE0(void)
{
  PORTB |=  _BV(PB0);
  uiTimer0High += 1;
  PORTB &= ~_BV(PB0);
}

int main (void)
{
  uint16_t i, u16Time;

  WDTCR = ((1<<WDTOE) | (1<<WDE));
  WDTCR = 0x00;
  OCR0  = 19;             // 20MHz  1024  195,315) = 1000 Hz
  TCCR0 = ( (0<<FOC0)
          | (1<<WGM01) | (0<<WGM00)
          | (0<<COM01) | (0<<COM00)
          | (1<<CS02)  | (0<<CS01)  | (1<<CS00) );

  while(1)
  {
    /*Reinit Controller-Registers*/
    TIMSK  = _BV (OCIE0); // Timer0 = Bastime

    cli();
    // read actual time
    u16Time = uiTimer0High;
    sei();

    if (u16Time & 0x8000)
      PORTB |=  _BV(PB1);
    else
      PORTB &= ~_BV(PB1);
  }
}

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab jetzt nur mal schnell drüber geschaut, aber:
Wo wird der WatchDog resettet?
Der Puls soll nach 33s kommen (1ms * 32768)?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Andreas:
Nö, das hier
> WDTCR = ((1<<WDTOE) | (1<<WDE));
> WDTCR = 0x00;
schaltet den WDT aus. Dann muss er auch nicht geresettet werden.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> INTERRUPT(SIG_OUTPUT_COMPARE0);
> void SIG_OUTPUT_COMPARE0(void)...

Was ist das denn???

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass mich raten: Der Compiler gibt Dir ne Warnung aus, dass die Funktion
SIG_OUTPUT_COMPARE0 nie aufgerufen wird?!? Außerdem arbeitest Du
anscheinend mit einer veralteten AVR-libc-Version. INTERRUPT ist
jedenfalls nicht mehr aktuell und war auch früher (als die libc-Version
noch 'in' war) mit größter Vorsicht zu genießen. Wenn Du keine
Update-Möglichkeit hast, dann benutze bitte SIGNAL anstelle von
INTERRUPT. Darüberhinaus ist Deine ISR leer
('INTERRUPT(SIG_OUTPUT_COMPARE0);'), was dazu führt, dass überhaupt
nix gemacht wird, soll heißen, Deine Variable dürfte sich gar nicht
ändern. Was die Zeile darunter soll, weißt wohl nur Du selber...

Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob die ISR-Routine korrekt ist, ist sicher fragwürdig, aber wieso kommt
dann der Port B0 so regelmässig im 1-ms-Takt ?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mal ne ganz banale Frage:
Arbeitest du überhaupt mit AVR-GCC ?

Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal die die ISR so aufgerufen:

INTERRUPT(SIG_OUTPUT_COMPARE0)
{
  ...
}

Fehler tritt aber wie gehabt auf!
Das Schlüsselwort SIGNAL hab ich noch nie benutzt, werde es aber gleich
mal testen...
Was soll den mit INTERRUPT(..) nicht funktionieren?

Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl Heinz: Ja, hab WinAVR GCC 3.4.1 (war wohl der grösste Fehler den
ich machen konnte) :-(

Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie würdet ihr denn die paar Zeilen Code schreiben?
Dann kann ich mal eure Ideen testen.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als aller erstes holst du dir mal einen neuen
Compiler.
Die aktuelle Version ist 4.irgendwas

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
INTERRUPT leitet eine unterbrechbare ISR ein. So etwas sollte man nur
dann verwenden, wenn man 100%ig sicher ist, was man tut. Ich würde vor
allem die Erzeugung dieser kurzen Impulse in der ISR bleiben lassen und
den Pin einfach jeweils toggeln. Das gibt ein sauberes Signal und nicht
irgendwas, das jede ms für ein paar 100ns auf High-Pegel geht.
Zumindest an den Initialisierungen kann ich jetzt keinen Fehler
entdecken.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die aktuelle Version ist 4.irgendwas

und dann schreibst du:


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

volatile uint16_t uiTimer0High;

ISR( TIMER0_COMP_vect )
{
  PORTB |=  _BV(PB0);
  uiTimer0High += 1;
  PORTB &= ~_BV(PB0);
}

int main (void)
{
  uint16_t u16Time;

  DDRB = 0x02;    // untersten 2 Bit von Port B sind Ausgang

  OCR0  = 19;             // 20MHz  1024  195,315) = 1000 Hz
  TCCR0 = ( (1<<WGM01) | (0<<WGM00)
          | (0<<COM01) | (0<<COM00)
          | (1<<CS02)  | (0<<CS01)  | (1<<CS00) );

  TIMSK  = _BV (OCIE0); // Timer0 = Bastime
  sei();

  while(1)
  {
    cli();
    // read actual time
    u16Time = uiTimer0High;
    sei();

    if (u16Time & 0x8000)
      PORTB |=  _BV(PB1);
    else
      PORTB &= ~_BV(PB1);
  }
}

* Wenn man einen Port als Ausgang benutzen will, dann
  sollte man auch das entsprechende DDR Bit setzen

* Lass den Watchdog in Ruhe
  Der ist beim Hochfahren sowieso ausgeschaltet.
  Kein Grund da an den Bits rumzupfriemeln.

* Innerhalb der while Schleife am Interrupt Bit
  rumzumachen ist keine gute Idee. Im besten Fall
  passiert nichts, im schlimmsten Fall initialisiert
  sich alles neu. Keine Ahnung wie das beim AVR ist.
  Ich halte mich an die alte Regel: Initialisert wird
  nur einmal, bzw. dann wenn eine Umkonfigurierung
  notwendig ist. Ansonsten laesst man die Konfig in Ruhe.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> * Wenn man einen Port als Ausgang benutzen will, dann
>   sollte man auch das entsprechende DDR Bit setzen

Selbst reingefallen.
Du benutzt ja PB0 und PB1. Also:

  DDRB = 0x03;

Ist mir im Simulator nicht aufgefallen

Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit der Reinitialisierung hat wichtige "Lang-Laufzeitgründe". Wenn
die SW monatelang ununterbrochen laufen muss, beschreib ich
grundsätzlich alle Register immer wieder, wenn ihr Inhalt statisch
bleibt. Bei EMV-Störungen könnten sonst ein Register seinen Wert
verlieren und die uC-Schaltung kommt ohne Spannungsunterbrechnung nie
wieder auf die Beine.

Beim Watchdog stimm ich Dir voll und ganz zu. Den will ich auch wieder
beleben, wenn das Ganze mal grundsätzlich funzt.

Die Int-Bit Manipulation ist notwendig, da die 16 Bit Operation doch
durch einen Int unterbrochen werden kann, deshalb schalt ich ihn für
diese Zuweisung ab!

Inzwischen hab ich auch die jüngste Version des WinAVR runtergeladen...
und bereu' es bitter!!!!
Die WinAVR-Macher halten wohl nicht's von gewissen
Abwärtskomatibilitäten... Jedenfalls kennt die neue Version kein
einziges Register mehr...   Na prima!

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann nicht sein.
Ich benutze selbst die neueste Version und bis auf
ein paar kleinen Änderungen lief dein Pgm auf
Anhieb durch den Compiler.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine der Anderungen waren zb.
die includes ganz am Anfang.
Ohne die ist es klar: nichts geht mehr, nicht ist mehr bekannt :-)

Autor: Corinna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Compiler läuft wieder, hatte makefile aus dem demo Beispiel verwendet
und den falschen Controller-Typ noch aktiv.
Tut mir leid WinAVR!
Trotzdem funzt die Sache draussen auf der HW NICHT !
Selbes Bild wie bisher.
Port B1 muss doch im 32,76 Sek. Takt toggeln ?!?!?!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Bei EMV-Störungen könnten sonst ein Register seinen Wert
> verlieren und die uC-Schaltung kommt ohne Spannungsunterbrechnung
nie
> wieder auf die Beine.

Nein, die IO-Register haben nach einem Hardware-Reset definierte
Werte (die im Datenblatt stehen), egal ob der Reset ein power-on,
externer oder watchdog reset war.  Nach einer EMV-Störung ohne
Reset weiterzuarbeiten ist sowieso tödlich.

Bist du dir eigentlich sicher, dass deine Hardware überhaupt richtig
funktioniert?  Karl Heinz hat dir das Beispiel ja nun wirklich bis
ins letzte funktionsfähig übergeben.

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.