Forum: Mikrocontroller und Digitale Elektronik Interrupt


von Dominik (Gast)


Lesenswert?

Hi Leute,

bin so frei gewesen und habe mir das gute Stück Software vom
Peter Dannegger (Precise 1 Second Timebase) kopiert und versucht zu
modifizieren!

Danke an Peter, für diese ausgezeichnete Software und sorry das ich
einfach so genommen hab ;) !!

Dann habe ich das halt nen bisschen geändert und versucht an meine
Bedürfnisse anzupassen, ging aber schief.Versteh aber leider nicht ganz
genau was da alles passiert !

Kann einer von mir da eventuell auf die Sprünge helfen ?
Hier das originale Programm:
=============================================================
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>


#ifndef OCR1A
#define OCR1A OCR1  // 2313 support
#endif

#ifndef WGM12
#define WGM12 CTC1  // 2313 support
#endif

#ifndef  PINC
#define  KEY_INPUT  PIND  // 2313
#else
#define KEY_INPUT  PINC  // Mega8
#endif
#define  LED_DIR    DDRB

//#define XTAL    11059201L  // nominal value
#define XTAL    8000000L  // after measuring deviation: 1.5s/d

#define DEBOUNCE  256L    // debounce clock (256Hz = 4msec)

#define uchar unsigned char
#define uint unsigned int

uchar prescaler;
uchar volatile second;      // count seconds


SIGNAL (SIG_OUTPUT_COMPARE1A)
{
/*********************************************************************** 
*/
/*      Insert Key Debouncing Here      */
/*********************************************************************** 
*/

#if XTAL % DEBOUNCE
  OCR1A = XTAL / DEBOUNCE - 1;    // compare DEBOUNCE - 1 times
#endif
  if( --prescaler == 0 ){
    prescaler = (uchar)DEBOUNCE;
    second++;        // exact one second over
#if XTAL % DEBOUNCE      // handle remainder
    OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per
second
#endif
  }
}


int main( void )
{
  LED_DIR = 0xFF;
  while( KEY_INPUT & 1 );    // start with key 0 pressed

  TCCR1B = 1<<WGM12^1<<CS10;    // divide by 1
          // clear on compare
  OCR1A = XTAL / DEBOUNCE - 1;
  TCNT1 = 0;
  second = 0;
  prescaler = (uchar)DEBOUNCE;

  TIMSK = 1<<OCIE1A;
  sei();

  for(;;){
    if( second == 60 )
      second = 0;
    LED_DIR = second;      // display second (binary)
  }
}

von Dominik (Gast)


Lesenswert?

Ich versteh z.B. nicht wofür
SIGNAL (SIG_OUTPUT_COMPARE1A)
{
.....
}

gut sein soll, sieht aus wie ne Funktion, steht aber ausserhalb des
main programmes, wird aber niemals aufgerufen und somit meiner meinung
nach nicht gebraucht. Lösche ich das allerdings raus, tut das Prog
nicht mehr ??

habe ich was übersehen ??
handelt es sich dabei um die ISR ??

von Dirk D. (dirkd)


Lesenswert?

> SIGNAL (SIG_OUTPUT_COMPARE1A)

Das ist der Interrupt Handler. Du startest einen Timer und wenn dieser
abläuft wird diese Funktion ausgeführt.

von Dirk D. (dirkd)


Lesenswert?

> und versucht zu modifizieren!

Besser wäre es mit Hilfe des Datenblattes des Controllers und der Doku.
des Compilers versuchen den Code zu verstehen.

Einfach Schritt für Schritt durchgehen.

von Dominik (Gast)


Lesenswert?

Ja besser wäre es mit dem Datenblatt ich glaub das versuch ich auch,
aber dann müsst ihr mir BITTE BITTE helfen, ok ??

Also sollte mein Programm schonmal grob so aussehen: ??
include bla bla

SIGNAL (SIG_OUTPUT_COMPARE1A)
{
...
}

void main(void)
{
  TCCR0     =  0x7c;    //
  DDRA     =  0xff;    //Port A als Ausgang definieren
  TIMSK = 0x02;
  TIFR  = 0x02;

  while(1)
  {
  }

}

von Dominik (Gast)


Lesenswert?

TCCR0 = 0x7c;

startet doch meinen Timer, der dann die ganze zeit wie dulle rennt,
und TCNT1 um 1 inkrementiert oder dekrementiert, richtig ?
und dann geh ich hin und knall nen Wert ins OCR
und sobald der wert im OCR mit dem im TCNT übereinstimmt
gibt es einen overflow??

von johnny.m (Gast)


Lesenswert?

Nein, wenn der Wert in TCNT0 mit dem in OCR0 übereinstimmt, gibts ein
Compare-Ereignis. Mit Overflow wird hier gar nicht gearbeitet. Der
Timer läuft im CTC-(Clear Timer on Compare Match) Modus, d.h. TCNT0
wird auf Null zurückgesetzt, sobald ein Compare-Ereignis auftritt. Dann
zählt er wieder hoch, bis TCNT0 den Wert in OCR0 erreicht und das
Spielchen geht von vorne los. Der Interrupt wird beim Compare-Ereignis
ausgelöst.

von Dominik (Gast)


Lesenswert?

Das heißt also:
ich schreib jetzt z.B. 200 in OCR0 rein und
TCNT0 wird von 0 bis 255 hochgezählt. kommt der Timer dann beim
hochzählen an die 200, gibts ein Compare-Ereignis und setzt auf null
und fängt von vorne an, und es wurde ein interrupt ausgelöst, der dann
die ISR
SIGNAL (SIG_OUTPUT_COMPARE1A)
{...}
aufruft, in der ich dann z.B. die led ein bzw. ausschalte ??

von Dominik (Gast)


Lesenswert?

hallo glaube ich habe nochwas rausgefunden:

TCNT0 wird von 0 bis 255 hochgezählt, das ergibt mit nem CPU Takt und
dem Prescaler von 256 folgendes:

1/fCPU   Prescaler    TCNT0max = 1/8.000.000   256  256
= 0,008192sec
und dann muss ich den scheiss 1/0,008192 mal hochzählen bis eine
Sekunde um ist, richtig ?

also 122,07......
also rechne ich mit 122, dann ist mir das schon genau genug !

Also setze ich OCR0 = 255 und dann wird wenn TCNT0 MAX erreicht ein
interrupt ausgeführt.
dieser ruft die ISR auf und in der habe ich folgendes stehen:

ISR
{
  i++;
  if(i == 122)
  {
    led an wenn aus
    led aus wenn an
    i = 0;
  }
}

soweit richtig ??
oder ist das zuviel gemüse innerhalb der ISR, das das zu lange dauert ?

von Dominik (Gast)


Lesenswert?

Hallo,
ich denke ich habe das erste Programm stehen, ist es so richtig, oder
ist da noch nen dicker Denkfehler drin ??
=====================================================================
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

unsigned char CountVariable  = 0;

SIGNAL (SIG_OUTPUT_COMPARE1A)
{
  CountVariable++;
}

void main(void)
{

//DDRA     = 0x07;  //Port A0-A2 als Ausgang definieren
DDRA     |= 0x01;//Port A0 als Ausgang definieren

TCCR0  =  0x7c;  //Startet Timer/Counter 0, von 0-255
TIMSK  =  0x02;  //enable Compare-Match Interrupt
TIFR  =  0x02;  //enable Compare-Match Interrupt
OCR0  =  255;  //Vergleichswert für Wert in TCNT0

while(1)    //Einleitung der Endlos-Systemschleife
{
  if(CountVariable == 121)
  {
    PORTA |= 0x01;  //LED (PORTA0) an
    CountVariable = 0;//Variable wieder auf 0
    }
    else
    {
    PORTA &= 0xFE;  //LED (PORTA0) aus
    }
        }
}
====================================================================

Bitte um Hilfe, weiß nicht ob das richtig ist

Vielen Dank schonmal an die Profis unter euch (also an alle) ;)

DANKE DANKE

Bitte um Hilfe, weiß nicht ob das richtig ist

von Dominik (Gast)


Lesenswert?

Ja da ist nen Fehler drin, ich weiß aber nicht wo,
habe das soeben in meinen uc geladen....
die LED leuchtet die ganze Zeit durch und ich muss die
falsch herum anklemmen das die leuchtet...
weil der uc den scheiss port auf masse zieht und nicht auf +5V


was muss ich da dann ändern,
also das der port auf +5v gezogen wird und die LED im sekundentakt
blinkt ??

von Sonic (Gast)


Lesenswert?

Vielleicht solltest Du Timer 0 und 1 nicht durcheinanderbringen!
Comare1A hat nix mit TCCR0 oder OCR0 zu tun!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.