www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 8Bit Timer Atmega16/Overflow Interrupt


Autor: Tobias D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich hab ein problem. ich verstehe nicht, wie ich bei dem 8 bit zähler 
ein interrupt programmiere. hab mir das im tutorial mal angesehen:

/* uC: AT90S2313 */
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
  // Timer 0 konfigurieren
  TCCR0 = (1<<CS01); // Prescaler 8

  // Overflow Interrupt erlauben
  TIMSK |= (1<<TOIE0);

  // Global Interrupts aktivieren
  sei();

  while(1)
  {
    /* Sonstige Aktionen */
  }
}

/*
Der Overflow Interrupt Handler
wird aufgerufen, wenn TCNT0 von
255 auf 0 wechselt (256 Schritte),
d.h. ca. alle 2 ms
*/
ISR (TIMER0_OVF0_vect)
{
  /* Interrupt Aktion alle
  (1000000/8)/256 Hz = 488,28125 Hz
  bzw.
  1/488,28125 s = 2,048 ms
  */
}


ich verstehe nicht ganz, was das "ISR (TIMER0_OVF0_vect)" im code soll? 
kann es villt sein, dass wenn der interrupt ausgelöst wird, dass program 
dort weiterläuft? hab auch versucht das programm mal in meinen code 
einzubinden, aber bei "ISR (TIMER0_OVF0_vect)" meckert er rum. ich bin 
dabei eine uhr zu programmieren, da is die timerfunktion ganz hilfreich.

kann mir jemand villt weiterhelfen? nicht nutze einen atmega16. 4mhz 
qaurz.

mfg

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

Bewertung
0 lesenswert
nicht lesenswert
Tobias D. schrieb:

> ich verstehe nicht ganz, was das "ISR (TIMER0_OVF0_vect)" im code soll?
> kann es villt sein, dass wenn der interrupt ausgelöst wird, dass program
> dort weiterläuft?

ganz genau.

Das ist wie eine normale C-Funktion
void foo()
{
  mach irgendwas
}

nur mit dem Unterschied, dass die letzte Funktion du selber aufrufen 
musst, während eine ISR vom 'System' automatisch aufgerufen wird, wenn 
das auslösende Ereignis eintritt.

> hab auch versucht das programm mal in meinen code
> einzubinden, aber bei "ISR (TIMER0_OVF0_vect)" meckert er rum.

Dann musst du nachsehen, wie die entsprechende Interrupt routine bei 
deinem µC konkret heißt. Die Namen unterscheiden sich leicht, je nach 
Prozessor. Normalerweise heißen die Dinger so, wie sie auch im 
Datenblatt genannt werden, nur mit einem _vect hinten drann.

Wenn das übereinstimmt, dann sieh dir deine Projektkonfiguration an, ob 
du den richtigen Prozessor eingestellt hast.

Aus dem Bauch heraus würde ich nämlich sagen, dass der Interrupt beim 
Mega16 TIMER0_OVF_vect und nicht TIMER0_OVF0_vect heißt (da ist bei OVF0 
eine 0 zuviel). Der Timer hat nur einen Overflow, daher macht es keinen 
Sinn von OVF0 im Gegensatz zu zb OVF1 zu reden. Mit TIMER0_OVF_vect ist 
genau festgelegt was gemeint ist: Der Overflow vom Timer 0

Autor: Tobias D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das habe ich auch schon mal gelesen. aber ich finde es nicht mehr im 
datenblatt. wenn ich:

ISR (TIMER0_OVF_vect)
{
  /* Interrupt Aktion alle
  (1000000/8)/256 Hz = 488,28125 Hz
  bzw.
  1/488,28125 s = 2,048 ms
  */
}

in meinen code einbinde, dann erscheinen 2 fehlermeldungen:
../ProjektWecker.c:113: error: static declaration of '__vector_9' 
follows non-static declaration
und:
../ProjektWecker.c:113: error: previous declaration of '__vector_9' was 
here

was ist mit dem global enable interrupt flag? hab ich das mit:
// Global Interrupts aktivieren
  sei();
gesetzt?

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

Bewertung
0 lesenswert
nicht lesenswert
Tobias D. schrieb:

> in meinen code einbinde, dann erscheinen 2 fehlermeldungen:
> ../ProjektWecker.c:113: error: static declaration of '__vector_9'
> follows non-static declaration
> und:
> ../ProjektWecker.c:113: error: previous declaration of '__vector_9' was
> here

zeig nochmal den ganzen Code.
da könnte irgendwo eine Klammer fehlen, oder sowas in der Richtung.

Schieb auch mal die ISR vor alle anderen Funktionen. Fehlermeldungen im 
Zusammenhang mit ISR können sehr irritierend sein und nicht immer sitzt 
der Fehler auch wirklich in der ISR

>
> was ist mit dem global enable interrupt flag? hab ich das mit:
> // Global Interrupts aktivieren
>   sei();
> gesetzt?

ja.
Siehe AVR-GCC-Tutorial

Autor: Tobias D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der code:

#define F_CPU 4000000      //Takt 4Mhz


#include <avr/io.h>
#include <util/delay.h>      //Headerfile für Zeitschleife
#include <stdlib.h>
#include <stdio.h>        //für sprintf
#include "define.h"        //header
#include <avr/interrupt.h>


int main ()
{

  DDRA = 0x03;
  DDRB = 0xff;
  DDRC = 0xff;
  DDRD = 0xff;
// Timer 0 konfigurieren
TCCR0 = (1<<CS02); // Prescaler 256
// Overflow Interrupt erlauben
TIMSK |= (1<<TOIE0);

// Global Interrupts aktivieren
  sei();


//init LCD
  RS_0;

  PORTC = 0b00111000;
  E();
  wait();
  PORTC = 0b00001100;
  E();
  wait();
  PORTC = 0b00000001;
  E();
  wait();



while (1)
{

if (TCNT0 == 0xff)
{
zaehler++;
}

if (zaehler == 61)
{
zeitsec++;
zaehler = 0;
}

if (zeitsec == 60)
{
zeitmin++;
zeitsec = 0;
}

if (zeitmin == 60)
{
zeitstd++;
zeitmin = 0;
}

if (zeitstd == 24)
{
zeitstd = 0;
}

sprintf( bufferstd, "%d: ", zeitstd);
ausgabestd();
sprintf( buffermin, "%d: ", zeitmin);
ausgabemin();
sprintf( buffersec, "%d ", zeitsec);
ausgabesec();

switch (zeitsec)
{
case 0:  PORTB = 0b00000100;
    PORTD = 0b00000010;
    break;
case 1: PORTB = 0b00000100;
    PORTD = 0b00000001;
    break;
case 2: PORTB = 0b00000010;
    PORTD = 0b10000000;
    break;
case 3: PORTB = 0b00000010;
    PORTD = 0b01000000;
    break;
case 4: PORTB = 0b00000010;
    PORTD = 0b00100000;
    break;
case 5: PORTB = 0b00000010;
    PORTD = 0b00010000;
    break;
case 6: PORTB = 0b00000010;
    PORTD = 0b00001000;
    break;
case 7: PORTB = 0b00000010;
    PORTD = 0b00000100;
    break;
case 8: PORTB = 0b00000010;
    PORTD = 0b00000010;
    break;
case 9: PORTB = 0b00000010;
    PORTD = 0b00000001;
    break;
}

  //Licht
  if (PINA&(1<<PINA5))
  {
  DDRA |=(1<< DDA5);
  PORTA |=(1<<PA5);

  _delay_ms(3000);

  PORTA &=~( 1<<PA5);
  DDRA &=~( 1<<DDA5);
  }

ISR (TIMER0_OVF_vect)
{
}

}
return 0;
}

der code ist aber lang noch nicht fertig.
vor welche funktionen soll dich dir ISR schieben.
die fehlermeldungen kommen schon wieder -.-'.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias D. schrieb:
> vor welche funktionen soll dich dir ISR schieben.

Egal. Die darf nur nicht, wie jede andere Funktion auch, innerhalb einer 
anderen Funktionen stehen. Verschachtelte Funktionen kennt C nicht.

Oliver

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

Bewertung
0 lesenswert
nicht lesenswert
Tobias D. schrieb:


Ach nö!


> while (1)
> {
>
> if (TCNT0 == 0xff)
> {
> zaehler++;
> }
>
> if (zaehler == 61)
> {
> zeitsec++;
> zaehler = 0;
> }
>
> if (zeitsec == 60)
> {
> zeitmin++;
> zeitsec = 0;
> }
>
> if (zeitmin == 60)
> {
> zeitstd++;
> zeitmin = 0;
> }
>
> if (zeitstd == 24)
> {
> zeitstd = 0;
> }
>
> sprintf( bufferstd, "%d: ", zeitstd);
> ausgabestd();
> sprintf( buffermin, "%d: ", zeitmin);
> ausgabemin();
> sprintf( buffersec, "%d ", zeitsec);
> ausgabesec();
>
> switch (zeitsec)
> {
> case 0:  PORTB = 0b00000100;
>     PORTD = 0b00000010;
>     break;
> case 1: PORTB = 0b00000100;
>     PORTD = 0b00000001;
>     break;
> case 2: PORTB = 0b00000010;
>     PORTD = 0b10000000;
>     break;
> case 3: PORTB = 0b00000010;
>     PORTD = 0b01000000;
>     break;
> case 4: PORTB = 0b00000010;
>     PORTD = 0b00100000;
>     break;
> case 5: PORTB = 0b00000010;
>     PORTD = 0b00010000;
>     break;
> case 6: PORTB = 0b00000010;
>     PORTD = 0b00001000;
>     break;
> case 7: PORTB = 0b00000010;
>     PORTD = 0b00000100;
>     break;
> case 8: PORTB = 0b00000010;
>     PORTD = 0b00000010;
>     break;
> case 9: PORTB = 0b00000010;
>     PORTD = 0b00000001;
>     break;
> }
>
>   //Licht
>   if (PINA&(1<<PINA5))
>   {
>   DDRA |=(1<< DDA5);
>   PORTA |=(1<<PA5);
>
>   _delay_ms(3000);
>
>   PORTA &=~( 1<<PA5);
>   DDRA &=~( 1<<DDA5);
>   }


Ich habe jetzt ehrlich gesagt keine Lust die { und  } abzuzählen um zu 
sehen, wo du eine vergessen hast. Rück deinen Code ein, so wie es jeder 
andere Programmierer auch tut. Nach einer { erhöht sich die Einrücktiefe 
um 2 Leerzeichen. Eine } wird wieder um 2 Zeichen nach links ausgerückt 
und dann in dieser Spalte darunter weitergeschrieben. Dann muss man am 
Ende der Funktion wieder ganz am linken Rand rauskommen. Wenn nicht - da 
stimmt doch was nicht.

> vor welche funktionen soll dich dir ISR schieben.

Ganz nach vorne

....

ISR( ... )
{
  ...
}

int main()
{
  ....
}

Autor: XXX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Eine Einrückung wurde ungemein helfen. Ich habe das Gefühl, deine
ISR-Routine steht innerhalb der main.

Gruß
Joachim

Autor: Tobias D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab ich doch auch nicht, aber es geht trotzdem nicht -.-'
ich brauch nur noch diesen richtigen ISR code für den atmega 16. sonst 
läuft alles. kann mir den mal jemand sagen?!^^

Tobias

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

Bewertung
0 lesenswert
nicht lesenswert
XXX schrieb:
> Hallo
>
> Eine Einrückung wurde ungemein helfen. Ich habe das Gefühl, deine
> ISR-Routine steht innerhalb der main.

Beim drüberscrollen würde ich sogar sagen: die steht innerhalb der 
while(1).

Wie du (und ich) schon sagten: Er soll mal seinen Code vernünftig 
einrücken.

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

Bewertung
0 lesenswert
nicht lesenswert
Tobias D. schrieb:
> hab ich doch auch nicht, aber es geht trotzdem nicht -.-'
> ich brauch nur noch diesen richtigen ISR code für den atmega 16. sonst
> läuft alles. kann mir den mal jemand sagen?!^^

Rück deinen verdammten Code endlich ein!

Deine ISR steht nicht auf der Schachtelungstiefe auf der Funktionen 
erlaubt sind.

verdammt nochmal.

Autor: XXX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ISR (TIMER0_OVF_vect)
{
}

}
return 0;
}

Da paßt doch was nicht mit den }. Rück das ganze mal
anständig ein!

Gruß
Joachim

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine ISR steht in der main(),da muss sie raus.

Wenn würde an deiner Stelle den Timer so einstellen, dass er jede 
Sekunde ein Interrupt auslöst und die Zeit in der ISR hochzählen.

Autor: Tobias D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also das mit den interrupts klappt jetzt. sitze jedoch schon die ganze 
zeit an der zeit. normalerweise müssten die sekunden jede sec um 1 
steigen. jedoch brauchen sie fast 2 sec.

der code:
#define F_CPU 4000000      //Takt 4Mhz


#include <avr/io.h>
#include <util/delay.h>      //Headerfile für Zeitschleife
#include <stdlib.h>
#include <stdio.h>        //für sprintf
#include "define.h"        //header
#include <avr/interrupt.h>


int main ()
{

  DDRA = 0b10000011;
  DDRB = 0xff;
  DDRC = 0xff;
  DDRD = 0xff;
// Timer 0 konfigurieren
TCCR0 = 0b00000011; // Prescaler 256
// Overflow Interrupt erlauben
TIMSK |= (1<<TOIE0);

//Global Interrupts aktivieren
sei();


//init LCD
  RS_0;

  PORTC = 0b00111000;
  E();
  wait();
  PORTC = 0b00001100;
  E();
  wait();
  PORTC = 0b00000001;
  E();
  wait();


while (1)
{

//Licht
  if (PINA&(1<<PINA5))
  {
  DDRA |=(1<< DDA5);
  PORTA |=(1<<PA5);

  _delay_ms(5000);

  PORTA &=~( 1<<PA5);
  DDRA &=~( 1<<DDA5);
  }

  //Zeiteinstellung
/*  if (PINA&(1<<PINA2))
  {
  _delay_ms(2000);
  }
    if (PINA&(1<<PINA2))
    {
    PORTA |=(1<<PA7);
    _delay_ms(300);
    PORTA &=~( 1<<PA7);
    }
        while (!(PINA&(1<<PINA4)))
        {
          if (PINA&(1<<PINA2))
          {
          zeitstd++;
          sprintf( bufferstd, "%d: ", zeitstd);
          ausgabestd();
          _delay_ms(300);
          }

        }*/



}
return 0;
}

ISR (TIMER0_OVF_vect)
{

zaehler++;
if (zaehler == 61)
{
zeitsec++;
zaehler = 0;
}

if (zeitsec == 60)
{
zeitmin++;
zeitsec = 0;
}

if (zeitmin == 60)
{
zeitstd++;
zeitmin = 0;
}

if (zeitstd == 24)
{
zeitstd = 0;
}

sprintf( bufferstd, "%d: ", zeitstd);
ausgabestd();
sprintf( buffermin, "%d: ", zeitmin);
ausgabemin();
sprintf( buffersec, "%d ", zeitsec);
ausgabesec();

led();
}

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

Bewertung
0 lesenswert
nicht lesenswert
Tobias D. schrieb:

1) hast du dein Programm immer noch nicht eingerückt

2)

> #define F_CPU 4000000      //Takt 4Mhz

nachrechnen ergibt: das ist glatt gelogen

3)
> // Timer 0 konfigurieren
> TCCR0 = 0b00000011; // Prescaler 256

das ist kein Prescaler von 256

4)
> ISR (TIMER0_OVF_vect)

Die Zeit in der ISR hochzuzählen ist in Ordnung. Aber die Ausgabe
muss dort raus. Das dauert viel zu lange für eine ISR.

Autor: Tobias D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die ganzen informationen. jetzt läuft alles :)

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.