3. Systém hodin
Hodiny jsou hnacím motorem každého mikrokontroléru. ATtiny3217 lze taktovat několika možnými zdroji. Lze využít vnitřní oscilátor nebo můžeme použít vnější zdroj hodin. Vnitřní oscilátor může být 16 MHz, 20 MHz nebo 32 768 Hz. Jako externí zdroj můžeme použít krystalový oscilátor 32 768 Hz připojený na vývody TOSC2 (RB2) a TOSC1 (RB3) nebo jiný externí zdroj 32 768 Hz, který je připojen na TOSC1. Další externí zdroj hodin lze pak připojit na vývod EXTCLK (PA3). Systémové hodiny lze též vyvést z mikrokontroléru na výstupní pin CLKOUT (PB5). Grafické vyjádření systému hodin je na níže uvedeném obrázku.
Výchozím zdrojem hodin, který je nastaven z výroby, je interní oscilátor 20 MHz s předděličkou 6, tedy přibližně 3,3 MHz. Výběr interního oscilátoru 16 nebo 20 MHz je možný naprogramováním pojistek (Fuses), o kterých se dozvíme více v některé z dalších kapitol. Výběr ostatních zdrojů lze provést pomocí registru MCLKCTRLA.
3.1. Předdělička hlavních hodin
Taktovací kmitočet CPU a periferií lze upravit (zmenšit) pomocí předděličky. Toto nastavení provedeme pomocí čtveřice bitů PDIV[3:0] v registru MCLKCTRLB. Dělicí poměr lze nastavit na 2, 4, 6, 8, 10, 12, 16, 24, 32, 48, 64.
Možná vás napadá otázka, proč dělit (snižovat) kmitočet mikrokontroléru? Většinou chceme, aby byl program co nejrychlejší, tak proč ho úmyslně zpomalovat? Důvodů může být více, ale jedním z nich je spotřeba. Se zvyšováním frekvence spotřeba roste. Podívejte se na následující tabulku jak. Pokud si říkáte, že vás pár miliampér nevytrhne, tak věřte, že u mobilních zařízení, která jsou napájena z baterie, se hodí každá miliampéra. Taktéž platí, že čím vyšší proud, tím vyšší teplota a problémy spojené s tím. Vždy tedy zvažte, zda je potřeba "hnát" CPU mikrokontroléru na maximální rychlost.
| Frekvence | Spotřeba |
|---|---|
20 MHz |
10,0 mA |
10 MHZ |
5,3 mA |
5 MHz |
3,0 mA |
32,768 kHz |
19,2 µA |
3.2. Registry pro Clock System
Zápis do všech registrů pro nastavení hodin, kromě registru MCLKSTATUS, je chráněn proti neúmyslné změně (Configuration Change Protection - CCP). Chceme-li do těchto registrů zapisovat, musíme tento krok nejprve potvrdit vložením klíče IOREG (0xD8) do registru CCP. Tím zpřístupníme registry na čtyři instrukční cykly. Zápis do registru proto musí následovat bezprostředně po vložení klíče.
|
/* Zápis do chráněných registrů */
CPU_CCP = CCP_IOREG_gc; // Odemčení chráněných registrů (na 4 instrukční cykly)
CLKCTRL.MCLKCTRLB = 0x00; // Zápis do chráněného registru
Přístup k registrům pro správu hodin je možný pomocí struktury CLKCTRL. Deklarace této struktury je uvedena níže.
/* Clock controller */
typedef struct CLKCTRL_struct
{
register8_t MCLKCTRLA; /* MCLK Control A */
register8_t MCLKCTRLB; /* MCLK Control B */
register8_t MCLKLOCK; /* MCLK Lock */
register8_t MCLKSTATUS; /* MCLK Status */
register8_t reserved_1[12];
register8_t OSC20MCTRLA; /* OSC20M Control A */
register8_t OSC20MCALIBA; /* OSC20M Calibration A */
register8_t OSC20MCALIBB; /* OSC20M Calibration B */
register8_t reserved_2[5];
register8_t OSC32KCTRLA; /* OSC32K Control A */
register8_t reserved_3[3];
register8_t XOSC32KCTRLA; /* XOSC32K Control A */
register8_t reserved_4[3];
} CLKCTRL_t;
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
CLKOUT |
— |
— |
— |
— |
— |
CLKSEL1 |
CLKSEL0 |
R/W - 0 |
R/W - 0 |
R/W - 0 |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b7 |
CLKOUT |
Hodiny na výstupu CLKOUT |
0: zakázáno; |
b1 až b0 |
CLKSEL[1:0] |
Výběr zdroje hodin |
00: interní oscilátor 16/20 MHz; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
— |
— |
— |
PDIV3 |
PDIV2 |
PDIV1 |
PDIV0 |
PEN |
R/W - 1 |
R/W - 0 |
R/W - 0 |
R/W - 0 |
R/W - 1 |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b4 až b1 |
PDIV[3:0] |
Dělicí faktor předděličky |
0000: f/2; |
b0 |
PEN |
Povolení předděličky |
0: předdělička zakázána; dělicí faktor = 1; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
— |
— |
— |
— |
— |
— |
— |
LOCKEN |
R/W - x |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b0 |
LOCKEN |
Uzamčení konfiguračních registrů |
0: žádný efekt; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
EXTS |
XOSC32KS |
OSC32KS |
OSC20MS |
— |
— |
— |
SOSC |
R - 0 |
R - 0 |
R - 0 |
R - 0 |
R - 0 |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b7 |
EXTS |
Status externích hodin |
0: externí hodiny neběží; |
b6 |
XOSC32KS |
Status externích hodin 32 kHz |
0: nestabilní; |
b5 |
OSC32KS |
Status interního osc. 32 kHz |
0: nestabilní; |
b4 |
OSC20MS |
Status interního osc. 20 MHz |
0: nestabilní; |
b0 |
SOSC |
Změna zdroje hodin |
0: zdroj hodin není měněn; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
— |
— |
— |
— |
— |
— |
RUNSTDBY |
— |
R/W - 0 |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b1 |
RUNSTDBY |
Vynucení oscilátoru ve Standby módu |
1: oscilátor 16/20 MHz poběží ve všech módech, a to i když není využíván systémem; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
— |
— |
CAL20M5 |
CAL20M4 |
CAL20M3 |
CAL20M2 |
CAL20M1 |
CAL20M0 |
R/W - x |
R/W - x |
R/W - x |
R/W - x |
R/W - x |
R/W - x |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b5 až b0 |
CAL20M[5:0] |
Kalibrace oscilátoru 16/20 MHz |
hodnota po resetu závisí na FUSE.OSCCFG |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
LOCK |
— |
— |
— |
TEMPCAL20M3 |
TEMPCAL20M2 |
TEMPCAL20M1 |
TEMPCAL20M0 |
R/W - x |
R/W - x |
R/W - x |
R/W - x |
R/W - x |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b7 |
LOCK |
Uzamčení kalibračních registrů |
0: žádný efekt; |
b5 až b0 |
CAL20M[5:0] |
Teplotní kalibrace oscilátoru 16/20 MHz |
hodnota po resetu závisí na FUSE.OSCCFG; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
— |
— |
— |
— |
— |
— |
RUNSTDBY |
— |
R/W - 0 |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b1 |
RUNSTDBY |
Vynucení oscilátoru ve Standby módu |
1: oscilátor 32 kHz poběží ve všech módech, a to i když není využíván systémem; |
Detail
bit_7 |
bit_6 |
bit_5 |
bit_4 |
bit_3 |
bit_2 |
bit_1 |
bit_0 |
— |
— |
CSUT1 |
CSUT0 |
— |
SEL |
RUNSTDBY |
ENABLE |
R/W - 0 |
R/W - 0 |
R/W - 0 |
R/W - 0 |
R/W - 0 |
| bit | Symbol | Význam bitu | Popis |
|---|---|---|---|
b5 až b4 |
CSUT[1:0] |
Čas náběhu ext. osc. 32 kHz |
00: 1k cyklů; |
b2 |
SEL |
Výběr zdroje hodin |
0: externí krystal; |
b1 |
RUNSTDBY |
Vynucení oscilátoru ve Standby módu |
1: externí krastalový oscilátor 32 kHz poběží ve všech módech, a to i když není využíván systémem; |
b0 |
ENABLE |
Povolení vstupu |
1: změní konfiguraci vývodů na TOSC1 a TOSC2; bity SEL a CSUT lze pouze číst; |
3.3. Příklad: Nastavení hodin
Pro ověření práce s nastavením hodin vytvoříme jednoduchý prográmek, na kterém vyzkoušíme nastavení zdroje hodin, předděličky a dostupnost hlavních hodin na výstupu mikrokontroléru. Schéma zapojení je uvedeno níže. Využijeme tlačítko, které je na desce Curiosity, a je připojeno na vývod PB7. Pomocí tohoto tlačítka budeme měnit dělicí faktor předděličky. Výstupní signál budeme pozorovat na pinu CLKOUT (PB5).
Program je velice jednoduchý. Nastavíme PB5 jako výstup, dále je potřeba nastavit pull-up na PB7 (tlačítko při stisku přivádí na vstup log. nulu). Jako zdroj hlavních hodin je nastaven interní oscilátor 32,768 kHz a je povolen výstup CLKOUT. Poté v nekonečné smyčce kontrolujeme, zda bylo tlačítko stisknuto. Pokud ano, je nastavena předdělička na f/64 a po jeho uvolnění je nastavena zpět na výchozí hodnotu f/6.
#include <avr/io.h>
int main(void) {
PORTB.DIRSET = PIN5_bm; //PORTB5 výstup
PORTB.PIN7CTRL |= PORT_PULLUPEN_bm; //pull-up pro tlačítko
CPU_CCP = CCP_IOREG_gc; //povolit zápis do MCLKCTRLA
CLKCTRL.MCLKCTRLA = 0b10000001; //32 kHz/6, CLKOUT povoleno
while (1) {
if(!(PORTB.IN & PIN7_bm)) { //tlačítko stisknuto
CPU_CCP = CCP_IOREG_gc; //povolit zápis do MCLKCTRLB
CLKCTRL.MCLKCTRLB = 0b00001011; //předdělička f/64
while(!(PORTB.IN & PIN7_bm)){}; //čeká na uvolnění tlačítka
CPU_CCP = CCP_IOREG_gc; //povolit zápis do MCLKCTRLB
CLKCTRL.MCLKCTRLB = 0b00010001; //předdělička f/6
}
}
}
Na obrázcích vidíte signály na tlačítku a výstupu CLKOUT. Z průběhů je zřejmé, jak dlouho trvá přepnutí dělicího faktoru.
Na závěr je třeba říci, že změna frekvence hodin nebo zdroje hodin v průběhu provádění programu není až tak častá činnost. Zpravidla se zdroj hodin nastaví při startu programu a více se s tímto nastavením nemanipuluje. V příštím díle se podíváme na ovládání vstupů a výstupů mikrokontroléru, což je asi nejčastější činnost při programování.