Arduin Timer0/Timer1

Hallo Leute, ich habe ein generelles Theorieproblem mit den Timern 0 und 1.
Wir programmieren mit Registern und ich habe da einige Verständnisprobleme.
Und zwar kapiere ich nicht ganz, ob jetzt der Pin 6 am Arduino(also OC0A) was mit der Grenze OCR0A zu tun hat und analog dazu OC0B mit OCR0B ?
Und kann ich beim FastPWM Modus überhaupt ein Vergleichsregister OCR0B haben oder ist dieser nur beim CTC-Modus vorhanden ?
Und wenn ich einen Fastpwm modus einstelle mit Top OCR0A wie kann ich dann einen Comparematch bekommen bzw. geht das dann überhaupt ?

Sorry, wenns ein bisschen Anfängerfragen sind aber bin auch noch nicht so lange im Geschäft. :slight_smile:

Danke bereits für Eure Bemühungen.

mfg

Hallo.

Dafür das du noch nicht lange im Geschäft bist, habe ich kein Word verstanden. Aber wenn du herausgefunden hast wie das beim Arduino geht. Würde mich das auch interessieren.

Ansonsten hier was zu lesen. 3 Sekunden bei Googel

Artikel bei Heise.de

Hallo,

welchen Arduino hast du?
Datenblatt zu deinem µC auf deinem Arduino hast du?
Wenn du mir sagst was du eigentlich machen willst, dann erkläre ich dir das genau an deinem konkreten Bsp.
Gewisse Dinge kann man pauschal erklären, ja, aber andere Dinge sind abhängig vom gewählten Timermode.

Doc_Arduino:
Hallo,

welchen Arduino hast du?
Datenblatt zu deinem µC auf deinem Arduino hast du?
Wenn du mir sagst was du eigentlich machen willst, dann erkläre ich dir das genau an deinem konkreten Bsp.
Gewisse Dinge kann man pauschal erklären, ja, aber andere Dinge sind abhängig vom gewählten Timermode.

Ok, sorry hatte ich vergessen. Ist ein Arduino mit einem ATMega328P. Und zwar wäre die Aufgabe, dass man mit dem Timer1 eine LED mit dem Tastgrad 25% zum leuchten bringen soll. Und als Modus soll man den fast-PMW Modus mit nichtinvertierendem Modi einschalten.

http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
Seie 172 rum

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
2 Likes

Doc_Arduino:
....

WOW!! Ich danke dir von Herzen! Was für eine verständliche und lange Erklärung, das hätte ich nicht erwartet. Jetzt ist es mir schon klarer geworden, auch mit den von dir genannten Formeln, die mir nicht bekannt waren. Nochmal herzlichen Dank und einen guten Rutsch!!!

mfg

Doc, dafür gibt's auch von mir ein GANZ FETTES KARMA

Hallo,

bei dem Danke hat sich die Arbeit gelohnt für dieses eine konkrete Bsp. Danke zurück.

Ich hatte vor etwas mehr als einem Jahr schon einmal begonnen ein "kleines" Tutorial" zu schreiben. Habe jedoch von meinen strengen Lektoren agmue und Rudi keine Freigabe erhalten. :slight_smile: Seitdem liegt das unfertig rum, denn es kommt auf jede Formulierung an. Vielleicht finde ich nochmal die Zeit wenigstens den Stand den es hat zu korrigieren.

Edit: habe oben paar Kleinigkeiten korrigiert die mir heute auffielen.

Hallo,

weil die Links zu pighixxx tot sind, hänge ich hier meine gesammelten Pinouts rein. Inhalt ist am Namen erkennbar. Weil pro Post nur 2MB erlaubt sind wird das aufgeteilt. Enthalten sind .pdf's

Pinouts_Uno_Nano_ProMini.zip (1.26 MB)

  1. zip

Pinout_Mega2560.zip (1.03 MB)

  1. zip

Pinouts_Micro_Leonardo.zip (1.14 MB)

Ausgezeichnet!