AVR Clock

K angligckému výrazu clock ve smyslu elektroniky se velmi těžko hledá plnohodnotný český ekvivalent. Nejlépe by se výraz clock dal přeložit jako taktovací frekvence. Jedná se o elektrický signál, který časuje vykonávání instrukcí v procesoru. Zjednodušeně řečeno pro AVR platí že s každou periodou clocku se vykoná jedna instrukce. Přirozeně nejde o instrukce v jazyce "C" ale o strojové instrukce, jejichž sadu si pro zajímavost můžete prohlédnout v datasheetu v sekci "Instruction Set Summary". V pravém sloupečku pak vidíte kolik taktů každá instrukce trvá. Takže například násobení (MUL) trvá 2 strojové cykly (tedy dva takty a tedy dvě periody clocku). Mějte ale pořád na zřeteli fakt, že příkazy v jazyce "C" se většinou přeloží do několika instrukcí. Náročnější příkazy jako třeba dělení mohou trvat desítky i stovky instrukcí. Frekvence clocku rozhoduje o rychlosti vykonávání instrukcí a tedy i o výpočetním výkonu mikrokontroléru. Je tedy zřejmé, že čím rychleji chcete počítat tím vyšší frekvencí musíte Atmel taktovat. Přirozeně je výpočetní čas ovlivňován také kvalitou algoritmu a mírou optimalizace. Nejlépe to asi bude vidět na příkladu násobení z=x*y velmi tupě realizovaného pomocí algoritmu

uint16_t z=0;
for(i=0;i<x;i++){
 z=z+y;
 } 

obludnost tohoto postupu bije do očí a to obzvlášť když si uvědomíte že čip má instrukci násobení, která příslušnou operaci provede ve dvou strojových cyklech. To už bychom ale hodně odbočovali od tématu clocku. Krom toho, že clock udává výpočetní rychlost tak je také zodpovědný za spotřebu. Přibližně se dá říct že spotřeba Atmelu je úměrná taktovací frekvenci. Řádově se pohybuje mezi 14mA při 16MHz s 5V napájením a 1mA při 1MHz s 3.3V napájením. Přirozeně spotřebu výrazně ovlivňují i režimy spánku. Další významnou roli hraje clock při ovládání periferií. Časovače, všechna komunikační rozhraní a i AD převodník odvozují svoje chování od taktu procesoru. U časovačů nebo jednotky USART je clock ústřední záležitostí, protože obě periferie musí obstarávat časování, které realizují na základě clocku. Na clock tak mohou být kladeny velké nároky, zvláště co se týče přesnosti a stability. Tyto tři dominantní jevy, tedy výpočetní výkon, spotřeba a požadavky periferií vás budou nutit nalézt vhodný kompromis při volbě taktovací frekvence. Například USART pro komunikaci vyššímy rychlostmi (například 115200 baud/s) bude vyžadovat aby clock byl celočíselným násobkem této komunikační rychlosti, tedy aby clock dostahoval hodnot například 9.216MHz nebo třeba 1.8432Mhz. Naopak pokud budete chtít realizovat časy v rozumných jednotkách (například us nebo jejich zlomky), budete nuceni volit frekvence vyhovující dělícím poměru předděličky pro časovače, tedy typicky 1,2,8 nebo 16 MHz. Proto aby jste těmto požadavkům mohli dostát, máte možnost u AVR volit si zdroje taktovací frekvence. Nejprve si probereme, které zdroje jsou k dispozici a pak jak je volit.

Interní RC oscilátor

Uvnitř čipu je vnitřní RC oscilátor, továrně kalibrovaný s přesností přibližně +-3%, který může sloužit jako zdroj taktovacího signálu. Jeho největší výhodou je fakt, že ke svému chodu nepotřebuje žádné vnější komponenty. Stačí tedy k čipu připojit napájení (kvalitně zafiltrované) a můžete Atmel taktovat až 8MHz. U Atmega16 můžete volit čtyři frekvence a to 1,2,4 a 8MHz. Je zřejmé, že přesnost +-3% rozhodně nebude dostačujicí pro měření časů (stopky co se odchylují každou minutu o vteřinu asi moc obdivu nesklidí). Je tedy zřejmé, že uplatnění najde tato varianta v aplikacích, kde časování nehraje klíčovou roli (a těch není málo). Tříprocentní je bohužel dost veliká i pro komunikaci rozhraním UART. Doporučovaná chyba pro 8 bitový přenos je +-2% (maximální teoretická chyba smí být +-5%). Aby ale situace nebyla tak černá, můžete frekvenci interního RC oscilátoru kalibrovat. Kalibrace probíhá v registru OSCCAL do něhož můžete kdykoli zapisovat hodnotu v rozsahu 0-0xff. Touto hodnotou můžete přeladit frekvenci oscilátoru v rozsahu 50-200%. S krokem dost jemným na to aby bylo možné nastavit frekvenci s chybou menší jak 1% od nominální hodnoty (1,2,4 a 8 MHz). Frekvence osciátoru se mění s napájecím napětím i s teplotou, takže pokud se vaše aplikace bude spoléhat na RC oscilátor a bude si potřebovat udržet rozumnou přesnost i přes změny napětí a teploty, budete muset připravit nějákou kalibrační tabulku, která registr OSCCAL naplní příslušnou hodnotou po změně provozních podmínek. Sám jsem ale této možnosti nikdy nevyužil. V závěru článku si pak v jednoduchém příkladu ukážeme jak kalibraci provést. Závěrem uvedu ještě jedno malé varování. Ovládáním OSCCAL můžete interní RC oscilátor přetaktovat skoro až na 15MHz. Což samo o sobě není nelegální, ale je potřeba si uvědomit, že interní RC oscilátor se využívá k časování zápisu do EEPROM a do Flash paměti. Pokud tedy jednu z těchto možností využíváte, je nutné aby byla během zápisu frekvence RC oscilátoru v rozsahu +-10% od nominální hodnoty. Jinak nemusí zápis proběhnout spolehlivě.

Externí zdroj taktovacího signálu

Volbou této varianty říkáte Atmelu že máte autonomní vnější zdroj taktovací frekvence. Může to být krystalový oscilátor (neplést s krystalem), jiný digitální obvod, nebo obecně libovolný zdroj obdélníkového průběhu se střídou 50%. Tato varianta se často volí, pokud potřebujete chod Atmelu s něčím synchronizovat. Vytovříte zdroj signálu a přivedete ho jako clock všem zařízením, která mají pracovat sycnronně. Můžete se pak spolehnout, že i když bude taktovací frekvence mírně kolísat, bude pro všechna zařízení stejná. Zapojení externího zdroje clocku je na obrázku a1 a je z něj patrné, že signál přivádíte do vývodu XTAL1. Když budete k nastavení clocku používat nějáký nástroj, bude s největší pravděpodobností v angličtině, tuto variantu tam najdete jako "external clock".


a1 - externí zdroj taktovacího signálu

Krystalový oscilátor

Vývody XTAL1 a XTAL2 jsou vstupem a výstupem invertujícího zesilovače, který lze nakonfigurovat jako krystalový oscilátor s krystalem připojeným mezi tyto vývody. Schema zapojení je na obrázku a2. Kapacity C1 a C2 volte v rozsahu 12-22pF (jak radí datasheet). Frekvence krystalu může být libovolná v rozsahu 0.9 - 16MHz. Po krystalovém oscilátoru sáhnete typicky ve dvou případech buď když budete potřebovat přesnou frekvenci nebo když budete chtít taktovat čip na vyšších frekvencích (16MHz). Kolem přenosti frekvence krystalových oscilátorů je docela složitá věda, vás to ale asi nemusí moc zajímat, protože bez zbytečných složitostí bude váš krystalový oscilátor držet svou frekvenci s chybou přibližně 15-20ppm (miliontin nominální frekvence). Anglicky tuto variantu hledejte pod pojmem "crystal oscillator".


a2 - Krystalový oscilátor jako zdroj taktovacího signálu

Externí RC oscilátor

Z mě neznámých důvodů, máte možnost taktovat čip i externím RC oscilátorem, který zapojíte podle schématu a3. Nikdy jsem tuto možnost nevyužil a nenapadá mě žádný pádný důvod, proč po ní sáhnout. Datasheet uvádí že frekvence by měla být přibližně F=1/3*R*C. Kapacita kondenzátoru by měla být nejméně 22pF, případně je možné využít interního kondenzátoru o hodnotě 36pF.


a3 - Externí RC oscilátor jako zdroj taktovacího signálu

Nízkofrekvenční krystalový ocilátor

V poslední řadě zmíním možnost připojit mezi XTAL1 a XTAL2 nízkofrekvenční krystal. Tím se myslí hodinový krystal s rezonanční frekvencí 32.768kHz. Zapojení je shodné jako v případě krystalového oscilátoru jen s tím rozdílem, že kondenzátory C1 a C2 jsou připojeny interně a mají hodnotu 36pF. Výběrem takto nízké taktovací frekvence výrazně zredukujete odběr Atmelu. Navíc je frekvence pěkně dělitelná na 1Hz. Cílem tedy budou různé nízkoodběrové aplikace jako třeba hodiny. Pokud ale používáte k programování běžný USBASP programátor, nezapomeňte si ověřit že umí programovat s frekvencí nižší jak 8kHz. Pokud to nedokáže, nebudete mít možnost tento zdroj hodin využívat (nebyli by jste schopni čip naprogramovat).

Jak zdroj taktovacího signálu volit

Volba clocku se provádí pomocí nastavení Fuses. Fuses lze zapisovat jedině programátorem a tudíž není možné měnit zdroj clocku za chodu programu. Zápis fuses můžete provádět buď z Atmel Studia nebo skrze celou paletu programů použitelných k naprogramování Atmelu (Extreme Burner, Avrdude atd.). Na webu k tomuto účelu existuje velice pěkná utilitka. Navolíte si fuses buď ručně nebo skrze roletková menu a jako bonus se vám v pravém dolním rohu stránky zobrazí i zápis pro Avrdude. Výběr clocku provádíte v úplně prvním řádku. Zajisté vás zarazí že seznam možností je výrazně delší než zde zveřejněných 5 variant. Je to z toho důvodu, že ke každému zdroji clocku si můžete také vybrat "start-up" time. Ten slouží k tomu aby měl zdroj hodin dostatek času se ustálit před tím než začne Atmel vykonávat program. Krystalovému oscilátoru trvá nějáký čas než získá potřebnou amplitudu a než se jeho činnost stabilizuje. Další varianty vznikají tak, že při volbě krystalového oscilátoru je potřeba předem specifikovat v jakém rozmezí se bude jeho frekvence nacházet. Volit můžete ze tří možností Low (0.9-3MHz), Medium (3-8MHz) a High (1-16MHz). Uvědomte si, že jakmile clock zvolíte a fuses zapíšete, musíte ho Atmelu také přivést. V případě interního RC oscilátoru to není problém, ten je totiž přítoment vždy. Ale pokud zvolíte například externí krystal a k Atmelu ho nepřipojíte, tak se Atmel nerozběhne. A pokud neběží, není možné se s ním spojit ISP programátorem ! O tom jak tyto problémy zvládat pojednává samostatná kapitola věnovaná fuses.

Možnosti Clockout

Některé čipy mají možnost clock vyvést na některý svůj vývod. Díky tomu můžete buď taktovací frekvenci sledovat, nebo signál využívat k synchronizaci s jinými obvody. Tuto možnost ale nemají všechny Atmely. Například relativně oblíbená Atmega328P může clock přivádět na pin PB0 (tato možnost se volí pomocí fuses). Bohužel u Atmega16 žádnou takovou možnost nemáme, takže si předvedeme dvě metody jak alespoň pevný zlomek taktovací frekvence vyvést ven z čipu. Přinejmenším proto aby jste si mohli měřením ověřit že vámi zvolená varianta pracuje tak jak očekáváte, nebo proto aby jste mohli pomocí OSCCAL kalibrovat frekvenci interního RC oscilátoru. Obě varianty budou ke své činnosti potřebovat jednu periferii. První co vás asi napadne je využít časovač. Využitím CTC mód se zaptnutým přepínáním příslušného OCx pinu můžete generovat defakto libovolný zlomek z taktovací frekvence. Nejvyšší frekvence však může být maximálně polovina frekvence clocku. Časovač je přece jen relativně vzácná periferie a u některých aplikací by vám mohlo vadit, že o něj takto přijdete. V takovém případě můžete "zneužít" ještě jednotku USART. Díky možnosti synchronní komunikace umí jednotka USART generovat na pinu XCK také zlomky clocku (opět s nejvyšší frekvencí rovnou polovině clocku). Obě tyto varianty si můžete prohlédnout na následující dvojici zdrojových kódů A) a B).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// A) improvizovaný clockou z USART
#include <avr/io.h>

int main(void){
DDRB = (1<<DDB0); // výstup pro clock ze USARTu
UBRRL = 0; // F_OUT = F_CPU/2
UCSRC = (1<<URSEL) | (1<<UMSEL); // vybíráme provoz USARTu v synchronním režimu
// od teď bychom měli mít na XCK (PB0) clock
while(1){}
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// B) improvizovaný clockout z Časovače 0
#include <avr/io.h>

int main(void){
DDRB = (1<<DDB3); // výstup OC0 (časovač 0)
TCCR0 = (1<<WGM01) | (1<<COM00) | (1<<CS00); // CTC mód + přepínání OC0 při compare události
OCR0 = 0; // strop časovače (přetečení časovače každý tick procesoru)
// přepínání OC0 ale dělí frekvenci na polovinu
// F_OUT = F_CPU/2;
while(1){}
}

Kalibrace interního RC oscilátoru

Jak již bylo řečeno kalibrace se provádí zápisem hodnoty do registru OSCCAL. Nižší hodnoty znamenají nižší frekvenci, vyšší hodnoty pak vyšší frekvenci. U mého kusu Atmega16A bylo možné přeladit 8MHz interní oscilátor na hodnotu 4.24MHz zápisem OSCCAL=0, zápisem hodnoty 0xAB jsem dosáhl relativně přesné frekvence 8MHz. Při zvyšování frekvence jsem zápisem maximální hodnoty (0xFF) nastavil frekvenci na 14.95MHz. Jen pro zajímavost je výsledný průběh na obrázku c1. Výstupní frekvence 3.98MHz napovídá že interní RC oscilátor pracuje na frekvenci 7.96MHz.


c1 - Kalibrace interního RC oscilátoru

Další možnosti správy taktovacího signálu

Některé Atmely mají možnost výstup ze zdroje taktovacího kmitočtu ještě podělit. Dělicí poměr lze měnit softwarově. Díky tomu může progra pružně manipulovat s clockem. Například kvůli snižování spotřeby. Jestliže čip vykonává relativně jednoduché úkoly, lze ho taktovat na nízké frekvenci (klidně řádově desítky kHz). Jakmile, ale potřebuje zvýšit výpočetní výkon, stačí přepnutím předděličky zvýšit takt a tudíž i výpočetní výkon. Stejně tak je možné změny clocku využívat k potřebám časovačů. V malé tabulce uvedu pár příkladů čipů, které mají buď možnost clockout nebo softwarově nastavitelnou předděličku clocku.

Atmel Předdělička Clockout Max. frekvence
Atmega48/88/168 ANO ANO 16 MHz
Atmega48A/88A/168A/328P ANO ANO 20 MHz
Atmega164A/324A/644A/1284 ANO ANO 20 MHz
ATmega640/1280/1281/2560/2561 ANO ANO 16 MHz
Atmega8 NE NE 16 MHz
Atmega8535/8515 NE NE 16 MHz
Attiny13 NE NE 16 MHz
Attiny24/44/84 ANO ANO 20 MHz
Attiny2313A/4313 NE ANO 16 MHz
Attiny48/88 ANO ANO 12 MHz
Attiny25/45/85 ANO ANO 20 MHz