Schalten Sie OC1A, OC1B und OC1C mit dem Timer im CTC-Modus um

Die meisten AVR-Mikrocontroller haben drei dedizierte Pins für jeden Timer (z. B. OC1A, OC1B und OC1C), die automatisch umgeschaltet werden können, wenn der Zähler den sogenannten Höchstwert in den entsprechenden drei Registern (OCR1A, OCR1B und OCR1C) erreicht.

Ich bin mir nicht sicher, wie diese drei dedizierten Pins / Register im CTC-Modus für verschiedene unabhängige Spitzenwerte arbeiten können, und das möchte ich erreichen. Ich möchte OC1A, OC1B und OC1C (obwohl "Ausgangsvergleich", nicht durch Interrupt oder ähnliches) in unterschiedlichen Intervallen umschalten (um zu sehen, dass drei dedizierte Register und Pins vorhanden sind).

Nehmen wir an, ich möchte den AVR-Timer so programmieren, dass er die Pins OC1A, OC1B und OC1C in unterschiedlichen Intervallen umschaltet (z. B. 1 Sekunde, halbe Sekunde, Viertelsekunde), aber es funktioniert nicht wie erwartet. Ich setze Vergleichsregister A und B und C mit den drei unterschiedlichen Werten, die den größten Wert auf A haben (ich habe auch versucht, ihn auf C zu haben).

Nur OC1A wird bei der benötigten Frequenz umgeschaltet.

Mir scheint, dass es möglich wäre, wenn sie nur OC1A-Top-Löschungen des Zählers vornehmen würden, dass die drei Pins mit drei verschiedenen unabhängigen Werten arbeiten könnten. Ist das richtig?

Hier ist das Segment, das ich in das Setup meines Arduino Lenoardo (basierend auf ATmega32U4 ) eingefügt habe. Ich bin loop()leer gegangen.

  // Initialize timer1
  noInterrupts();           // Disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1C = 0;
  TCNT1  = 0;

  OCR1A = 62500;            // Compare match register 16 MHz/256/1 Hz
  OCR1B = 31250;            // Compare match register 16 MHz/256/2 Hz
  OCR1C = 15625;            // compare match register 16 MHz/256/4 Hz

  // Toggle OC1A, OC1B and OC1C => (on Lenoardo) PB5, PB6 and PB7 => digital 9, 10, 11
  // TCCR1A = 0b01010100;
  TCCR1A |= (1 << COM1C0) | (1 << COM1B0) | (1 << COM1A0);
  // TCCR1B = 0b1100
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler

  interrupts();             // Enable all interrupts
Mit welchem ​​AVR hast du es zu tun?
Was ist die benötigte Frequenz und was ist die tatsächliche Frequenz?
@jippie es geht nicht um eine bestimmte Frequenz oder einen Chip, es geht darum, wie man einen beliebigen AVR verwendet, um die Pins OC1A und OC1B automatisch periodisch auf unterschiedliche Werte für OCR1A / OCR1B umzuschalten
Sie sind immer noch an denselben Timer gebunden. Ich bin mir nicht sicher, warum Sie denken, dass sie unterschiedliche Perioden haben können.
@ignacio-vazquez-abrams 3 verschiedene Register und 3 verschiedene Pins, was für eine Verschwendung, wenn sie etwas anderes haben können. Können sie unterschiedliche Phasen haben? irgendetwas?
Natürlich können sie unterschiedliche Phasen haben. Verwenden Sie PWM oder CTC mit ICR1 als TOP und stellen Sie sie dann auf andere Werte ein. Oder sie können differentiell sein. Stellen Sie einen auf nicht invertierend und einen anderen auf invertierend ein und geben Sie ihnen denselben Wert.
@IgnacioVazquez-Abrams die Frage bezieht sich auf CTC. also das sind OCR1A und OCR1B .. sollen unterschiedliche Phasenverschiebung nicht Frequenz bilden. Bitte bilden Sie es als Antwort und ich werde es auswählen. Bitte fügen Sie Beispielcode bei.

Antworten (2)

Ein Timer im Normal-, Fast PWM- oder CTC-Modus zählt direkt von UNTEN nach OBEN, wenn kein externer Einfluss ausgeübt wird. Wenn es jeden OC-Wert passiert, gibt es einen Interrupt aus und/oder frobs einen Pin, wie es konfiguriert ist. Jeder OC-Wert wird nur einmal gekreuzt , was bedeutet, dass alle OCs für den gleichen Timer alle mit der gleichen Frequenz laufen .

Sie können so konfiguriert werden, dass sie unterschiedliche Phasen haben oder basierend auf den Werten von OCRnr- und COMnrb-Bits in differentiellen Paaren arbeiten, aber die einzige Möglichkeit, sie direkt unterschiedliche Frequenzen verwenden zu lassen, besteht darin, ihre OCR-Werte bei jedem Aufruf ihrer ISR zu manipulieren.

Der einfachste Weg, die Pins mit unterschiedlichen Frequenzen wechseln zu lassen, wäre, den Timer auf den GCF/LCM der verschiedenen gewünschten Perioden/Frequenzen einzustellen, eine Zählung der verstrichenen Zyklen aufrechtzuerhalten und dann die Pins zu schlagen, wenn die entsprechende Anzahl von Zyklen vergangen ist .

Um es klarzustellen, die Aussage "drei dedizierte Pins für jeden Timer (z. B. OC1A, OC1B und OC1C)" in der Frage ist nicht wahr. OC1A, OC1B und OC1C sind einem und nur einem Zeitgeber zugeordnet, nämlich Zeitgeber1 (16-Bit-Zeitgeber).

Mit dem Timer-Modul können Sie mehrere Ausgänge mit unterschiedlichen Arbeitszyklen erzeugen, aber alle haben dieselbe Grundfrequenz. Wenn Sie andere Frequenzen erzeugen möchten, müssen Sie eine andere Methode verwenden. Es gibt zwei Hauptwege, dies zu tun. Die erste Methode besteht darin, drei Timer zu verwenden, die jeweils mit einer anderen Frequenz arbeiten. Wenn Sie versuchen, relativ niederfrequente Ausgänge (1 kHz oder weniger) zu erzeugen, können Sie einen angemessenen Timer-Tick und eine Interrupt-Routine verwenden. Wenn Sie 1 Hz, 2 Hz und 4 Hz erzeugen möchten, können Sie einen Timer-Tick von mindestens 8 Hz einstellen und dann Ticks zählen und die Pins zum richtigen Zeitpunkt ein- und ausschalten. Bei einem 8-Hz-Timer-Tick würde die Erzeugung eines 4-Hz-Ausgangs das Umschalten des Pins bei jedem Zyklus erfordern, 2 Hz wäre jeder zweite Zyklus und 1 Hz wäre alle 4 Zyklen.

Ich versuche, die Verwendung von 3 Registern TCCR1A, TCCR1B und TCCR1C zu verstehen und 3 entsprechende Pins (OC1A, OC1B und OC1C) umzuschalten. warum es 3 dedizierte Pins, Register und Werte gibt, wenn praktisch nur einer verwendet würde.