EVMS-mega128 v1.0 Výuková deska s mikrokontrolerem ATmega128 Výukové příklady Verze dokumentu 1.0 (09.04.2008)
Obsah 1 Úvod... 3 2 Popis struktury příkladu... 4 3 Příklady...6 4 Historie verzí dokumentace...8 Verze dokumentu 1.0 (09.04.2008)
1 Úvod Tento dokument předkládá několik jednoduchých příkladů jak používat periferie umístěné na výukové desce EVMS-mega128. Bližší popis periferií je možné nalézt v Uživatelském manuálu desky. Uvedené příklady zdrojových kódů je možné přeložit ve volně dostupném vývojovém prostředí Atmel AVR-Studio. Přeložené HEX-soubory je možné do mikrokontroleru zapsat buď programovacím kabelem ISP či JTAG a nebo přes USB rozhraní pomocí bootloaderu. Detaily o programování jsou opět dostupné v Uživatelském manuálu. Verze dokumentu 1.0 (09.04.2008) 3 / 9
2 Popis struktury příkladu Tato kapitola popisuje strukturu programu, od které jsou veškeré příklady v tomto dokumentu odvozeny. Jsou zde zobrazeny příklady jednotlivých částí struktury včetně popisu jejich významu. Hlavička Tato část programového souboru obsahuje pouze informativní údaje a nemá vliv na funkci programu. Měla by obsahovat: název programu, verzi programu, datum poslední úpravy (u složitějších programů i historii změn), cílový hardware, pro který je program určen a jeho případné nastavení či připojení (jumpery / konektory), jméno autora a krátký popis programu. ;*************************************************************************************************************** ; Program : Rotating light on LEDs test 0 ; Version : v1.0 ; Hardware : EMVS-mega128 v1.0 ; Xtall : 14.7456MHz ; Written by : Ing. Ivan Mikšánek jr. ;*************************************************************************************************************** ;*************************************************************************************************************** ; EMVS-mega128 v1.0 board configuration: ; -------------------------------------- ; ; Jumpers: ; Power : Depends on power supply used (REG or USB) ; VREF : Don't care (for example 2.5V) ; LEE : Don't care ; UART1 : Don't care ; ; Connectors: ; LCD display : Don't care ; Ext. memory : Don't care ; ADC : Don't care ; SPI : Don't care ; I2C : Don't care ; Misc : Don't care ; ;*************************************************************************************************************** Sekce vkládaných souborů (include) Zde jsou uvedeny pomocné soubory, které budou zpracovávány kompilátorem společně s programovým kódem. Pro každý typ mikrokontroleru výrobce vytvořil speciální soubor, který definuje jména všech vnitřních registrů, jména jejich bitů atd. přesně podle katalogového listu (datasheet-u). Programátor tedy může po použití tohoto souboru pracovat s jednotlivými částmi mikrokontroleru pomocí přiřazených jmen (místo toho, aby uváděl adresy registrů) což mu velmi zpřehledňuje a usnadňuje práci. Příkazy.NOLIST a.list udávají, že kód napsaný mezi nimi se nemá zapisovat do listingového souboru (textový soubor vzniklý při kompilaci). Příkaz.INCLUDE udává jméno souboru, který se má vložit. Uvedený soubor m128def.inc tedy definuje názvy registrů pro obvod ATmega128. ;================================================== Includes ===================================================.NOLIST.include "m128def.inc".list Sekce konstant Definuje jména identifikátorů, které bude možno v programu použít místo číselných konstant, což zpřehledňuje kód a umožňuje hromadnou změnu hodnot v rámci celého kódu pouze změnou definice hodnoty konstanty v této sekci. Kompilátor během překladu nahradí v programu všechny identifikátory daného jména příslušnými hodnotami konstant. ;====================================== Constants =============================================================.EQU BaudConst = 7 ; Baudova rychlost.equ BuffLen = 8 ; Velikost bufferu Verze dokumentu 1.0 (09.04.2008) 4 / 9
Sekce definující pojmenování registrů Definuje uživatelská jména registrů, což opět zpřehledňuje programový kód. ;============================================ Register definitions =============================================.def ZeroReg = r1.def FFReg = r2.def PDelReg = r16 Sekce paměti SRAM Definuje datové segmenty (úseky), tj. vyhrazuje části SRAM paměti pro jednotlivé proměnné (n-bytové). ;================================================ DATA segment =================================================.DSEG Var1.BYTE 1 ; 1-bytova promenna na adrese Var1 Buffer.BYTE 8 ; 8-bytova promenna na adrese Buffer Sekce paměti EEPROM Definuje obsah paměti EEPROM. Programátor si zde může vytvořit N-prvková pole konstant, které může v programu nejen číst, ale i měnit jejich hodnoty. Zápis do EEPROM paměti je však mnohem časově náročnější, než do RAM paměti a je také omezen maximálním počtem zápisů. Výhodou však je, že data uložená v této paměti zůstanou zachována i po odpojení mikrokontroleru od napájecího napětí. ;=============================================== EEPROM segment ================================================.ESEG ConstArr:.DB 0x00, 0x01 ; definuje tabulku konstant 0x00 a 0x01 na adrese ConstArr Sekce maker Zde jsou definována makra, která je možné v programu použít. ;=================================================== MACROs ====================================================.MACRO INC_Z16 add ZL, @0 adc ZH, @1.ENDM Programová sekce Definuje obsah programové (FLASH) paměti. Tato sekce tedy obsahuje samotný programový kód, kód rutin obsluhující jednotlivá přerušení a tabulky konstant. ;=============================================== PROGRAM segment ===============================================.CSEG.org 0x0000 ; urceni adresy, na ktere bude nasledujici instrukce v prog. pameti ldi TmpReg, 0 ; instrukce CharTab:.db 0x10, 0x02 ; definuje tabulku konstant 10h a 02h v prog. pameti Verze dokumentu 1.0 (09.04.2008) 5 / 9
3 Příklady Ve všech zde uvedených příkladech je začátek programu stejný. V sekci konstant se definují konstanty (pojmenování) pro vstupně/výstupní porty a jejich bity (přesně podle hardware výukové desky). ;================================================== Constants ================================================== // LEDs.equ LEDS_PORT = PORTD.equ LEDS_DDR = DDRD.equ LED0_BIT = 4.equ LED1_BIT = 5.equ LED2_BIT = 6... Programový kód (.CSEG) začíná výpisem všech přerušení, které použitý MCU umožňuje. Nevyužitá přerušení odskakují na instrukci reti, aby v případě, že nastanou bez vědomí programátora (chybně napsaným kódem), byla řádně obsloužena. ;********************************************** Interrupt vectors **********************************************.ORG 0x0000 jmp RESET ; Reset jmp EXT_INT0 ; External Interrupt-0 jmp EXT_INT1 ; External Interrupt-1... ;****************************************** Unused interrupt vectors ******************************************* EXT_INT0: EXT_INT1:... SPM_RDY: reti Za výpisem přerušení následuje podprogram Reset, který je vykonáván ihned po resetu MCU a nebo po připojení napájecího napětí. V jeho kódu se nastavují výchozí hodnoty registrů (např. ZeroReg = 0x00 a FFReg = 0xFF), inicializuje se stack pointer (SPH a SPL na hodnotu RAMEND = konec SRAM paměti), volá se podprogram SetupPorts a na závěr se skáče do části Main, kde je uveden hlavní kód programu. ;**************************************************** Reset **************************************************** Reset: clr ZeroReg ser TmpReg mov FFReg, TmpReg ldi out ldi out rcall jmp TmpReg, high(ramend) ; Initialize stack pointer to highest address in internal SRAM SPH, TmpReg TmpReg, low(ramend) SPL, TmpReg SetupPorts Main Podprogram SetupPorts nastavuje vstupně/výstupní porty mikrokontroleru na výchozí hodnoty tak, aby periferie připojené k mikrokontroleru výukové desky mohly být správně používány. Např. IO porty MCU, na které jsou připojeny LED diody jsou inicializovány jako výstupní (LEDS_DDR je maskován logickými 1-mi na patřičných bitech) atd. ;************************************************* Setup ports ************************************************* SetupPorts: // LEDs in TmpReg, LEDS_PORT ori TmpReg, LEDS_MASK out LEDS_PORT, TmpReg in ori out TmpReg, LEDS_DDR TmpReg, LEDS_MASK LEDS_DDR, TmpReg // Beeper cbi BPR_PORT, BPR_BIT sbi BPR_DDR, BPR_BIT... Před hlavní částí Main se často v příkladech nacházejí podprogramy, které plní pomocné funkce, např. nastavitelné časové zpoždění Delay1m apod. Hlavní část Main vykonává požadovaný algoritmus, např. řídí LED diody, čte stavy tlačítek, zapisuje na LCD display či posílá data na USB rozhraní. Verze dokumentu 1.0 (09.04.2008) 6 / 9
Příklad 1.0 - LEDs rotating light 0 Program cyklicky rotuje log. 0 tam a zpět na 4 bitech portu, kde jsou připojeny LED diody a tím generuje běžící světlo. Hlavní kód je založen na jednoduchém zhasínání s rozsvěcování LED diod instrukcemi sbi a cbi. Po každé změně stavu je volán podprogram Delay1m, který provádí časové zpoždění dané hodnotou registru PDelReg v [ms]. Příklad 1.1 - LEDs rotating light 1 Program má shodné chování s předešlým příkladem, pouze programový kód se mírně odlišuje - v hlavní části se místo přímého zápisu na port s LED diodami využívá volání podprogramu SetLeds. Jde tedy pouze o programátorsky čistší řešení stejné úlohy. Příklad 2.0 - Buttons 0 Program cyklicky čte stav 8 tlačítek a pokud je nějaké z nich stlačeno, je jeho číslo zobrazeno binárně na 4 LED diodách. Např. pokud je stlačeno tlačítko č. 3, LED diody 4 a 3 nesvítí, LED diody 2 a 1 svítí. Hlavní část programu využívá podprogramů GetButton a SetLeds. Příklad 3.0 - Beeper 0 Program cyklicky generuje zvuk (pípnutí) o frekvenci 1kHz (dané registrem CallReg0 ) a délce 0.5s (dané registry CallReg2 a CallReg1 ). Samotné generování obdélníkového signálu se provádí podprogramem Beep_soft (softwarové generování bez využití přerušení). Po dokončení pípnutí se 2x po sobě volá funkce Delay1ms pro provedení časového zpoždění 0.5s (PDelReg = 250). Příklad 3.1 - Beeper 1 Program má velmi podobné chování s předešlým příkladem, pouze programový kód se mírně odlišuje - generování obdélníkového signálu se neprovádí podprogramem, který by soustavně zabíral strojový čas mikrokontroleru, ale v přerušení od čítače/časovače TIM0_COM. Volání podprogramu BeepByIRQ pouze nastavuje registry a čítač/časovač. Během generování zvuku může mikrokontroler provádět jiné operace. Toto chování je možné jednoduše ověřit tím, že se v hlavní části programu Main povolí řádek s voláním podprogramu rcall WaitBeepEnd a tím se bude po započetí generování zvuku pasivně čekat po jeho dokončení - časová mezera mezi jednotlivými pípnutími se zvětší. Příklad 4.0 - LED display 0 Program pomocí přerušení od čítače/časovače zobrazuje na LED displeji 4 registry: Disp1 až Disp4. V hlavní části se pouze nastaví tyto registry a jsou pak dále automaticky vypisovány. Příklad 5.0 - LCD display 0 Program na LCD displeji vypíše řetězec Hello world. Vypisování se provádí v hlavní části tak, že se do registru LCDreg zapíše ASCII znak a pak se zavolá podprogram LCD_put_char, který tento znak vypíše na LCD. Program obsahuje veškeré podprogramy nutné pro obsluhu LCD displeje, včetně jeho inicializace. Příklad 5.1 - LCD display 1 Program cyklicky čte stav tlačítek a pokud je některé stisknuto, zobrazí se jeho číslo na LCD displeji. Načítání stavu tlačítek se provádí 3x po sobě a získané hodnoty se porovnávají, aby se odstranily problémy se zákmity a na LCD se nezobrazovaly nesprávné hodnoty. K hodně získané podprogramem GetButton je nutné přičíst znak '0', aby se hodnota tlačítka převedla na ASCII znak. Příklad 6.0 - UARTs 0 Program čeká na příjem bytu z RS-232 či USB rozhraní. Po jeho přijetí zobrazí spodní 4 bity na LED diodách a zašle zpět do PC na obě rozhraní negovanou hodnotu přijatého bytu. Příjem bytu se provádí pomocí přerušení od obou UART bloků. Verze dokumentu 1.0 (09.04.2008) 7 / 9
4 Historie verzí dokumentace Verze dokumentu / datum v1.0 / 09.04.2008 Vytvoření výchozí verze dokumentace Změny Verze dokumentu 1.0 (09.04.2008) 8 / 9
EVMS-mega128 v1.0 Výuková deska s mikrokontrolerem ATmega128 Výukové příklady (verze dokumentace v1.0) PK Design http://www.pk-design.net pkdesign@seznam.cz 09.04.2008 Verze dokumentu 1.0 (09.04.2008) 9 / 9