Autor: Prog0el | 17.11.2015 |
Můj seriál je především určen lidem, kteří mají chuť učit se užitečně pracovat s tak mnohostranně použitelným komponentem, jakým je mikrokontrolér, ať už jakýkoliv, sám. Nebudu zde popisovat rozsáhlou teorii, aniž bych ji kdy vysvětlil na praktickém příkladu, jelikož tímto postupem, mimo jiné běžně používaným na českých školách, se není schopen člověk naučit chápat studovanou látku jako celek. Každý následující díl bude složen z příkladu, který motivuje k pochopení toho, jak daná aplikace funguje. Zanedlouho si ukážeme praktické aplikace jako jednoduchý displej s běžícím textem, kalkulačku, voltmetr aj.
Mikrokontrolér, mikrořadič, či mikropočítač jsou synonyma pro jednočipový počítač, který má vyjma CPU přítomny také paměti a ostatní periferie nutné k chodu programu, kterému říkáme firmware. Firmware píšeme ve vývojovém prostředí, pomocí kterého ho zkompilujeme a hardwarovým přípravkem, kterému říkáme „programátor“, program nahrajeme do programové paměti mikrokontroléru přes nějaké rozhraní. K tvorbě firmware potřebujeme znát programovací jazyk, který si můžeme vybrat, nicméně u mikrokontrolérů se v současné době nejvíce používá jazyk C. V náročnějších aplikacích se stále využívá jazyk Assembler, který je složitější a pro první kroky s mikrokontroléry nemusí být nejšťastnější volbou.
Programátor si můžeme vyrobit sami nebo jej zakoupit již hotový, jehož cena se pohybuje ve stovkách až jednotkách tisíc českých korun. Pro naše potřeby nám vystačí některý z levnějších programátorů, jako například mnou používaný BiProg, AVRProg, USBasp aj. Důrazně doporučuji „ISP“ programátor, což znamená „In System Programming“, tedy schopnost připojit programátor přímo do hardwarové aplikace, ve které se mikrokontrolér nachází. Mé doporučení vznáším jednak z důvodu jednoduchosti použití, snadné přenositelnosti (nemusíme mít počítač s LPT portem jako tomu bylo třeba u tzv. „HVPP“- „High Voltage Parralel Programming“), jelikož většina dnešních programátorů se k počítači připojuje prostřednictvím rozhraní USB (pouze starší ISP programátory využívaly RS-232, na které není problém sehnat převodník z USB) tak i z důvodu, že se v současné době od HVPP ustupuje. Tento seriál bude popisován za použití USB ISP AVR programátoru BiProg a HVPP programováním mikrokontrolérů se nebudu nijak zabývat. Většina programátorů funguje jako převodník USB/UART, tj. se v systému hlásí jako sériový port („COMx“). Rozhraní používané přímo k připojení do mikrokontroléru je „SPI“- „Serial Peripheral Interface“, které se rovněž hojně využívá ze strany nejrůznějších periferních obvodů připojovaných k mikrokontrolérům, jako jsou paměti, digitální potenciometry, čidla apod. Rozhraní SPI je synchronní, tzn, že nechybí vodič pro přenos informace o čase- tzv. „taktování“, který se označuje „SCK“- „Serial clock“. Následují dva vodiče pro přenos dat. „MOSI“- „Master Out Slave In“ a „MISO“- „Master In Slave Out“, které, jak již text napovídá, slouží k obousměrnému transferu dat mezi obvodem „MASTER“, který generuje taktovací signál sběrnice SPI, a „SLAVE“. Nesmím zapomenout na vodič „!SS“, který na programátorech zpravidla nenaleznete, nicméně při zmiňovaném připojování periferních obvodů se využívá k volbě jednoho z více zařízení SLAVE, se kterým bude zařízení „MASTER“ komunikovat. Zařízení zvolíme logickou 0 na jeho vstupu „!SS“ (aktivní v log.0). Další vodiče již s SPI přímo nesouvisejí; jedná se o „!RESET“, který je také aktivní v logické 0 a jak již název napovídá, slouží k nastavení počátečních podmínek mikrokontroléru. Zbylé dva vodiče jsou napájení (+) a (-) 5V. Toto napětí nesmíme překročit o více jak 10% a při taktovacím kmitočtu mikrokontroléru do 8MHz toto napětí můžeme za účelem snížení spotřeby snížit až na 2,7V (v případě použití ATmega8L), či spíše na typické napětí 3,3V.
Mikrokontroléry architektury AVR se vyznačují harvardskou architekturou, tedy oddělenou pamětí pro data a program a RISC jádrem se schopností zpracovat jednu instrukci v jednom strojovém cyklu, což znamená, že výpočetní výkon udávaný v počtu instrukcí za sekundu, je totožný, jako taktovací kmitočet mikrokontroléru. V našem seriálu budeme využívat mikrokontrolér ATmega8 s taktovacím kmitočtem 8MHz získávaného z interního oscilátoru. Další možnosti, jak taktovací kmitočet získat, je externí RC článek (Rezistor a kondenzátor v sérii), krystal, keramický rezonátor, či externí zdroj. Mezi těmito zdroji lze vybírat pomocí tzv. „fuses“, které popíši později.
V mikrokontroléru je obsažena ALU- aritmeticko-logická jednotka, která vykonává samotné aritmetické operace, programová paměť FLASH, odkud se spouští firmware, paměť RAM pro data, která se smažou po resetu a interní EEPROM paměť pro uchovávání dat, která mají být zachována i po resetu.
Na rozdíl od osobních počítačů, kde je nutno nabootovat operační systém do paměti RAM, je v mikrokontrolérech AVR program spouštěn z FLASH paměti v něm zabudované; rovněž není možné spouštět program z jiné paměti, než interní FLASH. Bootování je možné, ale pouze s použitím tzv. „Bootloaderu“, kde se přepisuje pouze daná část programové paměti, což je samo o sobě téma pro začátečníka ne zcela vhodné, nicméně o této možnosti by i začátečník měl vědět. Další skupinou částí, o které se zmíním, jsou tzv. „periferie“. Periferie mikrokontroléru jsou připojeny na sběrnici a mají rozličné funkce. Jedná se většinou o řadiče rozhraní (RS-232, I2C, SPI,…), A/D převodníky, čítače/časovače a vstupně-výstupní (I/O) piny. I/O piny nejsou nic jíného, než většina vývodů mikrokontroléru, které můžeme použít jako vstupy či výstupy dat. Jedná se samo sebou pouze o dvoustavové informace (0/1; zapnuto/vypnuto; true/false).
K I/O pinům se přistupuje pomocí, většinou osmibitových, registrů. V závislosti na jejich konfiguraci lze například nastavit, zda bude daný pin vstup, či výstup, zda bude zapnut, či vypnut, nebo číst, zda je na vstup přivedena logická 1 či 0. Čte se vždy hodnota celého portu, který je v případě AVR mikrokontrolérů složen z maximálně osmi bitů. Pokud bychom se setkali s mikrokontrolérem, který je složen z portů, které se neskládají ze všech osmi I/O pinů, pak na hodnotě v registrech, která náleží zmiňovaným pinům, nezáleží. Postup nastavování, který I/O pin bude vstup a který výstup je následující:
DDRA=0b00001111;
Výše uvedeným postupem jsme nastavili I/O piny portu A (porty značíme písmeny) číslo 7,6,5,4 jako vstupy a piny 3,2,1,0 jako výstupy. Logická 0 tedy znamená v případě registru DDRA, DDRB, DDRC,... nastavení I/O jako vstup a logická 1 výstup. Za znakem „rovná se“ si povšimněte prefixu „0b“, který označuje, že se jedná o binární soustavu čísla uvedeného za ní. V tomto případě je binární soustava výhodná, jelikož nejlépe vidíme, který pin jsme jak nastavili; piny číslujeme zprava, tedy nejnižší číslice je nastavení pinu PA0 a nejvyšší číslice z osmi je nastavení pinu PA7. Předpokládám, že čtenáři znají základní číselné soustavy a jejich vzájemné převody, kterými se nebudu blíže zabývat. Uvedu pouze způsoby vyjádření číselných soustav:
Uvedené příklady všechny zastávají stejnou funkci, akorát s využitím jiné číselné soustavy.
U I/O pinů nastavujeme logickou hodnotu obdobným způsobem, jako nastavování vstupů či výstupů, akorát s použitím jiného registru. Příklad je níže:
PORTA=0b11100010;V případě, že nastavíme pin jako vstup a nastavíme jej na hodnotu logické 1, jedná se o aktivaci tzv. „pull-up rezistorů“, ke kterým se vrátíme v příštích dílech.
S registry se setkáme ještě mnohokrát, protože zastávají funkci pamětí pro nastavení parametrů periferií. Hodnota zapsaná v registrech se po každém resetu nastaví do výchozího stavu.
Vývojové prostředí Atmel Studio 7 je rozsáhlý nástroj založený na známém vývojovém prostředí Visual Studio. Pro začátek si vysvětlíme pouze základní operace v tomto prostředí, jelikož ze začátku jich příliš mnoho potřebovat nebudeme. Vývojové prostředí si stáhněte ze stránek zde a nainstalujte jej do svého počítače. Instalace je jednoduchá, stačí pouze odsouhlasit licenční ujednání a pokračovat stiskem tlačítek „další“. Pokud byla instalace úspěšná, vývojové prostředí si spusťte. Po spuštění se vám zobrazí úvodní obrazovka, kterou můžeme ignorovat a přejdeme rovnou k vytvoření nového projektu:
Komentáře nejsou kompilátorem brány na zřetel, slouží pouze pro lepší orientaci programátora ve zdrojovém kódu. Komentáře na více řádků značíme na začátku „/*“ a na konci „*/“; pro jednořádkové komentáře používáme nepírový tag „//“ na začátku řádku. Na obrázku jsou komentáře zvýrazněny zeleně.
#include je jeden z tzv. „paradigmat“ preprocesoru, kde zmíněný příklad vkládá do kódu knihovny, což je zvláště pro začínající programátory velmi užitečný pomocník. Například místo obsluhy LCD displeje pomocí vlastnoručně napsané rutiny můžete využít knihovny nějakého jiného programátora a s LCD pracovat již stylem „Vypiš na první řádek, druhou pozici text ‚AHOJ‘“. Samozřejmě i vy můžete vlastní knihovny zakládat bez jakýchkoliv omezení.
Hlavní funkce je část programu, která proběhne pouze jednou; nachází se v ní posloupnost příkazů a větvení programu, mezi které patří také Hlavní smyčka, která se opakuje až do odpojení napájení či resetu.
Zamyslete se nejdříve nad tím, jak vypadá blikání LED diody v čase, kde budeme uvažovat dobu svitu a dobu nečinnosti. Led dioda je nejdříve zhasnutá, posléze je na určitou dobu rozsvícena a následně znovu na určitou dobu pohasne; to vše se děje stále dokola. K řízení LED diody využijeme jednoho I/O pinu, který můžeme zvolit téměř libovolně s pomocí datasheetu, který si také můžete stáhnout zde. Zapojení jednotlivých pinů zjistíte v datasheetu z obrázku, který je níže. Budeme tedy mít nekonečnou smyčku programu složenou z těchto základních bodů:
Před „vstupem“ programu do hlavní smyčky je ještě nutno nastavit požadovaný pin jako výstup, v našem případě zvolíme třeba pin PB0.
Abychom měli kam zkompilovaný firmware nahrát, tak si na nepájivém kontaktním poli mikrokontrolér napojíme k programátoru- viz foto. Při zapojování se řiďte obrázkem v datasheetu.
Nyní připojíme LED diodu a rezistor dle následujícího schématu:
Rezistor R1 slouží k omezení proudu procházejícího LED diodou a jeho odpor (rezistence) se počítá se dle následujícího vzorce kombinujícího II. Kirchhoffův zákon s ohmovým zákonem:
R=(U_cc-U_LED)/I_LED [Ohm;V;V;A]Kde Ucc je napájecí napětí (v našem případě 5V), ULED je úbytek napětí v propustném směru, což je parametr závislý na konkrétní barvě LED diody, který se pohybuje v rozmezí 2,6-3,5V. Lze jej zjistit na internetu nebo v katalogovém listu dle barvy vyzařovaného spektra. Proud LED diodou se označuje ILED a jeho překročení vede k destrukci zmiňované diody. Pro experimentální použití v našem případě mohu doporučit proud 10mA (0,01A), který vyhoví naprosté většině použitelných LED diod.
Polaritu LED diody poznáme při pohledu do pouzdra, kde anodou je menší ze dvou elektrod. Anoda je na schématu připojena přes rezistor k PB0.
http://www.atmel.com/images/atmel-2486-8-bit-avr-microcontroller-atmega8_l_datasheet.pdf