Forum: Mikrocontroller und Digitale Elektronik Atmega CTC-Mode Impulse


von Büni (Gast)


Lesenswert?

Hallo Community,

ich stehe im Moment etwas auf dem Schlauch.

Ich benutze den Atmega162 und möchte am OCR3A-Pin 2 Impulse mit 
folgendem Muster erzeugen:

nach 120ms High --> nach 10us Low --> nach 10us High --> nach 10us Low. 
(und dabei bleiben)

Im Moment betreibe ich den Timer im CTC-Mode. Ich lade den 
Vergleichswert, der 120ms entspricht (TCCR3A = (1<<COM3A0)|(1<<COM3A1); 
- Set OCR3A on Compare Match) , habe die Interrupts aktiviert und lade 
im Interrupt den neuen Verlgeichswert für 10us und ziehe den OCR3A-Pin 
wieder auf LOW. (TCCR3A = (1<<COM3A1); Clear...on Compare Match)

Dies funktioniert gut, ich weiß nur nicht wie ich jetzt den neuen 
Vergleichswert laden soll, der den Pin wieder auf High setzt. Ich dachte 
auch bereits an den Toggle-Mode, weiß aber auch hier nicht, wie ich nach 
diesen beiden Impulsen, den Timer stoppe.

Ich dachte auch daran den OCR3B-Pin zu nutzen, der eben 10us später den 
Impuls erzeugt und in der ISR den Pin wieder auf Low zieht. Dabei müssen 
beide Pins aber das gleiche Ziel haben. Dabei habe ich eben 2 
unterschieliche Quellen.

Danke für eure Hilfe.


p.s. Wie müsste man es denn darüberhinaus machen, wenn man ein 
ungleichmäßiges Impulsmuster erzeugen möchte?

von Büni (Gast)


Lesenswert?

Ich lese oft, dass die Möglichkeit besteht den OCR-Wert upzudaten.
Ich habe dazu auch mehrfach wieder das Datenblatt zu Rate gezogen, finde
aber keine Lösung.

Wenn der Interrupt ausgelöst wird, müsste er doch immer wieder in 
dieselbe
ISR springen und übernimmt eben den dort programmierten Wert?

Es müsste doch dann auch möglich sein, den Timer nach dem zweiten 
Durchlauf
wieder zu stoppen, sodass nur die beiden Impulse erzeugt werden.


Vielleicht über eine PWM?

von Büni (Gast)


Lesenswert?

Keine Tipps?

von Karl H. (kbuchegg)


Lesenswert?

Büni schrieb:

> Dies funktioniert gut, ich weiß nur nicht wie ich jetzt den neuen
> Vergleichswert laden soll, der den Pin wieder auf High setzt. Ich dachte
> auch bereits an den Toggle-Mode, weiß aber auch hier nicht, wie ich nach
> diesen beiden Impulsen, den Timer stoppe.

Toggle Mode klingt doch gut.
Alles was du tun musst, ist in der ISR die richtigen Werte (je nachdem 
um welchen Pegel es sich gerade handelt) ins OCR Register zu laden und 
mit dem richtigen Pin-Zustand die ganze Sequenz anfangen.

Den Timer stoppst du, indem du ihm den Vorteiler abdrehst. Kein 
Vorteiler, keine Taktung des Timers. Keine Taktung des Timers - der 
Timer zählt nicht.


Wie sehen denn deine errechneten Vergleichswerte aus, damit du auf die 
Zeiten kommst? 120ms und 10µs sind ja dann doch schon etwas auseinander.

von Büni (Gast)


Lesenswert?

Hallo,

ich arbeite mit 12Mhz und einem Prescaler von 32.

Dementsprechend ergeben sich Werte von 44999 (120ms) und 4 bei (ca. 10us 
- muss nicht so genau sein)

Danke für deine Antwort. Mir fehlt es dann dabei leider an der 
Umsetzung. Ich denke, ich habe es noch nicht richtig verstanden. In 
meine timer_init() wird der Timer3 initialisiert und zwar mit dem 
Vergleichswert 44999. Nun
wird in der ISR der OCR3A-Pin mit dem Verlgeichswert 4 wieder auf Low 
gezogen. Es fehlt noch der 2te Impuls.

Wie läuft der toggle-Mode jetzt genau ab, welchen Vergleichswert nimmt 
der Timer als Grundlage um den OCR3A-Pin zu togglen? welche Frequenz 
entsteht?
Du sprichst von Werte(N), ich kann in der ISR doch aber nur einen neuen 
Vergleichswert laden.

Darüberhinaus muss ich doch dann aber auch ein unregelmäßiges 
Impulsmuster erzeugen können.

Vielen Dank.

von Karl H. (kbuchegg)


Lesenswert?

Büni schrieb:

> Dementsprechend ergeben sich Werte von 44999 (120ms) und 4 bei (ca. 10us
> - muss nicht so genau sein)

4 mal 32 sind 128.
Also 128 Takte.
Sollte sich noch ausgehen.


> Danke für deine Antwort. Mir fehlt es dann dabei leider an der
> Umsetzung. Ich denke, ich habe es noch nicht richtig verstanden. In
> meine timer_init() wird der Timer3 initialisiert und zwar mit dem
> Vergleichswert 44999. Nun
> wird in der ISR der OCR3A-Pin mit dem Verlgeichswert 4 wieder auf Low
> gezogen. Es fehlt noch der 2te Impuls.

Den erzeugt der Timer, wenn er den Pin toggelt.

  Pin auf High setzen
  Kontrolle des Pins mittels COM Bits an den Timer übergeben
  OCR  mit 44999 laden
  Count Register mit 0 laden
  Timer starten

  > die 120 ms laufen

  nach Ablauf toggelt der Timer den Pin (-> Low) und die ISR
  wird aufgerufen

  in der ISR feststellen, dass es der 1. Aufruf war
  -> OCR mit 4 laden, damit kommt der nächste Interrupt bei 10µs

  > die 10µs laufen

  nach Ablauf toggelt der Timer wieder den Pin ( -> High) und die
  ISR wird aufgerufen

  in der ISR wird festgestellt, dass dies der 2. Aufruf ist, bei
  dem nichts getan werden muss. Der Timer läuft nach wie vor weiter
  und das OCR Register zwingt ihn, sich bei 10µs wieder zu melden

  > die 10 µs laufen

  nach Ablauf toggelt der Timer den Pin ( -> Low) und die ISR wird
  aufgerufen

  in der ISR wird festgestellt, dass dies der 3. Aufruf ist und als
  Folge davon wird dem Timer der Vorteiler abgedreht.

  > Der Timer steht


> Wie läuft der toggle-Mode jetzt genau ab, welchen Vergleichswert nimmt
> der Timer als Grundlage um den OCR3A-Pin zu togglen?

Darum gehts nicht.
Der Timer Modus ist genau der gleiche. Worum es geht ist die Frage, was 
der Timer mit dem Output-Pin machen soll, wenn der Compare Match 
erfolgt. Soll er ihn auf 1 setzen, soll er ihn auf 0 setzen oder soll er 
ihn einfach nur umschalten. Die COM... Bits regeln das.


> Der Timer zählt
> Du sprichst von Werte(N), ich kann in der ISR doch aber nur einen neuen
> Vergleichswert laden.

Aber kein Mensch sagt, dass du immer denselben Vergleichswert laden 
musst. Du kannst ja auch mitzählen, der wievielte AUfruf der ISR (nach 
Start der Sequenz) das ist, un dann je nachdem einen anderen Wert laden.

von Benulba (Gast)


Lesenswert?

Zuerst einmal vielen Dank für deine ausführliche Antwort.

Ich habe jetzt in der ISR eine Variable definiert, die bei jedem 
Interrupaufruf um 1 erhöht wird. Bei der Abfrage, könnte ich dann den 
neuen
Vergleichswert laden.

Bisher funktioniert das aber noch nicht. Hier mal ein Codeauszug:
Einen Prescaler verwende ich jetzt doch nicht. Ich weiß allerding nicht 
genau, ob die Abfrage so funktioniert?

Die Variable y wurde als volatile und global definiert.

ISR (TIMER3_COMPA_vect,ISR_BLOCK)
{




  if (y == 3)  {

    TCCR3B = (0<<CS32)|(0<<CS31)|(0<<CS30);}


OCR3A = 119;
                  TCCR3B = (1<<CS30)|(1<<WGM32);



  y++;
}

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.