www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt


Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)
  }
}

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ??

Autor: Dirk Dörr (dirkd)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> SIGNAL (SIG_OUTPUT_COMPARE1A)

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

Autor: Dirk Dörr (dirkd)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)
  {
  }

}

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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??

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ??

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ??

Autor: Sonic (Gast)
Datum:

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

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.