Allgemein

Die Atmega*U besitzen zusätzlich zu den gewohnten Taktquellen eine PLL. Diese rastet in die gewählte Taktfrequenz ein und dient dazu, die 48MHz für den USB-Takt zu erzeugen.

Laut Datenblatt wird der Chip mit mit aktiviertem internen RC-Oszillator ausgeliefert. Da aber auch bereits ein Bootloader für USB auf den Chips mitgeliefert wird schaltet dieser praktischerweise die Taktquelle auf den externen Quartz um. Das bedeutet, dass der Atmega*U2 nicht zuverlässig (bzw. gar nicht) ohne 8MHz bzw. 16MHz Oszillator anläuft.

Warum das Ganze?

Wie oben schon geschrieben „schaltet der Bootloader die Taktquelle um“. Wie funktioniert das denn jetzt? Das ist definitiv neu im Vergleich zu den standard-Atmegas. Prinzipiell ist diese Neuerung essentiell und hat einige gute Gründe:

  • Der Atmega*U kann über USB programmiert werden, allerdings nur der Speicher, die Fuses können von FLIP nicht verändert werden. Ohne über die Software einstellbare Taktquellen könnte man also nicht zwischen den verschiedenen wählen.
  • Der Atmega*U kann theoretisch vom USB in den Sleep-Mode geschickt werden (Ruhemodus des PC, …). Dann darf der Controller nur noch einen geringen Strom aus der USB-Leitung ziehen. Dafür kann zB die PLL und der externe Takt abgeschalten und der Controller über den internen RC-Oszillator gespeist werden.

Register

Folgende Register stehen zur Verfügung:

Name 7 6 5 4 3 2 1 0
CLKSEL0 RCSUT1 RCSUT0 EXSUT1 EXSUT0 RCE EXTE - CLKS
CLKSEL1 RCCKSE L3 RCCKSE L2 RCCKSE L1 RCCKSE L0 EXCKSE L3 EXCKSE L2 EXCKSE L1 EXCKSE L0
CLKSTA - - - - - - RCON EXTON
OSCCAL CAL7 CAL6 CAL5 CAL4 CAL3 CAL2 CAL1 CAL0
CLKPR CLKPCE - - - CLKPS3 CLKPS2 CLKPS1 CLKPS0
PLLCSR - - - DIV5 DIV3 PINDIV PLLE PLOCK

Umschalten zwischen Taktquellen

Unabhängig von den Fuses kann man jetzt zwischen den Taktquellen umschalten. Man hat folgende Quellen zur Auswahl

  • RC Oszillator
  • Externe Taktquelle

Für das Umschalten ist Bit0 im CLKSEL0 Register zuständig, 0 wählt den internen RC Oszillator, 1 wählt die externe Taktquelle:

CLKSEL0 |= (1<<CLKS); // Diese Zeile wählt die externe Taktquelle
CLKSEL0 &= ~(1<<CLKS); // Diese Zeile wählt den internen RC-Oszillator

Sollte diese Taktquelle aber gerade schlafen/deaktiviert sein hat man ein Problem. Man sollte also vorher sicherstellen, dass die Taktquelle auch eingeschalten ist:

CLKSEL0 |= (1<<RCE); // Diese Zeile schaltet den RC Oszillator ein
CLKSEL0 |= (1<<EXTE); // Diese Zeile schaltet die externe Taktquelle ein
CLKSEL0 |= (1<<EXTE) | (1<<CLKS); // Diese Zeile schaltet die externe Taktquelle in und wählt sie als CPU-Takt