Hallo,
nun denn. Die Frequenz legen wir einmal auf 100Hz fest.
Die Einstellungen sehen dann wie unten aus. Wie kommt man darauf?
Die Seitenangaben beziehen sich noch auf eine ältere Ausgabe vom Manual.
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 haben wir 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. Einfach rumspielen ...
1 | /*
|
2 | IDE 1.8.5
|
3 | Arduino Mega2560
|
4 |
|
5 | LED mit 25% Duty Cycle bei 100Hz
|
6 |
|
7 | Pinouts >>> http://www.pighixxx.net/pinoutspg/boards/
|
8 | Uno >>> http://www.pighixxx.net/portfolio-items/uno/?portfolioID=314
|
9 | Mega2560 >>> http://www.pighixxx.net/portfolio-items/mega/?portfolioID=314
|
10 |
|
11 | */
|
12 |
|
13 | // Mega
|
14 | // const byte Takt_Pin = 12; // OC1B bzw. PB6, nicht invertiert
|
15 |
|
16 | // Uno
|
17 | const byte Takt_Pin = 10; // OC1B bzw. PB2, nicht invertiert
|
18 |
|
19 |
|
20 | void setup() {
|
21 |
|
22 | pinMode(Takt_Pin, OUTPUT);
|
23 | set_Timer1();
|
24 | }
|
25 |
|
26 |
|
27 | void loop()
|
28 | {
|
29 |
|
30 | }
|
31 |
|
32 |
|
33 | // ****** Funktionen ******* //
|
34 |
|
35 | void set_Timer1() // Fast-PWM, Mode 15
|
36 | {
|
37 | cli(); // Interrupts ausschalten
|
38 | TCCR1A = 0; // Reset TCCR1A Register
|
39 | TCCR1B = 0; // Reset TCCR1B Register
|
40 | TIMSK1 = 0; // Reset TIMSK1 Register
|
41 | TCNT1 = 0; // Start 0
|
42 | OCR1A = 19999; // TOP Wert bestimmt Auflösung und mit Prescaler den PWM Takt
|
43 | OCR1B = 5000; // Pulsweite, OCR1B <= OCR1A
|
44 | TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10); // nicht invertiert
|
45 | TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11); // Prescaler 8
|
46 | sei(); // Interrupts einschalten
|
47 | }
|