OBSAH
   Strojový kód, assembler
 Paměť
 Číselné soustavy
 Zápis zdrojového souboru - hlavička
 Pozvolna začneme s instrukcemi
 První program
 Překlad programu
Obsah této stránky je zde pro ty z Vás, kteří se sem vracejí, nebo již něco znají. Protože vše souvisí se vším, a nelze začít od prostředka, začátečníkům vřele doporučuji obsah přeskočit a začít kupodivu od první řádky. Pokud vydržíte číst do půlky stránky, programovat se nejspíš naučíte. Pokud ne, vzdejte to raději hned a věnujte se něčemu jinému.

     Takže to vezmu od začátku, kdy předpokládám, že o programování nevíte nic (jako já před lety), ale chcete se něco naučit. Předem upozorňuji, že je třeba se obrnit trpělivostí, ale myslím si, že alespoň začátky pochopí každý. Prosím nespěchejte, pro plné pochopení nestačí pár dní, a čím více toho naprogramujete, tím více pronikáte do detailů a zjišťujete nové a nové věci.
     Jednochip je prakticky (ostatně jako každý počítač) velice hloupé zařízení, které neumí nic jiného, než přehazovat hodnoty odněkud někam a popřípadě s nimi provést nějakou matematickou operaci. Celý program není nic jiného, než takový návod, co se kam má přehodit, co od čeho odečíst nebo třeba přičíst a to v pořadí, jak je to napsáno za sebou. Aby to nebylo tak jednoduché, může se v tomhle návodu (programu) přeskakovat a skákat a to podle něčeho. Pokud si říkáte, jak se pomocí tohohle (nějakého přičítání, odečítání, přesouvání, skoků a podobných "nesmyslů") dá například psát znaky na LCD displej, komunikovat s PC, měřit teplotu ap. pak vězte že ano, a po dočtení této stránky a pochopení Vám to bude jasné.
      Aby bylo pochopení, co to je program a programování snazší, převedu to analogicky do běžného života, dále jako kuchařková analogie. 
  Program je v podstatě nějaký soupis pokynů (u procesorů instrukcí), jejichž vykonáním dosáhneme žádaného výsledku. Jako jednoduchý příklad si vezměme třeba kuchařku (tím myslím knihu, ne dívčinu). Každý recept v kuchařce představuje ve své podstatě program, který říká jak postupovat, abychom uvařili nějaké jídlo.
  Procesor je "někdo" kdo onen program vykonává. Opět v analogii s kuchařkou a recepty je to kuchař, Vaše přítelkyně ap. prostě ten, kdo se programem řídí.
Jako jednotlivé instrukce si můžete představit kroky receptu, například:

vezměte pánev = jedna instrukce
vezměte z lednice vejce = další instrukce
zapněte sporák = další instrukce
a tak dále.

Tohle je myslím jasné.


      Procesor pracuje ve strojovém kódu. Strojový kód je v podstatě hromada čísel, ve kterých se vyzná procesor (tedy pokud je program správně napsaný) ale člověk ne. Pro příklad kousek strojového kódu (pro šťouraly - formát INTELHEX):
:10000000D290B2907BA77AAB7910D9FEDAFADBF600
:0200100080F07E
:00000001FF
     No uznejte, že to je nečitelné. Aby bylo programování pro člověka možné (a snadné) byl vytvořen jazyk symbolických adres (JSA) - vžilo se označení assembler. Assembler je nejnižší programovací jazyk. Je to soubor instrukcí toho kterého procesoru, které se postupně zapisují do zdrojového souboru. Tyto instrukce mnemotechnicky vyjadřují jednotlivé povely pro procesor, jsou to zkratky anglických pojmů (např. instrukce DJNZ - decrement and jump is zero - dekrementuj a skoč, pokud je nula).
     Zápisu programu v assembleru (JSA) se říká zdrojový kód - zdroják. Tento zdrojový kód se posléze přeloží překladačem (compilerem) do výše zmíněného strojového kódu, který se pak již programátorem naprogramuje do čipu (nebo paměti EPROM). Dalším výstupem překladače je listing překládaného souboru, a výpis chyb při překladu. Překladač odhalí například překlep v instrukci (třeba místo PUSH napíšete PZSH), skok na neexistující návěští, 2x definované návěští a podobně, v listingu je chyba přehledně zobrazena. Pozor, pokud odstraníte tyto chyby, ještě to neznamená, že Vám program bude fungovat, můžete mít v programu tzv. běhové chyby, kdy například zapisujete jinam, než jste chtěli, čtete jiná data, skoky provádíte jinam a spousta jiných radostí - prostě program běží, ale dělá něco jiného než jste chtěli. A zde nastupuje pojem ladění programu. To znamená postupné odladění funkčnosti subrutin v programu, kontrola výstupů subrutin a tak dále. Tohle je již "vyšší dívčí" programátorská, zatím se tím nemusíte zatěžovat. Další podrobnosti - tedy jestliže chcete, (nejsou nezbytně nutné) naleznete na jiné stránce tohoto webu.
     Jednočipy (tedy nejen jednočipy) je možné programovat buď v assembleru (jazyku symbolických adres - assembler je v podstatě překladač, ale vžilo se toto označení) nebo v nějakém vyšším jazyku např. C. Oboje má svoje výhody a nevýhody, záleží na každém programátorovi, co preferuje. Pokud bych to měl opět převést do naší "kuchařkové" analogie, tak například rozklepnutí vejce v jazyku C bude vypadat takto :

rozklepni vejce
ukliď skořápku


Naproti tomu v assembleru musíme naprogramovat:


zvedni ruku a uchop do ní vejce
klepni s ním o hrnek
šup s obsahem do hrnku
otevři koš
zahoď skořápku
zavři koš

      Rozdíl je v tom, že v C můžeme použít funkce, které již někdo naprogramoval za nás (v oné analogii je to jak zvednout ruku, jak rozklepnout vejce atd. prostě jen napíšete rozklepni vejce). Jednu podstatnou nevýhodu to má v tom, že nám tato funkce nemusí v maličkostech vyhovovat (opět např. chcete oddělit bílek od žloutku a pak nám již funkce rozklepni vejce nevyhovuje), a pak se bez assembleru stejně neobejdeme. Další menší nevýhodou C je poněkud větší velikost software v něm vytvořeného. Ale na druhou stranu ani assembler není bez vady na kráse, nevýhody jsou, že co si člověk neudělá, to nemá, všechny maličkosti si musíte naprogramovat sami a na všechno musíte brát zřetel. S tím však zase získáte kompletní kontrolu nad součástkou, a pokud něco nefunguje jak by mělo, většinou je to chybou mezi židlí a klávesnicí . Prostě v assembleru musíte sice na vše myslet, ale máte nad vším kontrolu (a já jej preferuji, právě z tohoto důvodu).


Aby bylo možné program v mikroprocesoru vykonávat, musí být někde uložen (analogie: recept je zapsán v knize) - k tomu slouží paměť programu. Procesor také musí mít možnost ukládání mezivýsledků operací ap. (analogie: paměť kuchaře -> pamatuji si, už jsem to osolil). Tyto paměti (programu a dat) se rozdělují hlavně podle technologie výroby a funkce.
 Adresa to je základ. Každá paměťová buňka, registr má nějakou svoji adresu. Prostě pokud chcete pracovat s daty, musíte vědět odkud je vzít a kam je dát, je to prostě jako s adresou lidí, pokud chcete někomu něco doručit, musíte znát jméno, ulici, město, zkrátka adresu. Prozatím se nebudu zabývat adresou v programu, formátem adresy atd., stačí, pokud víte, že něco takového jako adresa existuje. Pro práce s pamětí (potažmo s celým procesorem) je tohle pojem, bez kterého "to" prostě nejde dál.
 Paměť programu si "pamatuje" i bez přítomnosti napájecího napětí, je možné ji naprogramovat v programátoru a to buď jednou (OTP), nebo opakovaně, podle mazání lze rozdělit tyto paměti na elektricky mazatelné (FLASH - dnes asi nejrozšířenější) nebo mazatelné ultrafialovým zářením (EPROM - nevýhoda je pomalá manipulace, mazání déle trvá). Do paměti programu procesor nemůže zapisovat (to může pouze programátor - tím myslím zařízení), může z ní jen číst instrukce, co má dělat, popřípadě nějaká pevná data (analogie: instrukce = recept, pevná data = kolik dkg masa do guláše - tedy to, co se nemění). Paměť se označuje jako ROM (read only memory). Může být umístěna na čipu procesoru (FLASH - 89C51, 89C52, 89C2051, asi všechny typy PIC nebo s EPROM 8751). Také existují samozřejmě procesory bez integrované paměti programu (8031, 8032), kdy je nutno paměť umístit v systému mimo vlastní procesor, ale pro zjednodušení nebudu dále pokračovat.
 Paměť dat je paměť, která sice po vypnutí napájení vše zapomene, ale v průběhu práce procesoru do ní můžeme ukládat data, přepisovat je, číst, dále jsou v ní zahrnuty registry pro nastavení vlastní činnosti procesoru nebo jeho integrovaných periferií. Prostě registr v paměti je paměťové místo s nějakým přiděleným pojmenováním a přidělenou adresou. Pro další vysvětlování si prozatím řekněme, že obecné registry jsou nějak pojmenované, místa ve vnitřní RAM pro použití uživatelem pojmenovaná nejsou. Například registr A (accumulator) - jeho adresa E0H, registry R0 až R7 - adresa 00H až 07H (pro šťouraly první banka, pro neznalé - banky nejsou jen o penězích, ale pro Vás to zatím ještě není), registr TMOD - adresa 89H apod. Že Vám není jasný formát adresy a co je to H ? Jen nespěchejte, vše má svůj čas. Jinak předpokládám, že pojem bit, nibble a byte jsou Vám známy (1 byte = 2 nibble = 8 bitů čili nibble = 4 bity).



Pro pochopení jak programovat, zase znovu odbočíme a to tentokrát k číselným soustavám.

Ve škole nás učí desítkovou, v ní počítáme normálně. Pak existuje dvojková (dvojková proto, že má jen dva stavy 1 a 0, v té pracují počítače), a dále existuje šestnácková (hexadecimální - to je ono H u adres, jak jsem psal výše). Ještě existuje speciální interpretace a to je BCD (Binary Code Decimal), ale tím se zatím nebudeme zatěžovat.
     Dvojková soustava se používá právě pro ony dva stavy 1 nebo 0, zapnuto - vypnuto, svítí - nesvítí, (funguje - nefunguje). Tím se podstatně zjednodušuje komunikace čipu s okolím, prostě je vývod buď "v nule" nebo "v jedničce", nic mezi tím. Umíte si představit, jak byste takhle přes jeden vývod dokázali poslat číslo 1 až 10 ? Ne ? Pak právě proto dvojková (binární) soustava. S tím těsně souvisí soustava šestnácková (hexadecimální). Tato soustava má číselný základ ne 10 jako desítková, ale 16. Zmatek ? To přejde. Prostě je to tak, že v desítkové počítáte do 10, v hexadecimální (na tohle označení doporučuji si zvyknout, více se používá) počítáte do 16.
Také zobrazení v této soustavě je jiné. Napočítáte do 9 a pak se pokračuje písmeny, čili 10 odpovídá A, 11 odpovídá B atd. až 15 odpovídá F. Má to výhodu v tom, že když v desítkové napočtete do 9 a pokračujete dál, potřebujete další řád (9 = 1 cifra, 10 = 2 cifry), kdežto u hexadecimální soustavy vystačíte do 16 s jedním řádem (0 až F = 0 až 15 tedy 16 kombinací - čísel). POZOR, u počítačů se 0 bere jako platné číslo, proto šestnácková soustava ! Pro více informací se můžete podívat na jinou stránku tohoto webu, kde si můžete ujasnit převody mezi soustavami a podobně. Osobně pro převody používám kalkulačku, člověk to sice umí převést, ale proč se s tím dřít (třeba u 3 bytového čísla, že). Pro začátek to myslím stačí, až začneme se soustavami pracovat, trochu více tohle téma prohloubíme. Na závěr ještě jedna maličkost, aby bylo na první pohled jasné, o jakou číselnou soustavu jde, dopisuje se za číslem písmeno, takže 15D je normální číslo 15, 15H je hexadecimální číslo (takže je to v desítkové soustavě 1x16+5x1=21D) a nebo 00010101B což je binární číslo.


Nyní si ujasníme vlastní zápis programu a hodnot, abychom se k tomu již později nemuseli vracet.

     Jsou různé způsoby psaní software (teď nemyslím vymýšlení, ale fyzického psaní). Například pro PIC existuje MP Lab, kde si program napíšete, přeložíte a odladíte, pro 8051 já osobně preferuji obyčejný textový editor, který k textu nepřidává žádné formátovací znaky. Lze tedy použít např. Poznámkový blok z Windows 95/98/Me/NT/2000/XP, textový editor integrovaný v Norton Commanderu, Total Commanderu atd. Můžeme použít i další programy jako WordPad nebo MS Word všech verzí, výsledný dokument ale musíme uložit jako "čistý text", tj. v případě WordPadu zvolit při ukládání typ souboru textový dokument - formát MS-DOS, v případě MS Wordu zvolit typ souboru MS-DOS text nebo něco podobného.

Na začátku zdrojového souboru musí být vždy hlavička, která "říká" překladači (compileru) o jaký typ procesoru se jedná, jak má vytvořit listing překladu (kolik znaků na řádek) a další informace. Pro nás hlavním (a nadlouho jediným) zajímavým parametrem je parametr $MOD52. Tento parametr sděluje překladači, o jaký typ procesoru se jedná, tedy jakým způsobem přeložit zdrojový soubor. Jde totiž o to, že funkční registry v procesoru (nastavování přerušení, časovačů, spouštění časovačů ale i např. akumulátor, zásobník a další) mají samozřejmě svoji adresu (umístění v RAM, ale to byste již měli znát), ale abychom nemuseli ve zdrojovém souboru používat tuto adresu, je možné (a pro člověka více než užitečné) se na tyto registry odkazovat obecně vžitým označením těchto registrů. Že tomu nerozumíte ? Prostě opět podle kuchařkové analogie, když řeknu třetí skříňka zprava, druhá police od shora, je to totéž, jako když řeknu příborník. Oboje má stejnou "adresu" (umístění), jen v tom prvním popisu jsem přesně řekl, kde to je. Když na Vás ale vyhrknu "příborník" a Vy nebudete vědět kde ho v kuchyni mám, nejspíš skončíte ve špajzu.
      A stejně je to s tímto parametrem. Ve vnějším souboru, který se jmenuje MOD51 nebo MOD52 popř. jinak podle typu procesoru, (tyto soubory jsou součástí balíčku s překladačem) je nadefinováno, jaké zkratce odpovídá jaká adresa (lidově řečeno). Tímto přiřazením překladač při překladu ví, že pokud narazí na Acc, znamená to adresu 0E0H, pokud narazí na P0, jedná se o adresu portu 0 (tedy 080H). Jinak by byl programátor (tedy Vy) nucen vždy, pokud chce něco uložit/načíst např. do akumulátoru psát 0E0H namísto pohodlnějšího Acc.
Takže abych tuto část uzavřel, tento parametr se zapíše jako $MOD51 pokud chcete překládat pro 8051 nebo $MOD52 pokud použijete 8052.
Jako zlatý hřebíček Vám řeknu, že pokud všude zapíšete $MOD52, můžete to použít i pro procesor 8051, protože umístění registrů je shodné. Jen musíte dát pozor, abyste v programu pro x51 nechtěli něco zapsat do registrů, které má pouze procesor 8052 (třeba časovač 2), protože překladač Vám to sice přeloží (máme přece použito $MOD52), ale když to pak napálíte do procesoru, může nastat problém. Já osobně programuji tak, že při tvorbě nového zdrojového kódu prostě hlavičku opíšu z jiného kódu a je to. Pokud by Vás přesto zajímaly všechny parametry překladače, můžete si je stáhnout na stránce dokumentů.


Důležité: Cokoli ve zdrojovém kódu začíná středníkem, je bráno do konce řádku jako komentář. Pokud je před číslem znak # znamená to zápis čísla. Pokud tento znak nezapíšete, pracujete s paměťovou buňkou. Každý zdrojový kód musí být ukončen direktivou END. U překladače pro 8051 nezáleží na velikosti písmen (velká, malá), ale doporučuji si udělat nějaký systém, jak programy zapisovat, pokud pak přejdete na programování procesorů PIC, tam již na stylu zápisu záleží a to tak, že dost.



     Měl bych upozornit na nový pojem v této části, a tím je "příznak" (praporek, angl. flag). Tímto pojmem většinou označujeme bit, který buď hardware procesoru, nebo i uživatel může nastavit nebo nulovat při nějaké činnosti, výpočtu a podobně (například při přetečení po sčítání, atd.) - podle "kuchařkové analogie": jestliže mi došel cukr, nastavím příznak cukr na 0. Když budu v obchodě, otestuji příznak cukr. Pokud je v nule, koupím cukr. Pokud je v jedničce, cukr nekoupím, protože to znamená, že doma ještě je. Samozřejmě nesmím trpět sklerózou.
Dalším pojmem je port. Portem označujeme většinou vstupně / výstupní bránu, sdružení několika vstupů / výstupů. Pokud budete chtít vědět o portech více, podívejte se na stránku popisu portů, ale je tam popis dosti podrobný, a řekl bych pro začátečníky nepotřebný a nezajímavý.

     A nyní se již dostáváme k vlastním instrukcím mikroprocesoru. Nebudu zde popisovat všechny instrukce, popis najdete na jiné stránce tohoto webu, zde jen ty základní pro první práci.

 Uložení, zkopírování - pomocí této instrukce mohu něco odněkud načíst a zapsat to někam jinam. (Analogie: najdu tel. číslo v seznamu a zapíšu do diáře) Zdrojová buňka (tedy ta, odkud se načítá) nemění svůj obsah (když si přečtete číslo v tel. seznamu taky nezmizí). Ve vnitřní paměti můžete kopírovat (ukládat) buď přímo čísla, nebo obsah jiné buňky (nebo samozřejmě registru). Pro začátek to zatím stačí, nebudeme se prozatím zabývat indirect adresováním a podobnými lahůdkami. Instrukce má tvar MOV cílová slabika,zdrojová slabika nebo MOV cílová slabika,#číslo, v praxi MOV A,#10H uloží do akumulátoru číslo 10 hexadecimálně tedy 16 decimálně (desítkově). Nebo MOV R0,#13H uloží do registru R0 hodnotu 13H (hexadecimálně). Pokud ale zapíšeme MOV A,10H znamená to, že do akumulátoru zapíšeme hodnotu, která je uložena ve vnitřní RAM na adrese 10H. Totéž obdoba MOV 10H,A zapíše obsah akumulátoru na adresu 10H vnitřní RAM procesoru. Jestliže zapíšeme MOV A,#10D, do akumulátoru bude uloženo číslo 10 (D = decimální), jestliže zapíšeme MOV A,#00001111B znamená to ulož do akumulátoru číslo 15. Pokud označení za číslem (H, D, B) nerozumíte, vraťte se zpět na popis číselných soustav.

 Skoky v programu - skoky v programu mohou být nepodmíněné a podmíněné.
Nepodmíněný skok se provede vždy, je to skok na jiné místo v programu (kuchařková analogie: na konci stránky v kuchařce proveďte skok na další stránku s pokračováním receptu). Tento skok se provede prostě vždy, jakmile procesor narazí na instrukci SJMP, AJMP, LJMP (Small, Absolute, Long Jump). Rozdíl mezi instrukcemi prozatím ponechme utajený .
Podmíněný skok se provede jen a pouze tehdy, pokud je splněná nějaká podmínka. (kuchařková analogie: jestliže není po ruce vepřové, udělejte to z hovězího nebo jestiže není ve spíži rýže, uvařte k tomu brambory, jinak dejte vařit tu rýži). Testovat se dá v podstatě leccos, nulovost / nenulovost akumulátoru (instrukce JZ - jump zero, JNZ - jump not zero), test nastavení / nulování nějakého bitu, příznaku (JB - jump bit, JNB - jump not bit, JC, JNC), porovnání obsahu registru a skok při rozdílnosti (CJNE), snížení obsahu buňky a skok při nenulovosti (DJNZ).

 Nastavení / nulování bitů - pomocí instrukcí SETB a CLR můžete nastavit / nulovat adresovaný bit. Například provedením instrukce SETB P1.2 nastavíte bit 2 portu 1 do logické jedničky (tedy přesně řečeno vývod 12 procesoru AT89C2051) a instrukcí CLR P3.0 nastavíte do nuly bit 0 portu 3 tedy fyzický vývod 2 procesoru. Bitové operace můžete provádět s jednotlivými bity portů, bity akumulátoru, s příznaky a s bity v bitově adresovatelné části paměti RAM (část paměti RAM procesoru je možno adresovat po jednotlivých bitech, zbytek jen po bytech).
K tomuto tématu se ještě vztahuje instrukce CPL - instrukce negace. Pokud je např. bit P1.2 (port 1 bit 2) v log. L, a provedete instrukci CPL P1.2, výsledek bude log. H na uvedeném pinu a opačně samozřejmě také (P1.2 v H -> CPL P1.2 -> P1.2 v L).

Je to kupodivu, ale již tyto tři instrukce stačí pro vytvoření jednoduchého prográmku pro 8051, pomocí kterého budeme blikat LED diodou v sekundových intevalech.



První program pro procesor x51
      Předpokládám, že před vlastním započetím studia programování jednočipových mikroprocesorů jste si pořídili nějaký programátor. V dnešní době je jich velké množství na výběr, buď jsou na internetu schémata pro volně dostupné programátory, a nebo je možné si koupit profi programátor. Záleží na systému, jaký budete používat, pokud budete používat procesory s interní programovou pamětí flash (AT89C..), stačí programátor pro ně. Pokud budete (ale to v začátcích zcela jistě nehrozí) používat klasické procesory s externí EPROM (například), je třeba ještě programátor EPROM. Já osobně používám programátor PAtmel, pokud si objednáte procesor za cca 390,-Kč a zbytek si doděláte, je to velmi komfortní zařízení pro programování typu 89C51, 89C52, navíc s pomocí jednoduché redukce umí programovat i "malé" typy 89C2051, 89C4051 a další.

      A nyní již bez okolků k prvnímu příkladu. Je jím velice jednoduchý program (? - to snad ani není program - pár instrukcí), kterými naučíme procesor AT89C2051 (nebo 1051, nebo 4051) blikat s LED diodou v sekundových intervalech. Zapojení je maximálně jednoduché, procesor s taktovacím krystalem a kondenzátory, resetovací kondenzátor C3, blokovací kondenzátory C4 a C5 (zde nejsou bezpodmínečně nutné, ale zvykněte si, přidávat blokování k procesoru, ušetříte si nejednu horkou chvilku), no a konečně LED připojená anodou přes omezovací rezistor R1 na +5V a katodou na bit 2 portu 1. Proč je LED takto polarizovaná, je dáno konstrukcí portů u procesoru 8051 (podívejte se na stránku portů na obrázek portu P1 a vraťte se sem zpět). Porty mají na výstupu tranzistor, který pokud je sepnut, stahuje úroveň na portu do log. L. Kolektor tohoto tranzistoru je přes vnitřní pullup rezistor připojen ke kladnému napájení. Jestliže je výstupní tranzistor rozepnut, je na vývodu (bitu) log. H, z napájecího napětí právě přes onen rezistor. Problém (nebo spíše vlastnost) je to, že přes tento rezistor nemůžeme směrem ven z bitu portu nic napájet, protože tento rezistor má poměrně velkou hodnotu. Naopak přes výstupní tranzistor bitu jsme schopni k zemi "stáhnout" poměrně velký proud (proud LED) - tedy proud tekoucí směrem do vývodu.

Schéma zkušebního zapojeníNáhled na zapojení

Takže si zapojíme schémátko na obrázku, nejlépe třeba na nepájivé kontaktní pole. Hotovo ? Tak a teď k programu.


      Zvykneme si již od začátku vytvářet programy tak, jak by se to správně mělo. To, co vidíte vlevo je tak zvaný vývojový diagram. Jednotlivé tvary mají přiřazený význam (obdélník = přiřazení, kosočtverec = rozhodování), více se zde tímto nebudu zabývat, pokud máte zájem, hledejte na internetu. Vývojový diagram popisuje chování systému v reálném čase. Slouží k vytvoření algoritmu úlohy. Algoritmus je postupné vykonávání kroků, vedoucích k určenému cíli. Rozdíl mezi algoritmem a programem je v tom, že algoritmus je obecný zápis postupných kroků, kdežto program je zápis algoritmu již v daném jazyku pro ten který stroj (kuchařková analogie: recept na guláš je pořád stejný (algoritmus), ale napsaný česky nebo anglicky, to je již program pro český nebo anglický procesor -pardon kuchaře ) Obecné postupy tvorby algoritmů jsou pro všechny typy procesorů velmi podobné, pak již jen záleží, jakými periferiemi a instrukčním souborem je ten který typ procesoru vybaven. (x51, PIC a jiné).
      Jestliže bychom si rozebrali naši úlohu blikání s LED, pak tedy potřebujeme co? Periodicky měnit stav jednoho pinu mezi logickou nulou a logickou jedničkou. Mezi tyto dva stavy je třeba zařadit nějakou časovou prodlevu.
Takže nejprve zhasneme na začátku LED. Pak její stav znegujeme, takže LED rozsvítíme. Nyní musíme nějakou dobu počkat, a po uplynutí této doby stav LED opět negujeme, tím LED zhasne, nyní opět čekáme, negujeme stav atd. Časování v tomto algoritmu (potažmo programu) zajišťuje cyklus. Cyklus v podstatě znamená, že načteme někam nějakou hodnotu, tu postupně zmenšujeme, a pokud není hodnota nulová, program pokračuje stále zmenšováním hodnoty cyklu. U programů obecně si musíme uvědomit, že procesor, pokud mu běží taktování nelze zastavit, prostě stále musí něco dělat, není možné dojít na konec programu a tam se zastavit. Na tenhle základní stavební kámen programů je třeba pamatovat.
Nyní se vrátím k vysvětlení časového cyklu. Je využito tří registrů procesoru, označených R1, R2, R3 (procesor jich má 8 - R0 až R7 v jedné bance, banky se dají přepínat a jsou čtyři, takže dohromady je k dispozici 32 registrů, ale to zatím znát netřeba).
Pokud budete sledovat vývojový diagram, vidíte, že nejprve načteme hodnotu do registru R3, následuje načtení do registru R2 a nakonec do R1. Nyní se bude postupně snižovat hodnota v registru R1, dokud nebude 0. Jestliže hodnota dosáhla nuly, snížíme obsah registru R2 o jednu, znovu načteme hodnotu do registru R1 a opět ji budeme snižovat. A tak dále, pořád dokola. Pokud hodnota v R2 dosáhne nuly, zmenšíme hodnotu v R3, načteme znovu hodnotu do R2 a R1 a opět snižujeme R1, po dosáhnutí nuly snížíme R2 atd. až dosáhneme nuly i v registru R3. Tím jsme se dostali na konec cyklu, vrátíme se na začátek programu, kde změníme (negujeme) stav LED a opět se začne vykonávat časování. Jistě se zeptáte, proč jsou použity zrovna tři registry. Je to proto, že do registru, který je jednobytový můžeme zadat číslo o maximální velikosti 255 (tedy číslo 255, ale počítá se i nula, takže 256). Jestliže máme procesor taktovaný frekvencí 12 MHz, pak k vykonání jedné tříbytové instrukce potřebujeme čas 2 us (mikrosekundy), takže s jedním registrem by zpoždění trvalo maximálně hádejte kolik ? (SPRÁVNĚ - 2x255 mikrosekund). Proto jsou použity registry tři a jednotlivé cykly se násobí, takže výsledná délka je R1xR2xR3. (R1 se provede R2-krát, a to celé se ještě provede R3-krát)
A to je celé. Výše jsem se zmínil o tříbytové instrukci - to není nadávka. Každá instrukce procesoru (příkaz) potřebuje nějakou dobu na své provedení. U 8051-52 jsou instrukce jedno, dvou a tříbytové. Tyto instrukce trvají 1 nebo 2 pracovní cykly procesoru, a zmiňuji se o tom proto, že při počítání přesných časových smyček je nutno s délkou instrukcí počítat (pokud chcete např. čekací smyčku o délce 100usec. a přidáte jednu instrukci o délce jednoho cyklu, ejhle, smyčka již trvá 101usec.)

     A nyní již k funkci.

$MOD52
$TITLE(BYTE SIGNED MULTIPLY)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

org 0

LED	equ	P1.2		;vystup LED
;------------------------------

	setb	LED

zacatek:cpl	LED
	mov R3,#167
cas_1: 	mov R2,#171
cas_2:	mov R1,#16
cas_3: 	djnz R1,cas_3
   	djnz R2,cas_2
   	djnz R3,cas_1
   	sjmp	zacatek

end
Vlevo vidíte výpis programu. A to je celé ? Slyším. Ano, to je celé. Tohle bliká onou LEDkou. Takže popíši činnost od začátku. Prvních šest řádek je nám již dobře známá hlavička. Nyní následuje direktiva pro překladač ORG 0. Tato direktiva není instrukce pro procesor, je to instrukce pro překladač. Tato a podobné direktivy bezprostředně řídí vlastní překlad překladače. Vlastní popis těchto direktiv bude následovat později, momentálně stačí vědět, že direktiva ORG 0 provede nastavení programového čítače na adresu 0, to znamená, že po překladu bude první proveditelná instrukce za touto direktivou umístěna na fyzické adrese mikroprocesoru s číslem 0 (rozeberu později v listingu překladu programu) - tedy na úplném začátku programové paměti. Direktiva překladače EQU provádí přiřazení symbolického jména (zde jména LED) konkrétní adrese, v tomto případě bitu 2 portu P1. Znamená to, že pokud kdekoliv v programu zapíšeme LED, budeme pracovat s odpovídajícím přiřazeným pinem. Toto přiřazování symbolických jmen má dvě základní výhody.
     První, že si můžeme nadefinovat jméno jaké chceme a na něj se pak odkazovat (v zápalu programování se rozhodě lépe napíše např. CLR zelena_LED, SETB cervena_LED, než aby člověk pokaždé vzpomínal "a na kterém že to pinu mám červenou ledku a na kterém zelenou ?").
     Druhý důvod je ryze praktický a oceníte jej ve změnách software. Představte si, že máte rozsáhlý zdrojový kód o několika stovkách (tisících) řádek. Jestliže v tomto kódu budeme používat LED diodu, a pokaždé zapíšeme do programu její bit (čili P1.2 například) a budeme chtít z nějakého důvodu LED připojit na jiný vývod, musíme jít, a všechny instrukce pracující s LED přepsat (např. na P1.3). Pracné, pokud máte instrukci s LED třeba 50x, ale hlavně se snadno něco přehlédne. Jestliže budeme mít ale LED definovánu přiřazením (např. LED equ P1.2) a budeme ji chtít změnit, prostě jen zapíšeme LED equ P1.3 a v programu se nic nemění, neboť ten se odkazuje stále na LED a my jsme LED diodě přiřadili jinou adresu na portu. Tohle je doufám jasné. První instrukcí procesoru je setb LED. Touto instrukcí nastavíme pin (port P1.2) s připojenou LED do stavu log. úrovně H. Protože je LED připojena proti + napájení, svítit nebude. Protože nadále s LED pracujeme, bylo by možné, tuto instrukci vynechat, ale zvykněte si na to, vždy inicializovat připojené zařízení a proměnné, popř. příznaky které budeme používat, po připojení napájení jsou v nahodilém náhodném stavu. Pokud máte rozsáhlejší program a v něm pracujete s nějakým příznakem, který je po každém zapnutí napájení v jiném stavu, Vy jej po resetu nenastavíte do potřebného stavu a pak jej někde v programu testujete, čekají Vás velmi horké chvilky, za to Vám ručím.
     Jestliže se chceme v programu někam odkazovat (skoky) bylo by nemyslitelné vypočítávat adresy skoků, proto existují návěští a o zbytek se postará překladač. Návěští je Vámi volitelný text, v podstatě cokoliv, kromě tzv. rezervovaných jmen. Tato jména jsou jména a označení užívaná překladačem (např. nemůžete použít návěští ACC, protože to je vyhrazeno pro akumulátor) - zakázaná jména budou vypsána později.
     Takže návěští na prvním řádku je zacatek, od instrukce je oddělené dvojtečkou. Program provede instrukci cpl LED (invertuje stav LED bitu, takže bitu P1.2). Dále pokračuje načtením hodnot registrů do R3, R2 a R1. Nyní se dostáváme k vlastní časovací smyčce. Instrukce DJNZ sníží obsah adresovaného místa o jednu a pokud není nula, provede relativní skok na adresu (návěští) v instrukci. Pokud je nula, program pokračuje následující instrukcí. Takže sníží obsah R1 o jednu, a skočí znovu na tentýž řádek (návěští cas_3). Po dosažení nuly (po 16 obězích) pokračuje dalším řádkem. Sníží hodnotu R2 (při prvním provedení na 170), a provede skok na adresu s návěštím cas_2, kde načte znova hodnotu do R1, a cyklus se opakuje. Jestliže dosáhne nuly také R2, provede se snížení obsahu R3, a provede se skok na adresu s návěštím cas_1. Toto jsou ony výše zmiňované podmíněné skoky (je-li splněna podmínka, pokračuje se následující instrukcí, není-li splněna, provede se skok). Jestliže dosáhne registr R3 hodnotu nula, provede se nepodmíněný skok sjmp (nepodmíněný = vždy) na návěští zacatek, kde se provede negace bitu (vývodu) portu, na kterém je LED připojena. A opět se následuje časovací smyčkou. A to je celé, a stále dokola. Všimněte si, že čísla do registrů R1, R2, a R3 jsou zadávána bez označení soustavy (H, D), to znamená, že jsou brána automaticky jako čísla desítkové soustavy.

      Jestliže si upravíte zapojení podle obrázku vlevo (posílíte bit portu tranzistorem), a zkrátíte pauzu mezi změnami na portu, je možné za tranzistor připojit reproduktor, nebo sluchátko a zapojení bude pískat. Výše tónu (čili frekvence odborně ) je dána délkou pauzy mezi jednotlivými změnami úrovně na bitu portu. No a tuto délku nastavujeme změnou hodnoty časovací smyčky. Výpis prográmku pro houkání vidíte vedle obrázku. Také jste jistě zaregistrovali, že časová smyčka je kratší a stačí již pouze jeden registr.
$MOD52
$TITLE(BYTE SIGNED MULTIPLY)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

org 0

LED	equ	P1.2		;vystup LED
	setb	LED

zacatek:cpl	LED
	 mov R1,#164
opak:    djnz R1,opak
         sjmp	zacatek
end


     To je sice všechno hezké, ale co s tím výpisem, jak to udělat, aby to .... Takže si to zapojte podle schémátka. Nyní si zde stáhněte vlastní překladač, rozbalte archiv a uložte soubory do nějakého adresáře. Dále si stáhněte zdrojový soubor prvního příkladu a uložte jej do stejného adresáře. Můžete si tento ASM soubor otevřít, abyste viděli, jak tedy vlastně zdrojový soubor vypadá. Nyní přikročíme k překladu souboru do strojového (respektive IntelHex) kódu. Spustíme tedy v příkazové řádce (popisuji pro např. Windows Commander) soubor Asm51.exe s parametrem, kterým je jméno našeho zdrojového souboru (obrázek vlevo).

Spuštění překladu Ukončení překladu bez chyby

      Po ukončení překladu jsou vytvořeny soubory *.dbg, *.hex a *.lst. Nás zajímá soubor *.hex, který budeme "pálit" do procesoru a soubor *.lst. Soubor LST je listing (výpis) průběhu překladu. Naleznete v něm již konkrétní adresy, kde se co nachází, případně výpis chyb. Mimo jiné je ve spodní části listingu výpis všech návěští použitých v programu a také skutečná adresa, kde tato návěští leží. Dále je tam také výpis všech použitých proměnných a také jejich adresa (u přiřazení jmen některému z pinů portu je vypsáno číslo portu).

Výsledek překladu Listing překladu

     Jestliže dojde během překladu k chybě, je překlad ukončen chybovým hlášením a počtem chyb (obrázek vlevo). Pak si musíte otevřít listing, a podívat se, kde se chyby nalézají. Překladač tato místa označí (obrázek vpravo) a navíc je ve spodní části obrazovky soupis chyb.

Chyba v překladu Listing chybného překladu


       Tuto chybu jsem způsobil záměrně vynecháním písmena e v přiřazení equ. Tím vznikla první chyba - kdy překladači není jasné slovo qu. A protože touto chybou nemáme nikam přiřazeno uživatelské jméno LED, následují chyby, kdy se na toto jméno odkazujeme. (kuchařková analogie: pokud například v kuchařce nebude vysvětleno, že GOUDA je sýr, pak těžko pochopíme recept - vezměte 15dkg GOUDY.)
Listing chybného překladu - spodní část souboru

     Po odstranění všech chyb po překladu (samozřejmě že ne v listingu ale souboru ASM - na to pozor, v zápalu boje s počítačem můžete začít opravovat chyby právě v listingu, a protože to je již jen výsledek překladu, nebude to samozřejmě nic platné) a vygenerování souboru *.hex zbývá jen "vypálit" - naprogramovat procesor. A zapnout napájení. Samozřejmě, že překladač neodhalí programové chyby, to znamená, že nezjistí, zda se Vám ukládá to co chcete, na adresu jakou chcete a podobně. Překladač totiž samozřejmě nemůže vědět, co programátor zamýšlí, a tak odhalení těchto chyb je na programátorovi, kolikrát jde o ladění (název této činnosti) časově zdlouhavé, a ne vždy to, co na papíru musí fungovat bude stejně fungovat i v procesoru ve skutečném světě. Na závěr přidávám i přeložený HEX soubor příkladu 1 s LED a příkladu 2 s reproduktorem.



Ke stažení jsou tyto soubory:


Velikost 16 kByte  Oba příklady - ASM i HEX soubory

Doufám, že Vám oba příklady fungují, a že tato stránka pro Vás měla nějaký přínos.
Chcete-li, můžete pokračovat další stránkou, která Vás provede připojením sedmisegmentové číslicovky k mikroprocesoru, zobrazováním čísel a složitějšími příklady.


Vytisknout stránku

Zpátky Zpátky
© DH servis 2002 -