Forum: Mikrocontroller und Digitale Elektronik Timer wird nicht im main definiert?


von Jürgen H. (misteret)


Lesenswert?

Hallo zusammen,

ich würde fürs erste einfach mal gern ein Rechtecksignal am OCR1 Pin 
erzeugen.
Das würde ich gerne mit einem 16-Bit Timer realisieren.
Dazu verwende  ich einen ATmega16 und einen Quarz mit 16Mhz.



Meine Frage:
Lege ich die ganzen Register vor der main() fest?
Oder im main-Programm in einer while(1) Schleife?
Ich verstehe nicht so ganz, wenn ein Interrupt ausgelöst wird, wo das 
Programm nach Ausführung des Interrupts weitermacht.

Ich habe es so geschrieben:
main(){
/*Soll bis 20ms zählen und einen Interrupt auslösen */
TCCR1A |= (1<<OC1A); //Toggle-Modus
TCCR1B |= (1<<CS12) | (1<<CS10) | (1<<CTC1);
  // 16MHz => T = 62.5 ns
  // Mit Vorteiler mit 16Mhz / 1024
  // 62.5 ns  1024  312.5 = 20 ms => Vergleichsregister OCR1 auf
           313 setzen!
  // CTC1 gesetzt, d.h. bei Übereinstimmung von TCNT1 und OCR1 wird
           TCNT1 wieder 0 gesetzt
while(1)
{
        TCNT1H = 0x00;
  TCNT1L = 0x00; //Zählregister auf 0 gesetzt
  OCR1AH = 0x01;
  OCR1AL = 0x39; // OCR1A Register wird auf (313)d = (0x139)hex
                          gesetzt
        sei();
}
}

von Peter D. (peda)


Lesenswert?

Jürgen Hems wrote:

> Lege ich die ganzen Register vor der main() fest?

Du initialisiert die Peripherie am Anfang des Main.


> Oder im main-Programm in einer while(1) Schleife?

Das ist Quatsch mit Soße.
Wenn Du den Timer in ner Schleife ständig rücksetzt, wie soll der dann 
zählen?


> Ich verstehe nicht so ganz, wenn ein Interrupt ausgelöst wird, wo das
> Programm nach Ausführung des Interrupts weitermacht.

Genau an der gleichen Stelle, das ist ja der Sinn eines Interrupts.
Das Hauptprogramm merkt den Interrupt nicht.


Peter

von Johnny (Gast)


Lesenswert?

Wie Du es geschrieben hast macht es Sinn. Nach dem Aufstrarten springt 
die CPU (per Aufstratcode) ins Main. Dann werden Dinge erledigt die nur 
einmal gemacht werden müssen wie Register und Variabeln initialisieren. 
In der while(1) Schleife ist dann das Hauptprogramm.

Wurde eine Interruptserviceroutine abgearbeitet, macht der Controller 
dort weiter, wo er zuvor unterbrochen wurde. Es gehen also keine 
Operationen verloren.

von AVRFan (Gast)


Lesenswert?

>TCCR1A |= (1<<OC1A); //Toggle-Modus
>
>ich würde fürs erste einfach mal gern ein Rechtecksignal am OCR1 Pin
>erzeugen.

OK, aber wenn Du das über diesen Toggle-Modus realisierst, dann erledigt 
die Timerhardware die Signalerzeugung völlig autonom.  Daran ist kein 
Interrupt beteiligt!  Register setzen - leere Hauptschleife - am OCR-Pin 
Signal abgreifen.  Ein Interrupt kommt nirgendwo in Deinem Programm vor.

Sobald das funktioniert, kannst Du dann die "andere Methode" versuchen, 
nämlich das Signal über ein explizites, d. h. durch entsprechenden 
Programmcode bewirktes Pintogglen in einem Timerinterrupt ("Compare 
Match") zu erzeugen.

von Matthias L. (Gast)


Lesenswert?

Ja, aber für alle bisher beschriebenen Möglichkeiten sollte die 
while(1)-Schleife leer sein. Und das ist sie nicht.

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.