UNIVERZITA TOMÁŠE BATI VE ZLÍNĚ FAKULTA APLIKOVANÉ INFORMATIKY
PROGRAMOVÁNÍ MIKROPOČÍTAČŮ CVIČENÍ 11 Programování mikropočítačů v jazyce C Jan Dolinay Petr Dostálek Zlín 2013
Tento studijní materiál vznikl za finanční podpory Evropského sociálního fondu (ESF) a rozpočtu České republiky v rámci řešení projektu: CZ.1.07/2.2.00/15.0463, MODERNIZACE VÝUKOVÝCH
MATERIÁLŮ A DIDAKTICKÝCH METOD
Cvičení 11 – Programování mikropočítačů v jazyce C
Cvičení 11 – Programování mikropočítačů v jazyce C
STRUČNÝ OBSAH CVIČENÍ:
První program v jazyce C v prostředí CodeWarrior – aritmetické operace Příklad na podmínky a cyklus Příklad s využitím vlastní funkce Úkoly k procvičení
VSTUPNÍ ZNALOSTI: Toto cvičení předpokládá znalosti základů programování v jazyce C.
CÍL:
Na tomto cvičení se seznámíme s využitím jazyka C pro programování mikropočítačů. Jazyk C je nejrozšířenějším programovacím jazykem pro tvorbu aplikací pro mikropočítače, a proto je jeho znalost jedním z hlavních předpokladů úspěšného uplatnění v praxi.
Cvičení se vztahuje k těmto otázkám
Základní pojmy mikroprocesorové techniky, mikropočítač, mikroprocesor, sběrnice, periferní zařízení, registry,…
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
2
Cvičení 11 – Programování mikropočítačů v jazyce C
Řešené příklady Nyní si ukážeme jak vytvořit program v jazyce C v prostředí CodeWarrior. CodeWarrior umožňuje jak programování v assembleru (což jsme používali dosud), tak i jazyce C. Výhodou je, že i při použití jazyka C budeme stále pracovat ve známém vývojovém prostředí V ukázkových programech vyřešíme stejná zadání jako v našich prvních programech v assembleru.
Příklad 1 – Základní aritmetické operace v jazyku C
Úkol 1 Proveďte vyhodnocení výrazu ((c1+c2) – (c3+c4))*c5. Řešení: Zatímco v assembleru zabralo vytvoření takovéhoto programu mnoho řádků kódu, v jazyce C prakticky jen přepíšeme zadaný výraz a překladač sám zajistí jeho převod do „řeči“ procesoru“, tj. jeho rozložení na instrukce procesoru. Nejprve samozřejmě definujeme proměnné, do kterých budou uložena zpracovávaná čísla a výsledek. Použijeme datový typ int jazyka C tj. celé číslo se znaménkem. Definice proměnných v jazyku C bude vypadat následovně: int c1, c2, c3, c4, c5, vysledek; Samotný kód programu, který vyhodnocuje zadaný výraz je velmi jednoduchý: vysledek = ((c1+c2) – (c3+c4))*c5;
Překlad programu Spusťte CodeWarrior a vytvořte nový projekt. V prvním okně průvodce novým projektem zaškrtněte políčko C a odškrtněte políčka ASM a C++, viz obr. 1. Tím zvolíte jako programovací jazyk pro tento projekt jazyk C.
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
3
Cvičení 11 – Programování mikropočítačů v jazyce C
Obr. 1 ‐ Vytváření nového projektu v jazyku C v prostředí CodeWarrior
Další kroky jsou už stejné jako při vytváření projektu v assembleru. Tedy, vyberte typ mikropočítače (GB60) a jako připojení (connection) – zvolte simulátor. Po dokončení průvodce se opět vygeneruje kostra programu, viz. Obr. 2. Podívejme se na
vygenerovaný kód. Obr. 2 ‐ Kostra programu v C vygenerovaná CodeWarriorem
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
4
Cvičení 11 – Programování mikropočítačů v jazyce C
Základní struktura programu na obrázku 2 by vám měla být známá. Je totiž stejná jako u programu v C pro osobní počítač. Kód začíná direktivami #include, která vkládají do našeho zdrojového kódu definice základních portů a registrů zvoleného mikropočítače. Deklarace funkce void MCU_init(void) pro nás není důležitá, protože ji nebudeme využívat. Důležitá je ovšem funkce main, která, jak víme, představuje základní výkonnou jednotku programu v jazyku C. Program začíná vstupem do této funkce a opuštěním této funkce celý program končí. Vidíme, že průvodce už do funkce main vložil makro EnableInterupts, které povoluje přerušení. Toto makro je ekvivalentní provedení instrukce SEI v assembleru. Na konec funkce main pak průvodce vložil cyklus for, který v nekonečné smyčce provádí resetování watchdogu pomocí makra __RESET_WATCHDOG();. Takto vytvořený program by tedy nic užitečného nedělal. Po spuštění by pouze v nekonečné smyčce resetoval obvod watchdog. Definice proměnných zapíšeme na začátek programu, ještě před funkci main. Náš kód pak zapíšeme dovnitř funkce main, za makro EnableInterups, ale před cyklus for. Nyní tedy dopište do kostry programu vlastní kód dle obrázku 3.
Obr. 3 ‐ Zdrojový kód programu pro úkol 1
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
5
Cvičení 11 – Programování mikropočítačů v jazyce C
Námi vytvořený kód se skládá ze dvou bloků, které bychom mohli označit jako definici proměnných a samotný kód programu. Oproti zadání je v kódu navíc ukázáno i dělení celých čísel a získání zbytku po celočíselném dělení. Hned za direktivy #include na začátku programu jsme dopsali definici potřebných proměnných, tj. c1 až c5, vysledek a zbytek. Protože proměnné nejsou definovány uvnitř žádné funkce, budou globální, stejně jako bychom je v assembleru vytvořili direktivou RMB nebo DS.B. Náš kód je vložen do těla funkce main, za komentář „insert your code here“ (sem vložte svůj kód). Nejprve do proměnných c1 až c5 vkládáme nějaké konkrétní hodnoty, abychom mohli otestovat funkčnost programu. Se zadanými čísly by výsledek měl vyjít 14. Samotný kód vyhodnocení výrazu zabírá pouhý jeden řádek a jedná se vlastně jen o přepis zadání do jazyka C, což je velmi podobné jako běžný matematický zápis. Na dalším řádku pak vidíme, že dělení se v C zapíše pomocí „lomítka“ a zbytek po celočíselném dělení získáme pomocí operátoru modulo (%). S čísly dle obrázku dělíme 5/2 a tedy výsledek bude 2 a zbytek 1.
Testování programu Program přeložíme stejným způsobem jako dříve u programů v assembleru, tedy např. tlačítkem Build na panelu nástrojů. Po překladu a odstranění případných chyb program spusťte v debuggeru. Krokujte program a všimněte si následujícího: o Po prvním kroku, před vykonáním přiřazení c1 = 5; je ve všech proměnných nula, viz okno Data. Toto je výchozí hodnota pro globální proměnné, kterou jim nastavil překladač. o Po přiřazení do proměnných c1 až c5 by v nich měla být zadaná čísla. o Po vykonání řádku vysledek = … bude v proměnné vysledek číslo 14. o Po provedení dělení bude v proměnné vysledek hodnota 2 o Po provedení modula: zbytek = c1 % c2 bude v proměnné zbytek číslo 1, tedy zbytek po celočíselném dělení 5 / 2. o Program se pak neustále „točí“ v cyklu for. Můžete si také prohlédnout kód našeho programu v assembleru, tak jak jej přeložil překladač jazyka C – a to v okně Assembly vpravo nahoře. Např. příkaz c1 = 5; je přeložen jako: LDX #5 MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
6
Cvičení 11 – Programování mikropočítačů v jazyce C
CLRH STHX 0x0100 Se znalostmi assembleru získanými dříve z toho dokážeme odvodit, že překladač C rezervuje pro proměnnou typu int dva bajty paměti a přiřazení provádí přes registry H:X. Proto nahrává číslo 5 do registru X a registr H nuluje. Oba registry pak ukládá do paměti na adresu 100 hexadecimálně. Na této adrese se tedy bude nacházet proměnná c1. V dalším příkladu se podíváme na zápis podmínek a cyklů v C.
Úkol 2 – podmínky, cykly a pole Porovnejte čísla c1 a c2 a větší z nich uložte do proměnné vysledek. Dále definujte pole M o pěti prvcích a toto pole vynulujte.
Řešení Podívejme se na výpis programu na obrázku 4. Proměnné c1 a c2 tentokrát definujeme uvnitř funkce main a zároveň jim přiřazujeme hodnoty 5 a 3. Dále definujeme proměnné vetsi, i a M. M je přitom pole o pěti prvcích. První část kódu porovnává čísla c1 a c2 a pokud je c1 větší než c2, ukládá do proměnné vetsi c1 (c1 = vetsi;), v opačném případě (else) ukládá do proměnné vetsi c2. Zápis je vám jistě srozumitelný, jedná se o podmínku if (podmínka) vyraz else vyraz. Druhá část programu vyplní pole M nulami. K tomu potřebujeme cyklus. Jedním z cyklů v jazyce C je for, který je použit v naší ukázce. Zápis cyklu for je obecně: for ( inicializační příkaz; podmínka trvání cyklu; příkaz prováděný na konci cyklu ) { tělo cyklu } V našem příkladě se nejprve inicializuje proměnná i (počitadlo cyklu) na nulu. Podmínka běhu cyklu je i < 5, takže cyklus se zopakuje právě 5-krát (pro i =0, 1, 2, 3 a 4). Uvnitř složených závorek (v těle cyklu) se provádí příkaz M[i] = 0; Ten do i-tého prvku pole M přiřazuje nulu.
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
7
Cvičení 11 – Programování mikropočítačů v jazyce C
Obr. 4 ‐ Zdrojový kód programu dle zadání 2
Překlad a ladění programu Vytvořte nový projekt stejným způsobem jako u předchozího úkolu. Do kostry programu pak dopište zdrojový kód dle obr. 4. Po překladu a odstranění případných chyb program spusťte v simulátoru. S čísly podle ukázkového kódu bude splněna podmínka if (c1 je větší než c2) a proto se provede příkaz vetsi = c1 a větev else se přeskočí. Př krokování pole sledujte jak se jednotlivé prvky pole M plní nulami. Pokud pole již obsahuje nuly, upravte program tak, aby místo nuly přiřazoval jiné číslo, např. 3.
Úkol 3 – funkce Napište program, který spočítá, kolik z čísel c1 a c2 je sudých a výsledek uloží do proměnné nSude. Pro určení, zda je číslo sudé napište funkci, která jako vstupní parametr dostane číslo, které má otestovat a vrátí 1 jestliže je sudé a 0 jestliže není. Řešení Podobný příklad jsme již řešili v assembleru. Pro určení, zda je číslo sudé jsme použili dělení daného čísla dvěmi. Pak jestliže je zbytek roven nule, číslo je sudé. Zápis tohoto algoritmu v jazyku C bude mnohem jednodušší než v assembleru. Podívejte se na obr. 5 na výpis MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
8
Cvičení 11 – Programování mikropočítačů v jazyce C
zdrojového kódu. V zeleném rámečku v pravé části obrázku je kód funkce (podprogramu) pro určení zda je předané číslo sudé. Funkce se jmenuje JeSude. Levá část obrázku obsahuje kód „hlavního programu“, tedy funkce main. Šedě je zde uveden kód který vygeneroval průvodce novou aplikací.
Podívejme se nejprve na kód hlavního programu. Uvnitř funkce main jsou definovány proměnné c1, c2 a nSude. C1 a c2 jsou přímo inicializovány na určité hodnoty. nSude bude po skončení programu obsahovat počet sudých čísel v těchto dvou proměnných, což může být buď 0 nebo 1 nebo 2. S konkrétními čísly dle uvedeného kódu bude v proměnné nSude číslo 1, protože proměnná c2 obsahuje sudé číslo, kdežto c1 obsahuje číslo liché. Vlastní kód začíná přiřazením nuly do proměnné nSude. Mohli bychom to samozřejmě udělat už v definici proměnné jako je tomu u c1 a c2. Zde se jedná jen o ukázku různých možností pro dosažení stejného cíle. Dále je zapsána podmínka if. Výraz v závorce je poněkud složitější než u předchozího příkladu. Provádí se zde volání funkce JeSude s číslem c1 jako parametrem. Výsledek vrácený funkcí JeSude() je pak porovnán s číslem 1. Podle zadání má funkce JeSude vrátit 1 jestliže je předané číslo (její parametr) sudé. Je proto celkem logické, že jestliže číslo vrácené funkcí JeSude() bude rovno jedné a tudíž podmínka if bude splněna, zvětšíme hodnotu v proměnné nSude o 1 (nSude = nSude + 1). Jestliže funkce JeSude nevrátí jedničku, podmínka splněna nebude a inkrementace proměnné nSude se neprovede. Druhá podmínka if testuje sudost proměnné c2. Je ale zapsána úspornějším způsobem bez operátoru porovnání. Využívá toho, že v jazyce C se podmínka vyhodnotí jako nesplněná (nepravda), jestliže je výsledkem výrazu 0 a jako splněná, pokud je výsledek nenulový. Jestliže c2 bude sudé číslo, vrátí funkce JeSude jedničku, což bude vyhodnoceno jako splněná podmínka (nenulový výsledek) a provede se inkrementace proměnné nSude. Jestliže c2 nebude sudé a funkce JeSude tudíž vrátí nulu, bude to vyhodnoceno jako nesplněná podmínka. Inkrementace proměnné je u druhé podmínky také zapsána úsporným způsobem: nSude++, což je ekvivalentní zápisu nSude = nSude + 1;.
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
9
Cvičení 11 – Programování mikropočítačů v jazyce C
Obr. 5 ‐ Zdrojový kód programu na počítání sudých čísel
Kód funkce JeSude je uveden v zeleném rámečku na obr. 5. První řádek kódu: int JeSude(int cislo) říká, že funkce JeSude vrací celé číslo (int) a jako vstupní parametr má jedno celé číslo (int cislo). Podle zadání má funkce otestovat předaný parametr a v případě, že je to sudé číslo, vrátit hodnotu 1, jinak vrátit hodnotu 0. Uvnitř funkce je nejprve definována proměnná int zbytek. Na dalším řádku je do ní uložen zbytek po celočíselném dělení vstupního parametru cislo dvěmi. K tomu slouží operátor modulo (%), se kterým už jsme se setkali v prvním programu. Podmínka if ( zbytek == 0) je pak splněna, jestliže cislo bylo dělitelné 2 bez zbytku. Což znamená, že je sudé. Proto jestliže je podmínka splněna, funkce končí příkazem return 1, čímž vrací volajícímu hodnotu 1. (volajícím je zde funkce main). Pokud podmínka není splněna, provede se větev else, což znamená, že funkce JeSude skončí příkazem return 0, tedy vrátí volajícímu nulu.
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
10
Cvičení 11 – Programování mikropočítačů v jazyce C
Testování programu Vytvořte nový projekt v jazyku C, opět nastavený pro spuštění v simulátoru. Přepište kód z výpisu o vašeho programu. Kód funkce JeSude() napište za funkci main(), tj. za uzavírací závorku („}“) funkce main, viz šipka na obrázku. Po překladu a odstranění případných chyb spusťte program v simulátoru a zkuste jej odkrokovat. Vyzkoušejte příkaz Step into, který bude krokovat dovnitř funkce JeSude() i příkaz Step Over, který funkci JeSude provede v jediném kroku. Zkuste změnit hodnoty v proměnných c1 a c2 tak, aby výsledkem byla 0 sudých čísel a 2 sudá čísla. Změnu je možno provést přímo v simulátoru poklepáním na proměnnou v okně Data – stejně jako u programu v assembleru.
Příklady k procvičení
1. Vytvořte program, který vyhledá v poli pěti čísel minimální a maximální hodnotu a uloží je do proměnných min a max. Pole naplňte libovolnými hodnotami podle uvážení. 2. Vytvořte program, který bude pomocí funkce faktor počítat faktoriál z čísel uložených v poli z předchozího příkladu. Faktoriály uloží do nového pole f_pole. Vzhledem k omezenému rozsahu celočíselné proměnné int (2 bajty tj. max 65535) nepoužívejte pro výpočet faktoriálu čísla větší než 8.
Doplňující zdroje [1]
Freescale: Firemní dokumentace pro mikropočítače HCS08, dostupné online: http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=S08GB&nodeId= 01624684491437EDD5
MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD CZ.1.07/2.2.00/15.0463,
11