mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega32 - 8-Bit-Timer


Autor: Dietmar P. (dietmar2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wieder einer, der seine Hausaufgaben nicht alleine machen kann.

Ich taste mich an den Timer im Atmega 32 ran und habe ein kleines 
Testprogramm dazu geschrieben, nur tut es nicht. Die C-Syntax ist wohl 
richtig, aber die Timer-Logik nicht.

Habe versucht nach dem Datenblatt folgende Aufgabe zu lösen:
- Taktfrequenz Prozessor intern 1 Mhz
- Prescaler auf 1024 setzen
- Overflow zählen
- bei jeweils vierten Überlauf LED an Pin 0 von PORTA an- bzw. 
ausschalten
  (Ergebnis sollte ein Blinkimpuls von ca. einer Sekunde sein)

Hier mein Code:
// Timer Testprogramm

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

  volatile unsigned int Counter = 0;  // Zähler für Timer
  uint16_t i = 0;           // Zähler bei Bedarf verwendet

  ISR(SIG_OUTPUT_COMPARE0)    // Timer 0 overflow ISR
  {
    Counter++;
  }

int main(void)
{  
  
  DDRA = 0xff;    // PORTA auf Ausgang
  PORTA = 0xff;    // internal pullup on 
  
// ********** Timer init ******

  TCNT0 = 0x00;        //Timer 0 mit Null initialisieren
  TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); // Teiler: 1024
  TIMSK = ( 1 << TOIE0 );     // Overflow Interrupt einschalten
  TIMSK |= (1 << OCIE1A);     // Vergleichsregister Interrupt für Timer einschalten
  sei();         // Interrupts aktivieren
  
 
  // ***** HAUPTROUTINE ******

  while(1){

//    _delay_ms(100);    // Verzögerung 

  if (Counter >= 4){
  Counter = 0;
  if (i==0){
    PORTA |= (1<<1);    // PortA Pin1 auf high 
    i=1;
    }
  else{
    i=0;
    PORTA &= ~(1<<1);    // PortA Pin1 auf low 
  }
     }
  }  //while 
}//main

Könnt Ihr mir bitte helfen?

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dietmar P. schrieb:

> - bei jeweils vierten Überlauf LED an Pin 0 von PORTA an- bzw.

<->
>     PORTA |= (1<<1);    // PortA Pin1 auf high

?

Autor: Ziegenpeter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Könnt Ihr mir bitte helfen?
Wobei?

P.S.:
>> Overflow zählen  !=  ISR(SIG_OUTPUT_COMPARE0)

Autor: Dietmar P. (dietmar2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für Eure Info's.

@ Justus:

Klar hatte mich vertippt, muss natürlich Pin 1 heißen.

@ Ziegenpeter:

Da ich noch keinen Timer programmiert habe, wäre eine Ergänzung / 
Korrektur der Timer Zeilen sinnvoll.

>> Overflow zählen  !=  ISR(SIG_OUTPUT_COMPARE0)

Wie setze ich das syntaktisch um?

Conter != ISR(SIG_OUTPUT_COMPARE0)

Zählt er dann so?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein.  Du hast mehrere Probleme auf einmal.
  TIMSK = ( 1 << TOIE0 );     // Overflow Interrupt einschalten
  TIMSK |= (1 << OCIE1A);     // Vergleichsregister Interrupt für Timer einschalten
Hiermit schaltest Du 2 Interrupts frei (der Kommentar in der zweiten 
Zeile ist schlicht verkehrt).  Nur für einen dieser 2 gibt es eine 
Interruptroutine.  Für den anderen gibt es keine, und das heißt, dass 
der Default-Handler dafür in Aktion tritt, denn angesprungen wird eine 
Interrupt-Routine ja trotzdem.  Und der Default-Handler macht einen 
Soft-Reset.

Und dann schau Dir mal genau an, für was Du eine Interrupt-Routine 
gebaut hast.  Das "was" steckt im Argument zu ISR(), wo Du eine 
veraltete und nicht mehr empfohlene Bezeichnung gewählt hast:
ISR(SIG_OUTPUT_COMPARE0)
Die funktioniert aber trotzdem noch, nur passt „Output Compare“ nicht zu 
Deiner Beschreibung, wonach Du Overflows zählen möchtest.  Für letztere 
hast Du nichts vorgesehen (was den besagten Soft-Reset ergibt).

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

Bewertung
0 lesenswert
nicht lesenswert
* Welchen Interrupt willst du eigentlich?

  Den Overflow

  oder den Compare Interrupt

* du solltest dir schleunigst angewöhnen, nur die Interrupts
  freizugeben, für die du auch Handler hast!
  Tritt ein Interrupt Ereignis auf, das du freigegeben hast und
  hast du keinen Handler dafür, dann wird der µC resettet.

Autor: Dietmar P. (dietmar2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leute seid gnädig, ich habe ja geschrieben, dass ich mich heran taste. 
Das Datenblatt vom Atmega32 ist für einen Einsteiger schon etwas 
verwirrend. Einen Teilhabe ich aus dem Netz, offenbar verkehrt.

Nur den Overflow Interrupt wollte ich.
Ist ISR() selbst veraltet, oder das Argument in der Klammer?

Ich möchte als Test im ca. Sekundentakt den Pin1 von PortA abwechselnd 
auf high bzw. low schalten, um für weitere Anwendungen den Timer 
einsetzen zu können.
Dabei bin ich davon ausgegangen, dass 1MHz/1024/256/4 ca. 1 Hz ergibt.

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

Bewertung
0 lesenswert
nicht lesenswert
Dietmar P. schrieb:
> Leute seid gnädig, ich habe ja geschrieben, dass ich mich heran taste.
> Das Datenblatt vom Atmega32 ist für einen Einsteiger schon etwas
> verwirrend. Einen Teilhabe ich aus dem Netz, offenbar verkehrt.

Nein nicht verkehrt.

> Nur den Overflow Interrupt wollte ich.

Warum nimmst du dann nicht den Overflow Interrupt?
AVR-GCC-Tutorial
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ist ISR() selbst veraltet, oder das Argument in der Klammer?

Das Argument.  Siehe AVR-libc-Dokumentation, z.B. 
http://www.nongnu.org/avr-libc/user-manual/group__... .

Autor: Dietmar P. (dietmar2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Eure Hinweise und Links,
jetzt kann ich wieder weiter basteln.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dietmar P. schrieb:
> DDRA = 0xff;    // PORTA auf Ausgang
> PORTA = 0xff;    // internal pullup on

Ist übrigens auch verkehrt. Mit der zweiten Zeile schaltest Du in diesem 
Fall alle Pins in Port A auf 1, da Du Port A auch komplett als Ausgang 
definiert hast. Die zweite Zeile würde stimmen, wenn Du Port A komplett 
als Eingang geschaltet hättest (mit DDRA = 0;)

Autor: Dietmar P. (dietmar2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hatte ich wohl viel zu kompliziert gemacht.
Habe den Code gem. Eurer Hinweise geändert und läuft!
LED taktet mit ca. einer Sekunde.

Hier mein bereinigter Code:
// Timer Testprogramm

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

  volatile unsigned int Counter = 0;  // Zähler für Timer
  uint16_t i = 0;           // Zähler bei Bedarf verwendet

  ISR (TIMER0_OVF_vect)
  {
    Counter++;
  }

int main(void)
{  
  
  DDRA = 0xff;    // PORTA auf Ausgang
  
// ********** Timer init ******

  TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); // Teiler: 1024
  TIMSK = ( 1 << TOIE0 );     // Overflow Interrupt einschalten
  sei();         // Interrupts aktivieren
  
 
  // ***** HAUPTROUTINE ******

  while(1){

  if (Counter >= 4){
  Counter = 0;
  if (i==0){
    PORTA |= (1<<1);    // PortA Pin1 auf high 
    i=1;
    }
  else{
    i=0;
    PORTA &= ~(1<<1);    // PortA Pin1 auf low 
  }
     }
  }  //while 
}//main

Autor: Mario Grafe (mario)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht aber auch schicker mit dem Timer 1 (16-bit). Da kannst du dir 
nämlich den Compare ausrechnen lassen und den CTC-Mode benutzen (die 
Sekund ist allerdings nicht ganz genau, da 1Mhz nicht glatt durch 1024 
teilbar ist):
// Timer Testprogramm

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

ISR (TIMER1_COMPA_vect)
{
   PORTA ^= (1 << PA0); 
}

int main(void)
{  
  
  DDRA = 0xff;    // PORTA auf Ausgang
  
  TCCR1B = (1<<WGM12) | (1 << CS12) | (1 << CS10); // CTC und Teiler:1024
  OCR1A  = (uint16_t)(F_CPU/1024);     // Overflow-Wert (gerundet)
  TIMSK  = (1 << OCIE1A);;             // Overflow Interrupt einschalten

  sei();         // Interrupts aktivieren
  
  for(;;)
  {
  }

}

Einfach mal in Ruhe durchgehen...

Autor: Dietmar P. (dietmar2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Mario,

sicher das ist eleganter, danke.
Die Sekunde muss auch nicht genau stimmen.
Schrittchen für Schrittchen wächst das Atmega- Wissen.

Gruß
Dietmar

Autor: Mario Grafe (mario)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach dir nichts draus, hat bei mir auch ne Weile gedauert bis ich die 
umfangreichen Funktionen des Timers verstanden habe.

Gruß
Mario

Autor: jrraid (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat das schon mal jemand mit dem Pollin Board versucht? Bei mir 
funktioniert der code nicht. PORTS und DDR hab ich entsprechend dem 
board aufbau geändert aber nix passiert.

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.