8Bit Timer Atmega16/Overflow Interrupt

Gast #1894492
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
#1894502
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
1
void foo()
2
{
3
  mach irgendwas
4
}

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
Gast #1894527
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?
#1894533
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
Gast #1894551
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 -.-'.
#1894576
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
1
....
2

3
ISR( ... )
4
{
5
  ...
6
}
7

8
int main()
9
{
10
  ....
11
}
Gast #1894744
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();
}
#1894761
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren