Hallo Community,
und zwar wir sollen uns mit Registern bschaftigen.
dafür haben wir einen Programm Code für eine 5V PWM für den Arduino
bekommen:
TCCR0A = B00100011;
TCCR0B = B00000011;
OCR0B = 25;
so jetzt habe ich erst mal im Daten Blatt für den Atmega328P geschaut
http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
ab Seite 113
da habe ich herausgelesen, dass die Register Bit Nr. haben und dafür
Bezeichnungen die je nach dem ob sie auf 1 oder 0 sind aus einer Tabelle
etwas bestimmtes machen. Jetzt habe ich aber keine Ahnung was das alles
bedeutet. Also ich weiß aus der Tabelle wie ich das rauslesen muss
komme aber nicht dahinter was die zustände genau bedeuten und daraus
eine 5V PWM entsteht.
Hoffe mir kann hier jemand helfen
danke schon mal :))
Sion24 schrieb:> bedeutet. Also ich weiß aus der Tabelle wie ich das rauslesen muss> komme aber nicht dahinter was die zustände genau bedeuten und daraus> eine 5V PWM entsteht.
Dann würde ich sagen, dass du dir erstmal die Bits für folgende
Einstellungen aus den TCCR0A/B Registern rausschreibst:
- Waveform Generation Mode
- Compare Output Mode
- Clock Select Bit (Prescaler)
Dann schaust du in die Tabellen vom Datenblatt (Timer0) und liest ab,
welche Funktion durch die Bitkombinationen gegeben ist.
Und schon hast du die Eckdaten der resultierenden PWM...
TCCR0A, Bit 1 und 0 und TCCR0B Bit 3 ergeben zusammen drei Bits, mit
denen sich der "Waveform Generation Mode" einstellen lässt.
WGM steht damit auf 011, was gemäß Table 15-8 für Fast PWM steht.
Und so funktioniert auch der Rest.
Eine Gruppe von Bits ist einer Funktion zugeordnet und anhand der
Tabellen kann man dann die entsprechende Funktion zuordnen.
TCCR0B Bits 2 bis 0 sind z.B. noch der Clock Select bzw. Vorteiler. In
Table 15-9 kann man ablesen, mit welchem Takt der Timer läuft. Nämlich
mit 011 -> CLK/64, also 1/64 des Systemtaktes.
Mit dem Rest müsstest du das eigentlich selber hinbekommen. Ist nicht
soo schwer ;)
Sion24 schrieb:> Jetzt habe ich aber keine Ahnung was das alles> bedeutet. Also ich weiß aus der Tabelle wie ich das rauslesen muss> komme aber nicht dahinter was die zustände genau bedeuten und daraus> eine 5V PWM entsteht.
Dann zunächst mal hier mit Lesen beginnen.
https://www.mikrocontroller.net/articles/Timer
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 ...
Top erklärt vielen Dank.
Eine Frage hab ich aber noch eine Frage hoffe ich hab das nicht
überlesen aber wozu genau waren jetzt beim Timer TCCR0A Register die
bits COM0A1 0 und COM0B1 0?
Sion24 schrieb:> wozu genau waren jetzt beim Timer TCCR0A Register die> bits COM0A1 0 und COM0B1 0?
Guck doch ins Datenblatt! Da sind alle Register tabellarisch
dargestellt.
Hallo,
ich helfe dir auf die Sprünge. Im obigen Beispiel lassen wir ohne Umwege
direkt vom Timer den Pin Namens "OCR1B" schalten. Dazu setzen wir das
"COM1B1" Bit. Es bewirkt das der Pin vom Timer überhaupt geschalten wird
und bestimmt ob invertiert oder nicht geschalten wird. Also in welcher
Logik das Duty Cycle wirkt. Nimm obigen Code und spiele erstmal mit
COM1B0 und COM1B1 rum.
Die erste "1" steht für Timer 1.
Das "B" steht für den Compare Channel. Wir lassen OCR1"B" schalten. "A"
ist für TOP belegt.
Die letzte 0 oder 1 steht für die Bitstelle im Register. Allerdings
nicht absolut gesehen sondern relativ. Jetzt kannst du mittels diesen 2
Bits (4 verschiedene Möglichkeiten) COM1B0 und COM1B1 einstellen wie der
Pin geschalten werden soll. Dafür dienen die Tabellen für jede
Betriebsart des Timers extra. Den Aufbau der Tabellen muss man erstmal
wirken lassen. Irgendwann rafft man das.
Ansonsten zeige deinen kompletten Timer 0 Code, beschreibe was der
machen soll und was er aktuell nicht macht wie gewünscht.
Veit D. schrieb:> 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.
Vorsicht: Das gilt längst nicht für alle Timer. DB befragen.
> 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.
ICR ist nicht zwingend ungepuffert, im "phase and frequency correct"
mode ist es gepuffert. Allerdings beherrscht den wiederum auch nicht
jeder Timer und außerdem ging's ja explizit um den Fast-PWM-Mode.
Trotzdem: immer DB lesen, niemals auf irgendwas verlassen, was man zu
kennen glaubt...
Guten Morgen,
kann ich unterschreiben.
Das nahm ich zum Anlass um wegen dem IRCn Buffer nachzulesen. Ich kann
jedoch beim besten Willen nichts von einem ICRn Buffer lesen. Es geht
immer nur um OCRnx Buffer. Diese sind, außer im Normal- und CTC-Mode,
immer vorhanden. Habe Timer 0 und 1 vom ATmega 328P und 2560 gelesen.
Vielleicht bei einem anderen ATmega? ATtiny vielleicht?