Hallo,
nun denn. Die Frequenz habe ich jetzt mal mit 100Hz festgelegt.
Die Einstellungen sehen dann wie unten aus. Wie kommt man darauf?
Timer 1
Fast-Modi gibt es mehrere. Tabelle auf Seite 172. Modi 5, 6, und 7 sind auf feste TOP Werte festgelegt.
Das heißt die Timerfrequenz ist in diesen drei Modi nur noch mittels Prescaler einstellbar.
Der flexibelste Modi ist immer der, aus meiner Sicht, wenn man einen verwenden kann wo man den TOP Wert in einem OCR1A Register einstellen kann. Das ist nämlich gepuffert, dass heißt man kann den Wert live in seinem Programm ändern ohne den Timer stoppen/nullen zu müssen, wenn alles korrekt laufen soll mit dem Compare Match.
Wenn die Frequenz konstant bleibt, kann man für die TOP Wert Einstellung auch einen Modi nehmen wo ein ICR1 Register für TOP zuständig ist. Man könnte auch hier die Frequenz später im Programm ändern, hat nur im Code mehr Aufwand, weil ICRn ungepuffert ist, dass am Rande.
Wir nehmen Modi 15. Damit sind schon 2 Dinge festgelegt laut Tabelle Seite 172.
Das Frequenz bestimmende Register ist OCR1A und das Duty Cycle Register ist OCR1B.
Der Timer 1 beim 328P hat nur zwei OCR1x Register. A und B.
Einen verwenden wir als TOP, nämlich OCR1A, damit bleibt nur OCR1B übrig für den Hardware Taktpin oder ISR.
Die LED Frequenz ist auf 100Hz festgelegt.
Jetzt benötigen wir den TOP Wert zusammen mit dem Prescaler der die 100Hz Frequenz erzeugt.
Dazu suchen wir uns die passende Formel raus.
Abschnitt Fast-PWM, Seite 164.
Die Formel stellen wir nach TOP um.
TOP = (CPU Takt / Prescaler / Takt ) - 1
Mit Prescaler 64 erhalten wir: 2499 ... etwas wenig für einen 16 Bit Counter
Mit Prescaler 8 erhalten wir: 19999 ... schon besser
Mit Prescaler 1 erhalten wir: 159999 ... zu viel, 16 Bit geht nur bis 65535
Also nehmen wir den Prescaler 8 und TOP Wert 19999.
Damit taktet der Timer schon einmal mit 100Hz.
Jetzt wollen wir aber den Pin bei 25% der Periodendauer abschalten.
Das heißt, wir brauchen noch einen zweiten Vergleichswert für OCR1B.
25% von unseren TOP 19999 sind 5000. Das ist der Wert für unser OCR1B Register.
Damit der Timer zugehörige Pin auch schaltet, müssen wir das noch aktivieren.
Und zwar das COM1B1 Bit, Seite 171, restliche Tabelle oben.
In welchen Registern befinden sich nun die vielen Bits die wir setzen müssen?
Nun, dazu müssen wir uns im Datenblatt die Registerbelegungen mit ihren Bits anschauen.
Das beginnt ab Seite 170.
Für Fast Mode 15 müssen wir alle 4 WGM1x Bits einschalten.
Die verstreuen sich auf 2 Register. Seite 170 und 173.
TCCR1A und TCCR1B.
Prescaler soll 8 sein, wird ebenfalls im Register TCCR1B eingestellt, Seite 173.
Das sind die CS Bits. Wir benötigen hier Bit CS11.
Mehr benötigen wir nicht, alles in Code umgesetzt sieht es dann so aus. Wichtig wäre noch das man in der IDE alle Register vorher nullt, weil die intern vorgeladen werden für analogWrite usw. Sonst macht der Timer nicht das was man möchte.
Ich hoffe es ist verständlich formuliert.
Wenn ja und alles klar ist, kannste den Code ändern in dem du den Modi wechselst und für TOP
das ICR1 Register verwendest. Und/oder in der loop den Wert für die Pulsweite änderst, welcher sich in dem Bsp. zwischen 0 und 19999 (TOP) bewegen darf.
/*
Doc_Arduino - german Arduino Forum
IDE 1.8.5
Arduino Mega2560
27.12.2017
LED mit 25% Duty Cycle bei 100Hz
Pinouts >>> http://www.pighixxx.net/pinoutspg/boards/
Uno >>> http://www.pighixxx.net/portfolio-items/uno/?portfolioID=314
Mega2560 >>> http://www.pighixxx.net/portfolio-items/mega/?portfolioID=314
https://forum.arduino.cc/index.php?topic=519208.0
*/
// Mega
// const byte Takt_Pin = 12; // OC1B bzw. PB6, nicht invertiert
// Uno
const byte Takt_Pin = 10; // OC1B bzw. PB2, nicht invertiert
void setup() {
pinMode(Takt_Pin, OUTPUT);
set_Timer1();
}
void loop() {
} // loop Ende
// ****** Funktionen ******* //
void set_Timer1() // Fast-PWM, Mode 15
{
cli(); // Interrupts ausschalten
TCCR1A = 0; // Reset TCCR1A Register
TCCR1B = 0; // Reset TCCR1B Register
TIMSK1 = 0; // Reset TIMSK1 Register (disable Timer Compare Interrupts)
TCNT1 = 0; // Start 0
OCR1A = 19999; // TOP Wert bestimmt Auflösung und mit Prescaler den PWM Takt
OCR1B = 5000; // Pulsweite, OCR1B <= OCR1A
TCCR1A = _BV(COM1B1) | _BV(WGM11) | _BV(WGM10); // nicht invertiert
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11); // Prescaler 8
sei(); // Interrupts einschalten
} // end Funktion