Zpět na seznam článků     Číst komentáře (6)     Verze pro tisk

Programování mikrokontrolérů architektury AVR (1)

Autor: Prog0el   
17.11.2015

V tomto úvodním díle se seznámíme s vývojovým prostředím Atmel Studio 7 a vysvětlíme si funkci mikrokontroléru Atmel ATmega8 na našem prvním programu, který bude blikat LED diodou, což je obdoba programu „Hello world“. Pro začátek je nutné pochopit jednodušší programy, abyste byli schopni pochopit složitější systémy.


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.

Co budeme potřebovat

  • Mikrokontrolér ATmega8 (v pouzdře DIP pro usnadnění vývoje): cca 100,-Kč
  • LED diodu- libovolnou :jednotky Kč
  • Rezistor- viz text :jednotky Kč
  • Programátor: stovky Kč
  • Nepájivé kontaktní pole: cca 100,-Kč
  • Počítač s vývojovým prostředím
  • Touhu naučit se něco nového

Základní terminologie

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

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.

Architektura AVR

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:

  • Desítková: bez prefixu (DDRD=255;)
  • Binární: prefix „0b“ (DDRD=0b11111111;)
  • Hexadecimální: prefix „0x“ (DDRD=0xFF;)
  • Oktalová: prefix „0“ (DDRD=0377;)

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.

Seznámení s vývojovým prostředím

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:

  • File>New>Project
  • Zvolte „GCC C Executable project“ a v poli dole vyplňte název projektu, který je libovolný (jedná se o název adresáře a souborů projektu).
  • Stiskněte „OK“
  • V okně pro výběr mikrokontroléru vyberte možnost „ATmega8“
  • Stiskněte „OK“
  • Otevře se vám nový projekt s vygenerovanou hlavní funkcí, ve které se nachází hlavní smyčka programu.

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.

Praktický příklad

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ů:

  • Vypni LED
  • Vyčkej
  • Zapni LED
  • Vyčkej

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.

  • Před tím, než budete pokračovat ke kompilaci vašeho prvního programu bude nutno nastavit, který programátor používáte. Připojte, tedy programátor do počítače a případně jej dle pokynů výrobce nainstalujte.
  • Přejděte na Tools>Add target a stiskněte „Apply“
  • Stiskněte Alt+F7 a v okně, které se zobrazí, zvolte v kolonce „Select debugger/programmer“ jinou možnost, než „simulator“. V mém případě „STK500“, což je komunikační protokol pro programování mikrokontrolérů- v závislosti na použitém mikrokontroléru se může lišit. Posléze nastavte interface na „ISP“.
  • Kartu uzavřete (zbude karta „main.c“)
  • Pokud je cíl v projektu nastaven, není nutno jej měnit před každou kompilací.

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.

  • Nyní připojte programátor k počítači a přejdeme do Tools>Device programming
  • Nastavte horní kolonky dle obrázku:
  • Stiskněte „Apply“
  • Pokud jste postupovali správně a vše funguje tak, jak by mělo, zobrazí se vám následující okno:
  • Přejděte do „Fuses“
  • Nastavte kolonku „SUT_CKSEL“ dle obrázku, čímž nastavíme taktovací kmitočet mikrokontroléru na 8MHz se zdrojem z interního RC oscilátoru. Buďte opatrní, jelikož při chybném nastavení by již mikrokontrolér nemusel být použitelný.
  • Stiskněte „Program“
  • Po ukončení programování stiskněte „Close“
  • Při posledním kroku stiskněte F5, čímž spustíte kompilaci firmware, který se následně nahraje do mikrokontroléru.
  • Nyní se LED dioda rozbliká
  • Můžete zkusit experimentovat s nastavením zpoždění a zkusit například stroboskopický efekt.

Reference

http://www.atmel.com/images/atmel-2486-8-bit-avr-microcontroller-atmega8_l_datasheet.pdf


Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 2.6/15

1  2  3  4  5    
(známkování jako ve škole)