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...
1 | //Bit Nr 76543210
|
2 | TCCR0A = B00100011; |
3 | //Bit Nr 76543210
|
4 | TCCR0B = B00000011; |
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 ...
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 | }
|
Hallo, auch wenn du keinen Arduino haben solltest, die Timerconfig bleibt gleich. Nur den Pin musste anders als Ausgang programmieren.
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.
:
Bearbeitet durch User
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.