logo_elektromys.eu

/ AVR nové generace |

/ Úvod |

Tímto článkem bych rád zahájil novou serii tutoriálů o AVR. Atmel, dnes už Microchip, vyrábí novou řadu Attiny a Atmega. Která se od původních AVR zásadně odlišuje. A to jak skladbou periferií tak programovacím a debugovacím rozhraním. Možnosti které se tím bastlířům otevírají jsou lákavé a proto se pokusím najít čas a seznámit vás i sebe s jejich ovládáním. Ve článku o (low-cost) debuggerech jste se už mohli dočíst jeden z klíčových benefitů nového programovacího rozhraní UPDI. Tím je možnost obstarat si opravdu levný a schopný debugger. Než se vrhneme na nějaké detailnější informace, uděláme si malý výčet čipů o kterých teď obecně bude řeč. Nové čipy se totiž ve svých názvech nijak charakteristicky neliší od starších AVR. Řeč bude o mikrokontrolérech z následujícího seznamu.

TinyAVR 1-series MegaAVR 0-series

/ Errata |

Podotknu, že ceny se pohybují v příjemném pásmu 10-25kč za Attiny a mezi 30-40kč za Atmega. Web je celý protkaný nesčetným množstvím článků (tady, tady a nebo tady), představujících možnosti nových AVR, takže nebudu plýtvat časem na to abych je popsal. Naopak co si pár řádků zaslouží je Errata. Protože jde o "mladé" čipy, mají vcelku bohatý seznam chyb. Naštěstí ne tak bohatý aby vás to odradilo. První na seznamu je komparátor, který může občas falešně hlásit překročení komparační hladiny. Jak moc často se to stává si ověříme později v tutoriálu o komparátoru. AD převodník má chyby, které se nezdají nijak zvlášť omezující. Timer/Counter B má jisté citelné omezení v režimu měření externího PWM. Další chybky jsou v modulu TWI (I2C) a těžko říct jak moc budou komplikovat práci. Jistá drobnost, s nejspíš zanedbatelným dopadem je také v UARTu.

/ Hardware |

Není to tedy tak strašné a nic nám nebrání postoupit dál a podívat se na čem budeme provádět experimenty. Jako nejvhodnější adept se jeví Attiny416, neboť je na kitu Attiny416-Xnano (o němž už byla řeč v článku o debuggerech). Tentýž čip je navíc k dostání i v pouzdře SO-20, tedy ve formě, která bude vyhovovat asi většině bastlířů. Kdo bude chtít, může experimentovat na svém čipu a Xnano modul použit jen jako externí debugger. Komu by nestačila paměť, může sáhnout po výkonnějším Attiny1616 (ve stejném pouzdře) a návody by měly být přenositelné. Další odlišnost od starých AVR o které by jste se měli dozvědět jsou alternativní funkce vývodů. Starší AVR mají na každém z vývodů jednu až dvě funkce, nové AVR jich mají výrazně více. Některé alternativní funkce je možné "remapovat" a lze tak do jisté míry uniknout konfliktům kdy se dvě periferie odkazují na jeden vývod.

Kit na kterém budeme testovat Attiny416 - Xnano

/ Knihovny |

Dalším prvkem který doznal citelných změn oproti starým AVR jsou hlavičkové soubory. Pro přehlednost uvedu rozdíl na příkladech. Na starých AVR měl každý bit v každém registru své unikátní jméno a tím to haslo. Například prescaler se na Atmega328P nastavoval pomocí bitů CLKPS3, CLKPS2, CLKPS1 a CLKPS0 v registru CLKPR . Vy jste si nejprve pohledem do datasheetu zvolili kombinaci například 0b0101 (prescaler 32x) a zapsali jste ji jako:

 CLKPR = (1<<CLKPS2) | (1<<CLKPS0); 
Tento způsob má jeden klíčový nedostatek. Neustále musíte sledovat datasheet a bit po bitu sestavovat masky. Komu to vadilo, mohl si napsat svá makra s různými kombinacemi a v kódu se pak už odkazovat jenom na ně. A stejný přístup zvolili u Atmelu. Nové hlavičkové soubory (o jejichž notaci se dočtete v AVR1000) obsahují nejen makra ke všem bitům ve všech registrech, ale i většinu jejich kombinací. Vysvětlím to na jednom konkrétním příkladě. V registru MCLKCTRLB (Main Clock Control B) máme bity PEN, PDIV0, PDIV1, PDIV2, PDIV3. Bit PEN zapíná a vypíná prescaler (děličku) a bity PDIV0PDIV3 vybírají dělící poměr. Mrkněme se co nám nabízí hlavičkový soubor k ovládání poměru děličky:

/* CLKCTRL.MCLKCTRLB  bit masks and bit positions */
#define CLKCTRL_PEN_bm  0x01  /* Prescaler enable bit mask. */
#define CLKCTRL_PEN_bp  0  /* Prescaler enable bit position. */
#define CLKCTRL_PDIV_gm  0x1E  /* Prescaler division group mask. */
#define CLKCTRL_PDIV_gp  1  /* Prescaler division group position. */
#define CLKCTRL_PDIV0_bm  (1<<1)  /* Prescaler division bit 0 mask. */
#define CLKCTRL_PDIV0_bp  1  /* Prescaler division bit 0 position. */
#define CLKCTRL_PDIV1_bm  (1<<2)  /* Prescaler division bit 1 mask. */
#define CLKCTRL_PDIV1_bp  2  /* Prescaler division bit 1 position. */
#define CLKCTRL_PDIV2_bm  (1<<3)  /* Prescaler division bit 2 mask. */
#define CLKCTRL_PDIV2_bp  3  /* Prescaler division bit 2 position. */
#define CLKCTRL_PDIV3_bm  (1<<4)  /* Prescaler division bit 3 mask. */
#define CLKCTRL_PDIV3_bp  4  /* Prescaler division bit 3 position. */

/* Prescaler division select */
typedef enum CLKCTRL_PDIV_enum
{
    CLKCTRL_PDIV_2X_gc = (0x00<<1),  /* 2X */
    CLKCTRL_PDIV_4X_gc = (0x01<<1),  /* 4X */
    CLKCTRL_PDIV_8X_gc = (0x02<<1),  /* 8X */
    CLKCTRL_PDIV_16X_gc = (0x03<<1),  /* 16X */
    CLKCTRL_PDIV_32X_gc = (0x04<<1),  /* 32X */
    CLKCTRL_PDIV_64X_gc = (0x05<<1),  /* 64X */
    CLKCTRL_PDIV_6X_gc = (0x08<<1),  /* 6X */
    CLKCTRL_PDIV_10X_gc = (0x09<<1),  /* 10X */
    CLKCTRL_PDIV_12X_gc = (0x0A<<1),  /* 12X */
    CLKCTRL_PDIV_24X_gc = (0x0B<<1),  /* 24X */
    CLKCTRL_PDIV_48X_gc = (0x0C<<1),  /* 48X */
} CLKCTRL_PDIV_t;

Všimněte si nejprve koncovek maker Nejčastěji tedy budete pracovat s _bm když budete chtít nastavit nebo vynulovat konkrétní bit, dále s _gc když budete chtít nastavit určitou kombinaci bitů a nebo s _gm když budete chtít skupinu bitů vynulovat. Předpokládám, že se vám tento přístup bude zamlouvat.

Citelné změny doznalo také pojmenovávání registrů a bitů. Zatímco u starých AVR měl každý registr své unikátní jméno, u nových AVR už to neplatí. Ovládacích registrů je o poznání více a tak návrháři zvolili odlišný přístup. Každé periferii přidělili unikátní jméno a registry pak pojmenovávají podle funkce. Takže například registr CTRLA najdete snad u každé periferie. Ke konkrétním registrům se tedy musíte odkazovat pomocí dvou názvů. Tak například k registru MCLKCTRLB periferie CLKCTRL (Clock Control) se lze odkazovat dvěma způsoby. Buďto přímo nebo pomocí struktury.

CLKCTRL_MCLKCTRLB = .... // přímo

nebo

CLKCTRL.MCLKCTRLB = .... // s využitím struktury

V podobném duchu se vede i pojmenování jednotlivých bitů. Název se skládá z názvu periferie a názvu bitu. Takže například maska CLKCTRL_CLKOUT_bm se odkazuje k bitu CLKOUT v periferii CLKCTRL (který mimochodem zapíná clockout funkci). Všimněte si že makro neobsahuje název registru. Každý bit v příslušné periferii by tedy měl mít (a asi i má) unikátní jméno. Kódy jsou tedy o něco rozvláčnější, ale je z nich daleko více patrné co dělají. Osobně mi tento styl docela vyhovuje. To je asi všechno co potřebujete vědět před tím než se pustíme do prvních experimentů. Doufám tedy, že se setkáme u dalších dílů tutoriálu.

| Odkazy /

Home
| V1.01 13.12.2018 /
| By Michal Dudka (m.dudka@seznam.cz) /