JEDNOČIPOVÉ PROCESORY

ATMEL AT 89C2051

 

Úvod do problematiky - procesory všeobecne................................................ 3

Organizácia pamäte RAM.................................................................................................. 4

Popis FREE RAM.................................................................................................................. 5

Popis SFR............................................................................................................................. 6

Prvý ľahký úvod do inštrukčnej sady................................................................... 7

DRUHÝ ĽAHKÝ ÚVOD DO INŠTRUKČNEJ SADY:............................................................... 9

Tretí ľahký úvod do inštrukčnej sady................................................................ 10

PRERUŠENIA:......................................................................................................................... 13

EXTERNÉ PRERUŠENIE..................................................................................................... 14

ČÍTAČ/ČASOVAČ................................................................................................................. 17

SÉRIOVÝ PRENOS.............................................................................................................. 22

 

 

 

ÚVod do problematiky - procesory všeobecne

 

 

1)      Program procesora – t.j. to, čo má vykonávať, je uložený v pamäti ROM

2)      Program zapísaný v pamäti ROM sa vykonáva postupným vykonávaním sledu inštrukcií

3)      Inštrukcie sú vlastne jednoduché príkazy ktoré procesor vykonáva (inštrukcia sčítania, odčítania, presunu dát)

4)      Každý procesor má pevnú inštrukčnú sadu a jej syntax (zápis)

5)      Dáta s ktorými procesor pracuje, výsledky matematických operácií sa ukladajú do voľných pamäťových miest v pamäti RAM, ktoré sa nazývajú registre.

6)      Pamäte ROM (kde je program) a RAM (kde sú spracúvávané dáta) sú vzájomne oddelené

7)      Procesor môže prerušiť vykonávanie hlavného programu tzv. prerušením. Vtedy preruší beh programu, vykoná obsluhu prerušenia a vráti sa späť do hlavného programu. Zdrojov prerušení (t.j. to, čo prerušenie spôsobuje) je viac a závisia od typu procesora.

 

 

Základný prehľad procesora:

 

·         Je umiestnený v pätici DIL20

·         Je kompatibilný s procesormi radu ´51, je to 8 bitový procesor)

·         Jeho pamäť ROM má veľkosť 2kbyte a technologicky je realizovaná ako pamäť flash EEPROM – t.j. je asi 1000 krát reprogramovateľná

·         Pamäť RAM má veľkosť 128bytov t.j. 128x8bit RAM

·         Pracovná frekvencia procesora je 0 - 24MHz

·         Napájacie napätie je 2,7 - 6V

·         Obsahuje 15 I/O liniek, užívateľ programom definuje, ktoré sú vstupné a ktoré výstupné. Linky P1.0 až P1.7 tvoria port1 a linky P3.0 až P3.6 tvoria port3

·         Výstupy možno priamo  pripojiť na LED bez použitia ochranného odporu. Jeden pin dodá až 20 mA

·         3 možnosti zabezpečenia programu:     0 - program nemá žiadnu ochranu

1 - program sa nedá z pamäte ROM prečítať

2 - procesor sa nedá prečítať, ani preprogramovať

 

·         procesor obsahuje dva 16 bitové čítače/časovače. Čítač je hardwarové zariadenie, ktoré počíta prichádzajúce impulzy a ich počet ukladá do registra. 16 bitový čítač dokáže zaregistrovať 216 impulzov

·         obsahuje programovateľný sériový vysielač/prijímač (UART = Universal Asynchronous Receiver - Transceiver)

·         obsahuje analógový komparátor

·         je možné využiť 6 zdrojov prerušení

·         k dispozícii je power down mód – t.j. mód, kde dôjde k minimalizovaniu odoberaného prúdu

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Organizácia pamäte RAM

 

Pamäť RAM sa skladá z registrov – t.j. voľných pamäťových miest. Keďže procesor je 8-bitový, aj jeho registre sú 8-bitové. Pamäť RAM uchováva dáta privedené do procesora cez I/O linky alebo porty a dáta vypočítané procesorom. Na to slúži časť pamäte RAM označená ako FREE RAM.

Druhá časť označená ako SFR (Special Function register – špeciálne funkčné registre) obsahuje takisto 8-bitové registre, ale ich obsah, ktorý takisto užívateľ programovo napĺňa, priamo vplýva na chovanie sa procesora a nastavuje sa nimi režim činnosti mikroprocesora, a takisto činnosť čítačov/časovačov, sériového prenosu a externých prerušení.

 

 

Ako na obrázku vidno, spodná časť pamäte RAM (FREE RAM) má veľkosť 128 bytov, rovnako ako časť špeciálnych funkčných registrov.

 

 

Popis FREE RAM

 

Najčastejšie registre používané na uchovávanie dát sú registre R0 až R7. Táto sústava 8 registrov tvorí tzv. banku registrov. Užívateľ má k dispozícii 4 takéto banky registrov. Súčasne môže pracovať len s jednou bankou - ak chce načítať, alebo zapísať údaje do inej banky registrov, musí sa do nej prepnúť vhodným nastavením špeciálneho funkčného registra PSW.

 

Nad bankami registrov je bitovo adresovateľná oblasť - túto teda môžeme pristupovať k dátam priamo po jednotlivých bitoch. Každý bit má svoju adresu (00 až FF) a ak si v programe zadefinujeme, že napr. bit s adresou 50h bude mať symbolický názov "štart", tak v programe sa môžeme kedykoľvek na tento bit odvolať a v prípade potreby ho vynulovať, alebo nastaviť do jedničky.

 

            Nad bitovo adresovateľnou oblasťou je ďalšia voľná oblasť, adresovaná však už len po bytoch. Aj tuto samozrejme v programe môžeme každej adrese dať symbolické meno a potom pracovať s osembitovým registrom, ktorý bude mať dané symbolické meno.

 
 


7FH

 

 

 

 

 

 

 

 

 

30H

 

 

 

 

 

Bytovo adresovateľná oblasť

 

 

 

 

 

2FH

FF

 

 

 

 

 

 

F8

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bitovo adresovateľná oblasť

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

20H

07

06

 

 

 

 

 

00

1FH

 

18H

 

Banka registrov 3

17H

 

10H

 

Banka registrov 2

0FH

 

08H

 

Banka registrov 1

07H

 

0H

 

Banka registrov 0

 

 

Popis SFR

 

 

F8

 

 

 

 

 

 

 

 

F0

B

 

 

 

 

 

 

 

E8

 

 

 

 

 

 

 

 

E0

ACC

 

 

 

 

 

 

 

D8

 

 

 

 

 

 

 

 

D0

PSW

 

 

 

 

 

 

 

C8

 

 

 

 

 

 

 

 

C0

 

 

 

 

 

 

 

 

B8

IP

 

 

 

 

 

 

 

B0

P3

 

 

 

 

 

 

 

A8

IE

 

 

 

 

 

 

 

A0

 

 

 

 

 

 

 

 

98

SCON

SBUF

 

 

 

 

 

 

90

P1

 

 

 

 

 

 

 

88

TCON

TMOD

TL0

TL1

TH0

TH1

 

 

80

 

SP

DPL

DPH

 

 

 

PCON

 

 

 

Zo SFR si zatiaľ všimnime len registre P1 a P3. Ako už ich označenie hovorí, sú to registre, v ktorých je uložený obsah portov P1 a P3. Ak teda chceme niečo na P1 zapísať, stačí, aby sme to zapísali do registra P1 a logické úrovne na pinoch P1 sa adekvátne tomu zmenia. Podobne, keďže sa jedná o I/O porty, kedykoľvek môžeme stav portov zistiť tak, že si ich jednoducho z registra daného portu prečítame.

 

- P1:    Port 1

- P3:    Port 3

 

Ďalší dôležitý register je ACC – akumulátor. Do neho najčastejšie ukladáme dáta a v ňom je výsledok matematických operácií ako napr. sčítanie a odčítanie. Jeho význam nám bude oveľa jasnejší z príkladov – takže hurá do toho. Nasleduje ľahký úvod do inštrukčnej sady:

 

 

Prvý ľahký úvod do inštrukčnej sady

 

 

Inštrukcie zodpovedné za presun dát:

 

 

·         MOV A, Rn           presunie obsah registra Rn do akumulátora (Registre Rn sú registre R0 až R7)

·         MOV A, #data      vloží do A hodnotu „data“ - napr. číslo 20

 

V tomto príkaze sa dodržuje nasledovná konvencia:

MOV A, #11101100b              - ide o binárnu hodnotu

MOV A, #20h                          - ide o hexadecimálnu hodnotu

MOV A, #23                            - ide o decimálnu (desiatkovú) hodnotu

 

 

·         MOV A, direct     pričom „direct“ je priama adresa - napr. 20h. Daný príkaz vloží do akumulátora to, čo je na adrese direct

 

·         MOV A, @Ri        táto inštrukcia presunie do A to, čo je na adrese uloženej v registri Ri, pričom Ri je register R0 alebo R1

 

MOV A, @40h   znamená, že  procesor zistí, čo je uložené na adrese 40h. Predpokladajme, že je tam číslo 20h. Potom do akumulátora prenesie obsah bunky RAM s adresou 20h.

 

Príklady:

 

Urč, čo vykonajú nasledujúce inštrukcie:

 

1)      MOV A, R1          

2)      MOV A, #00001000b       

3)      MOV A, 01h

4)      MOV P1, #255                

5)      MOV A, @R0

 

Odpovede:

 

1)      Presunie do akumulátora obsah registra R1

2)      Do akumulátora vloží osmičku

3)      Do akumulátora vloží jednotku

4)      Na port P1 zapíše číslo 255.V binárnom tvare je to #11111111b, t.j. všetky piny portu P1 sú v logickej jedničke.

5)      Zistí, čo je uložené v R0. Predpokladajme, že je tam číslo x. Potom do akumulátora prenesie obsah bunky RAM s adresou x.

 

 

Najčastejšie používané inštrukcie sú inštrukcie presunu dát ( to sú tie, o ktorých sme vraveli doteraz) a inštrukcie matematických operácií. Tu sú najdôležitejšie z nich.

 

 

 

ADD A, Rn                 sčíta to, čo je v akumulátori s tým, čo je v registri R0. Výsledok ostáva zapísaný v akumulátore. Symbolicky môžeme tňúto inštrukciu zapísať ako:

         (A) + ( to, čo je v Rn) a výsledok ulož do A

 

SUBB A, Rn               od odčíta to, čo ve v registri Rn od akumulátora a  výsledok uloží do akumulátora. Pri odčítaní zohľadňuje výpožičku, v prípade, že A<Rn. Symbolický zápis: (A) - ( to, čo je na adrese uloženej v Rn) + (zohľadni           výpožičku) a výsledok ulož do A

 

 

INC   A                         inkrementuj A - tj. zväčši A o jedna   (A=A+1)

INC   Rn                     inkrementuj obsah Rn - tj. zväčši Rn o jedna   (Rn=Rn+1)

DEC Rn                     dekrementuj Rn - tj. zmenši Rn o jedna   (Rn=Rn-1)

DEC A                        dekrementuj A - tj. zmenši A o jedna   (A=A-1)

INC   direct                inkrementuj obsah priamo uvedenej adresy

DEC    direct             dekrementuj obsah priamo uvedenej adresy

 

 

 

 

 

PRÍKLAD 1: Do registra R0 zapíš číslo tri, do R1 dvojku, sčítaj ich a výsledok zobraz na porte P1.

 

Riešenie:

 

 

org 00h                                   ;umiestni program v pamäti ROM od adresy 00h

$mod2051                              ;použi symbolické mená pre procesor 2051

 

 

MOV R0, #00000011b           ;vlož do R0 trojku

MOV R1, #00000010b           ;vlož do R0 dvojku

MOV A, R0                             ;vlož do A register R0

ADD A, R1                             ;sčítaj A s R1, výsledok je v A

MOV P1, A                             ;presuň obsah v A na P1

 

END                                       ;koniec

 

 

Telo programu je jasné - sú tam použité inštrukcie, o ktorých sme už hovorili. Ostáva vysvetliť príkaz org a $mod2051. Program napísaný v assembleri je ešte pred naprogramovaním potrebné preložiť prekladačom. Slúži na to program a51.

Príkaz org určuje, od ktorej adresy pamäte ROM sa daný program naprogramuje. V našom prípade ho umiestnime štandardtne - od začiatku. T.j. od adresy 00h.

príkaz $mod2051 umožní, že môžeme používať symbolické mená registrov, t.j môžeme použiť príkaz MOV R5, #11110000b namiesto MOV 4h, #11110000b. Tieto dve inštrukcie sú totiž identické - bunka pamäti RAM s adresou 4h je práve register R5 banky0.

END označenie konca programu pre prekladač. Pozor! Za príkazom END musí byť zapísaný ešte jeden prázdny riadok, inak prekladač vyhlási chybu!

 

 

 

DRUHÝ ĽAHKÝ ÚVOD DO INŠTRUKČNEJ SADY:

 

 

LJMP  adresa            táto inštrukcia zabezpečí, že program z miesta tejto inštrukcie priamo odskočí na uvedenú adresu. Keďže inštrukcie sa vykonávajú postupne, po vykonaní inštrukcie na adrese 20h pokračuje vykonávaním inštrukcie na adrese 21h, potom 22h atď.

 

 

JB    bit, adresa (jump, if bit is set) Táto inštrukcia v prípade, že daný bit je v jedničke, spôsobí to, že hlavný program skočí na adresu uvedenú ako paramerer. Príklad:

 

JB P1.1, 20h   Ak pin1 portu P1 je v jedničke, program odskočí na adresu 20h

 

 

JNB    bit, adresa (jump, if bit is not set) To istá, ale odskok na danú adresu nastáva, ak daný bit je v nule.

 

 

 

Iste  nie je príjemné popisovať miesta, kam má program skočiť priamymi adresami (napr. 30h). Oveľa výhodnejšie by boli symbolické mená. Aj to je možné. Dané miesto v programe si môžme označiť tzv. návestím. Príklad:

 

 

navestie1:          MOV P1, #255

                          MOV P1, #0

                          LJMP navestie1

 

 

Ako vidno tento jednoduchý program urobí to, že rozsvieti celý port P1 (teda nastaví všetky jeho piny do jedničky), potom ho zhasne a robí to donekonečna - je v slučke. Samozrejme, ak takýto program spustíme, blikanie portu neuvidíme, lebo procesor vykoná pri 12MHz kryštáli 1milión inštrukcií za sekundu (tento údaj je informatívny, závisí to od zložitosti inštrukcie), takže ďalšou dôležitou vecou, ktorú neskôr využijeme skoro vo všetkých programoch je naprogramovanie čakacej slučky. K tomu nám značne pomôže tretí ľahký úvod do inštrukčnej sady:

 

 

 

 

Tretí ľahký úvod do inštrukčnej sady

 

 

DJNZ  Rn, adresa     zmenši o jedno register Rn a choď na danú adresu,  ak sa Rn =0

DJNZ direct, adresa zmenši o jedno byte s priamo uvedenou adresou "direct" a skoč na adresu "adresa",  ak sa Rn =0

 

LCALL adresa           volanie podprogramu označeného návestím, alebo adresou

RET                            návrat z podprogramu

 

Posledné dve inštrukcie si azda zasluhujú vysvetlenie. Symbolickým menom si môžeme označiť aj časť programu a potom sa naňho kedykoľvek odvolať. Daná časť programu (podprogram) sa vykoná a pokračuje v hlavnom programe. Lepšie je to znázornené na nasledujúcom obrázku. Ako je však vidno, každý podprogram musí končiť inštrukciou RET.

 

 

 

Nuž poďme teda na napísanie programu, ktorý vykoná dostatočné pozdržanie činnosti procesora. Najjednoduchšie riešenie je asi nasledovné

:

1)      naplň ľubovoľný register na maximálnu hodnotu. (teda 255, keďže je to 8-bitový procesor)

2)      znižuj postupne register až na nulu (inštrukcia djnz) a keď sa jeho obsah konečne rovná nule, pokračuj ďalej vo vykonávaní programu.

 

Program teda vyzerá takto:

 

MOV R0, #11111111b           ;naplň R0 hodnotou 255

zaciatok:         DJNZ R0, zaciatok                 ;zníž R0 o jedno a ak sa ešte R0 nerovná 0, skoč

                                                                       ;na návestie "zaciatok"

 

 

Poďme si prepočítať, koľko času zoberie takýto čakací cyklus. Z tabuľky inštrukčnej sady (je v prílohe) zisíme, že na vykonanie inštrukcie djnz potrebujem 2 inštrukčné cykly (je to 2bytová inštrukcia a v jednom inštr. cykle sa pracuje len s 8 bitovým slovom, lebo je to 8bitový procesor) a jeden inštrukčný cyklus trvá 12/frekvencie oscilátora (ak máme kryštál 12Mhz, trvá inštrukčný cyklus teda 1μs.)

 

Teda výsledný čas je 255x2x1μs=500μs=0,5ms.

 

Bohužiaľ, stále málo. Ľudské oko toto zdržanie ešte nevie zaregistrovať. Nasledujúci algoritmus nám však môže pomôcť: Predstavme si, že na dipleji máme číslo 99 a to postupne znižujeme na nulu. Aj keď rozprávam o jednoduchej veci, napíšem to:

 

99  98  97  96  95  94  93  92  91  90

89    88  87  86...

 

Najprv sa teda znižujú jednotky (z deviatky na nulu), a až potom sa o jedno znížia desiatky. (Jednotky opäť prebehnú od deviatky po nulu).

 

Tento fakt možme využiť. Zopakujem ešte raz túto dôležitú vec: číslo vo vyššom ráde sa zníži o jedno až vtedy, poiaľ v nižšom rade neprebehnú všetky čísla - od najvyššieho po najmenšie.

 

Nech teda číslo v nižšom ráde je register R0 a číslo vo vyššom ráde je register R1. Tu máme dokonca tú výhodu, že keď znižujem hodnotu registra idem z čísla 255 na nulu - nie z deviatky na nulu - teda trvá to (podstatne) dlhšie, čo je výhoda. Tu je vývojový diagram:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Celkovo teda program vykoná 255x255 znižovaní a takto získaný čas je už v rozsahu stoviek milisekúnd. Takže iste už nebude problém napísať program, ktorý bude striedavo rozsvecovať a zhášať ledky na celom porte P1: 

 

org 00h                                               ;umiestni program od adresy 00h

$MOD2051                                        ;zabezpečenie možnosti používania symb. mien

 

start:    mov P1, #11111111b             ;rozsvieť P1

            lcall delay                               ;volaj podprogram delay

            mov P1, #00000000b             ;zhasni P1

            lcall delay                               ;volaj podprogram delay

            ajmp start                               ;skok na návestie start

 

 

 

delay:  mov     r1, #11111111b          ;podprogram delay: naplň R1 na hodnotu 255

nav2:   mov     r0, #11111111b          ;naplň R0 na hodnotu 255

nav1:   djnz     r0, nav1                      ;znižuj R0, pokiaľ sa nerovná 0

            djnz     r1, nav2                      ;zníž R1, a ak sa nerovná nule, skoč na nav2

            ret                                           ;návrat z podprogramu

  

END

 

 

 

Iste nebude problém, prerobiť daný program aj na dlhšie časové intervaly. Nasledujúci program bliká P1 v asi sekundových intervaloch:

 

 

$MOD2051

 

start:    mov P1, #11111111b

            lcall delay

            mov P1, #00000000b

            lcall delay

            ajmp start

 

delay:  mov     r1, #2h

nav3:   mov     r2, #ffh

nav2:   mov     r3, #ffh

nav1:   djnz     r3, nav1

            djnz     r2, nav2

            djnz     r1, nav3

            ret

  

END

 

 

 

 

PRERUŠENIA:

 

 

Celkovo existuje 5 zdrojov prerušení s nasledujúcou prioritou (t.j tým, čo sa skôr vykoná):

 

1.      externé prerušenie 0

2.      čítač/časovač 0

3.      externé prerušenie 1

4.      čítač/časovač 1

5.      prerušenie sériového kanála

        

 

 

- každé prerušenie spôsobí, že mikropočítač skočí na špecifickú pevne danú adresu, kde sa musí vyskytovať podprogram, ktorý dané prerušenie spracuje

 

- poradie priority prerušení sa dá meniť

 

-          pri externom prerušení sa dá nastaviť, či bude reagovať na hranu, alebo úroveň.

 

Malé vysvetlenia prerušení:

 

externé prerušenie pin P3.2 a P3.3. Ak na tento pin privedieme log0, lebo dobežnú hranu (závisí od toho, ako je ext. prerušenie nakonfigurované) pre procesor to znamená, že došlo k žiadosti o externé prerušenie.

 

prerušenie čítača/časovača: Najprv definície: čítač impulzy počíta a časovač odrátava presné časové intervaly. K dispozícii máme dva 16 bitové čítače/časovače (T0 - pin P3.4 a T1 - pin P3.5). K prerušeniu od čítača dôjde, ak počet počítaných impulzov už prekročí možnosť čítača (dôjde k pretečeniu) . Keďže je to 16 bitový čítač,  pretečie po 216 impulzoch.  časovač funguje tak, že počíta impulzy o frekvencii 1/12 fosc, pričom fosc je frekvencia kryštálu. Ak dôjde k pretečeniu, znamená to žiadosť o prerušenie.

 

prerušenie od sériového kanála: k tomuto prerušeniu dôjde, ak je úspešne prijatý, alebo vyslaný znak.

 

 

Ako sme vraveli: v prípade, že je zaregistrovaná žiadosť o prerušenie, procesor opúšťa hlavný program a odskakuje na tzv. vektorovú adresu, (závislú od typu prerušenia), kde sa nachádza program určený na obsluhu prerušenia. Na konci tohto programu je inštrukcia RETI (return from interrupt) a procesor pokračuje ďalej vo vykonávaní hlavnáho programu. Tu je tabuľka vektorových adries:

 

typ prerušenia

vektorová adresa

IE0       (ext. prerušenie 0)

03H

TF0      (čítač/časovač 0)

0BH

IE1       (ext. prerušenie 1)

13H

TF1     (čítač/časovač 1)

1BH

RI&TI   (sériový kanál)

23H

 

 

Na to, aby sme mohli vybrať, ktoré prerušenia chceme používať, slúži register povolenia prerušení IE (interrupt enable) umiestnený v SFR (špeciálnych funkčných registroch) .

 

EA

-

-

ES

ET1

EX1

ET0

EX0

 

 

- EA  : centrálne povolenie prerušení

- ES  : povolenie sér. kanála

- ET1   : časovač 1

- EX1   : externé prerušenie 1.

- ET0   : časovač 0.

- EX0   : externé prerušenie 0.

 

pričom               0 = zakázané

               1 = povolené           

 

 

 

 

EXTERNÉ PRERUŠENIE

 

 

Poďme na vec priamo a začnime nasledujúcou úlohou: Napíš program, ktorý po privedení impulzu na EXT0  blikne LED diódou na pine P1.4

 

Vývojový diagram programu je zrejmý:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Vývojový diagram je jednoduchý, pri písaní programu však musíme zohľadniť nasledujúcu skutočnosť: Ak dôjde k žiadosti o prerušenie, program skáče na adresu 03h. Aj keď hlavný program nerobí nič, len čaká na prerušenie, zatiaľ nevieme s istotou povedať, či dĺžka hlavného programu nepresiahne 4 byty a tak nám vlastne bude zasahovať aj do adresy 03h. Preto použijeme nasledujúce riešenie:

 

Hneď prvá inštrukcia (na adrese 00h) bude inštrukcia skoku na adresu napríklad 100h, kde bude umiestnený hlavný program (direktívou org 100h). Takisto direktívou org 03h umiestnime od adresy 03h program na obsluhu prerušenia EXT0.

 

Pamäť ROM teda bude vyzerať nasledovne:

 

 


skok na adresu 100h

03h

 

skok na adresu 150h

 

 

Čárový popisek 3 (bez ohraničení): Vektorvá adresa obsluhy prerušenia EXT0

100h

 

program:

 

 

 

 

 

 

150h

 

obsluha prerušenia EXT

...

reti

 

 

 

Tu je samotný program:

 

 

$MOD2051

 

org 00h                                                          ;na adresu 00h umiestni

ljmp program                                                 ;inštrukciu skoku na navestie hl. programu

 

 

org 100h                                                        ; hlavny program je umiestneny od 100h

program:         mov IE, #10000001b              ; povol prerusenie EXT0

start:               mov P1, #00000000b             ; zhasni P1

                        ajmp start                               ; skoc na navestie start

 

org 003h                                             ; umiestni obsluhu prerusenia od adresy 03h

 

 

setb P1.4                                           ;rozsviet P1.4

delay:  mov     r1, #11111111b          ;uz znamy podprogram delay – cakacia slucka

nav2:   mov     r0, #11111111b         

nav1:   djnz     r0, nav1                     

            djnz     r1, nav2                     

clr P1.4                                              ; zhasni P1.4

reti                                                      ; navrat z prerusenia do hlavneho programu

  

END

Ďalší príklad umožňujúci demonštráciu ext. prerušenia je tzv. „hracia kocka“ : Zrealizuj hraciu kocku – t.j. po stlačení tlačítka sa na displeji zobrazí náhodné číslo od 1 do 6.

Algoritmus je jednoduchý: program postupne inkrementuje port akumulátor od 1 do 6. Samozrejme čas inkrementácie je veľmi malý. Stlačením tlačidla (ext. prerušenie 0) sa aktuálny stav akumulátora vypíše na port1.

 

 

; hracia kocka - generator cisel 1-6

 

$MOD2051

 

 

org 00h

ljmp program

 

org 0003h

ljmp ext0

 

 

org 100h

program:         mov IE, #10000001b ;povol ext. prerusenie0

                        setb IT0                      ;aby ext0 reagovalo na hranu

                        mov P1, #00000000b

start:               mov A, #00000001b

                        inc A

                        inc A

                        inc A

                        inc A

                        inc A

                        ljmp start

                       

 

org 150h

 

ext0:   mov P1, A                    ;obsluha prerusenia vypise obsah akumulatora na P1

            reti

 

  

END

 

 

 

 

 

ČÍTAČ/ČASOVAČ

 

 

 

2051 obsahuje dva 16 bitové čítače/časovače využívajúce registre TH a TL

 

Čítač:  počíta impulzy privedené na jeho vstup a uchováva ich v registroch TH a TL

Časovač: generuje impulzy v presne stanovených časových intervaloch tým spôsobom, že do TH a TL sa zapíše 16 bit.číslo, ktoré procesor postupne  inkrementuje. Keď dôjde k pretečeniu časovača (prechod zo samých 1  do samých 0), vzniká žiadosť o prerušenie.

 

Dôležité zhrnutie: Užívateľ si volí, či chce využiť čítač, alebo časovač správnym nastavením SFR (uvedené neskôr). Vstup čítača 0 je pin P3.4, čítača 1 pin P3.5. Časovač slúži na generovanie presných časových udalostí, negeneruje však impulzy na pinoch T0 a T1, ale dochádza k prerušeniu v presne stanovených a rovnakých časových intervaloch.

 

 

Existujú 4 módy činnosti čítača/časovača:

 

Mód 0: Emuluje 13-bitový čítač/časovač. 

Mód 1: 16-bitový čítač/časovač.                 

Mód 2: 8-bitový časovač s predvoľbou – najčastejšie používaný

Mód 3 : časovač 0  = dva 8-bitové časovače.

                  časovač 1 určuje prenosovú rýchlosť sér. kanála        

 

 

 

 

Registre zodpovedné za nastavenie parametrov čítača/časovača:

 

TMOD

 

GATE

C/T

M1

M0

GATE

C/T

M1

M0

 

 

 

Pričom:

- GATE : štart / stop čítača (1=štart)

- C/T : určuje, či sa jedná o čítač, alebo časovač. (1=čítač, 0=časovač)

- M1, M0 : určuje mód práce:

00 : Emuluje 13-bitový čítač/časovač. 

01 :16-bitový čítač/časovač.

10 : 8-bitový s predvoľbou

11 : časovač 0  = dva 8-bitové časovače.

                             časovač 1 určuje prenosovú rýchlosť sér. kanála

 

 

 

TCON

 

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

 

 

- TF1, TF0 : príznaky pretečenia jednotlivých čítačov

                   (sú v jedničke, keď dôjde k pretečeniu)

- TR1, TR0 : štartovací bit pre čítače. 1=štart, 0=stop

––––––––––––––––––––––––––––––––––––––––––

- IE1, IE0 : príznak externého prerušenia 1 a 0. *

         Nastaví sa do jedničky, ak dôjde k prerušeniu, vynuluje sa po obsluhe prerušenia – sú k dispozícii len na čítanie, generuje a maže ich procesor

 

- IT1, IT0 : určuje typ externého prerušenia, t.j. či ext. prerušenie má byť iniciované dobežnou hranou, alebo úrovňou log. nuly. *

         1=dobežná hrana, 0=úroveň

 

* = nesúvisí s čítačom/časovačom

 

Pozrime sa na jednotlivé módy čítača/časovača podrobnejšie:

 

 

MÓD 0 čítača/časovača1:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Ako je z obrázku vidieť, bitom C/T si volím, či chcem použiť čítač, alebo časovač. Na to, aby však impulzy z vnútorných hodín (C/T=0 t.j. prípad časovača), alebo z fyzického pinu T1 (C/T=1 t.j. prípad čítača) mohli prechádzať ďalej a napĺňať registre TL1 a TH1, spínač CONTROL musí  byť zapnutý. Teda určite musí byť v jedničke bit TR1. Preto je v popise SFR uvedený ako štart/stop čítača alebo časovača. Samotný bit TR1 v jedničke však nestačí, v jedničke musí byť aj druhý vstup hradla AND. Tu si však už môžeme vybrať – buď čítač/časovač odštartujeme softwarovo (nastavením bitu GATE do log. nuly, alebo hardwarovo – privedením log. nuly na fyzický pin INT1. Ajhľa, ako vidno, pinom určeným na externé prerušenie1 môžeme odštartovať aj čítač/časovač.

Pre čítač/časovač T0 platí to isté, len indexy sú nulové, t.j. nie TH1, ale TH0, nie INT1, ale INT0...

Na objasnenie, skúsme zrealizovať 8 bitový čítač, ktorý počíta impulzy a ich počet zobrazuje na porte P1. Využime k tomu čítač 0. Impulzy sa potom samozrejme privádzajú na pin T0.

 

Vývojový diagram:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Použijeme zatiaľ známy mód 0, lebo na port P1 aj tak vyvedieme len 8 bitov registra TL0.

 

 

Tu je výpis programu:

 

 

$MOD2051

 

org 00h                                                          ; na prvu adresu umiestni

ljmp program                                                 ; odskok na adresu 100h, kde je hlavny program

 

 

 

org 100h

program:         mov A, #00000000b               ; vynuluj akumulator

                        mov P1, #0h                           ; zhasni P1

                        mov IE, #10000010b              ;povol citac T0

                        mov tmod, #00000100b         ; citac, mod0, GATE=0

                        mov tcon, #00010000b          ;start TR0

start:               mov A, TL0                             ;vloz do akumulatora obsah TL0

                        mov P1, A                              ; zobraz to na P1

                        ajmp start                               ; skoc na navestie start

 

END

 

 

 

 

 

MÓD 1 čítača/časovača1: sa veľmi nelísši od módu 0, jedine v tom, že register TH1 sa využíva na plných 8 bitov.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MÓD 2 čítača/časovača1: V tomto prípade ide len o 8 bitový čítač/časovač s predvoľbou – využíva sa len register TL1, pretože v registri TH1 je uložená predvoľba – t.j. číslo, ktoré sa automaticky zapíše do TL1, ak dôjde k pretečeniu čítača/časovača.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MÓD 3 čítača/časovača1:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Čítač 0 = 2 osembitové čítače

Čítač 1 = určuje prenosovú rýchlosť sériového kanála

 

 

 

 

SÉRIOVÝ PRENOS

 

 

- Je to plne duplexný UART (Universal Asynchro Receiver- Transceiver)

- 4 módy činnosti

- Registre zodpovedajúce za sér. prenos:

            SCON - Serial port control register

            SBUF  - prečítanie prijatých dát

                        - zápis dát určených na vyslanie

            PCON - obsahuje SMOD bit, ktorý určuje prenosovú rýchlosť (baudrate)

            TH1     - takisto určuje prenosovú rýchlosť

 

 

RxD – prijímanie dát (pinP3.0)

TxD – vysielanie dát (pin P3.1)

 

 

 

 

 

 

 

 

 

SCON : Serial Control Register

 

 

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

 

- SM0, SM1 = Mód sériového vysielania

         00 = Mód 0 :

         01 = Mód 1 : 8-bit UART s voliteľnou prenosovou rýchlosťou

         10 = Mód 2 : 9-bit UART s pevnou prenosovou rýchlosťou

         11 = Mód 3 : 9-bit UART s voliteľnou prenosovou rýchlosťou

 

- REN = povolenie prijímania

- TB8 = 9-ty vysielaný bit (v móde 2 a 3)

- RB8 = 9-ty prijímaný bit (v móde 2 a 3)

- TI = príznak prerušenia pri vysielaní (ak je už znak úspešne vyslaný)

- RI = príznak prerušenia pri prijímaní (ak je prijatý nový znak)

 

Algoritmus sériového vysielania a prijímania:

 

sériové vysielanie:      - nastaviť mód sér. prenosu a prenosovú rýchlosť

                        - zápis dát do SBUF

                                   - čakať, pokiaľ sa bit TI rovná 1  (signál, že dáta boli vyslané)

                                   - vynulovať TI, aby bolo možné vyslať ďalší znak

 

sériové prijímanie:      - nastaviť mód sér. prenosu a prenosovú rýchlosť

                        - povoliť sériový príjem (bit REN=1)

                                   - čakať, pokiaľ sa bit RI rovná 1 (signál, že dáta boli prijaté)

                                   - vybrať dáta z SBUF na ďalšie spracovanie

                        - vynulovať RI, aby bolo možné prijať ďalší znak

 

 

Pozrime sa na jednotlivé módy sériového prenosu podrobnejšie:

 

MÓD 0:

 

V tomto prípade je prenosová rýchlosť rovná :

 

 

 

 

 


Je to málokedy využívaný mód.

 

 

MÓD 1: Ide o 8 bitový UART s voliteľnou prenosovou rýchlosťou. 8-bitový UART znamená, že dáta sa prenášajú systémom: štart bit, 8 dátových bitov a stop bit. Keďže prenosová rýchlosť sa nastavuje pomocou registrov PCON a TH1 (register určený pre čítač/časovač1), je v tomto móde potrebné povoliť časovač1. Ten nakonfigurujeme, aby pracoval v móde s automatickou predvoľbou, ( mód 2 ) a zamaskujeme jeho žiadosť o prerušenie. To preto, lebo čas potrebný na vyslanie jedného bitu sa odvádza priamo z pretečenia čítača 1 naplneného vhodnou predvoľbou. Čím väčšia predvoľba, tým rýchlejšie pretečenie, tým väčšia prenosová rýchlosť. Tú dostaneme podľa vzťahu:

 

 

 

 

 

 

 


Bit SMOD sa nachádza v registri PCON a TH1 je predvoľba časovača1.

Ak chcete požadovanú štandardnú rýchlosť, vyberte si hodnoty bitu SMOD a registra TH1 z tabuľky:

 

 

 

 

 

 

 

 

 

 

 

 

 

 


MÓD 2 – 9 bitový UART s pevnou prenosovou rýchlosťou

 

Prenáša sa štart bit, 8 dátových bitov, 9-ty bit (napr. parita) a stop bit. Prenosová rýchlosť sa rovná:

 

 

 


Príklad: Naprogramuj kontinuálne vysielanie dvoch znakov "1010101010" a "01010101" prenosovou rýchlosťou 2400bit/s.

 

 

 

Riešenie:

Zvolíme mód 1 sériového vysielania (8 bitov, voliteľná prenosová rýchlosť). Časovač1 nastavíme do módu2 (automatická predvoľba) a nepovolíme jeho prerušenie. Z so skôr uvedenej tabuľky zistíme, že pri frekvencii kryštálu 12MHz potrebujeme naplniť predvoľbu na hodnotu f3h. Rovnako nepovolíme ani prerušenie sériového kanála, lebo či bol znak vyslaný budeme kontrolovať softwarovo - podľa stavu bitu TI

 

 

 

$MOD2051

 

org 00h

ljmp program

 

 

org 100h

program:         mov scon, #01000000b         ;mod1 ser. vysielania, zakazanie prijmu (REN=0)

                        mov tmod, #00100000b         ;mod2 casovaca T1, gate=0, casovac T1

                        mov th1, #f3h                         ;baudrate 2400

                        mov tcon, #01000000b          ;start casovaca T1

                       

start:               mov sbuf ,#10101010b

                        jnb TI,$                                   ; cykli sa, dokial sa bit TI nebude rovnat jednicke

                        clr TI                                       ; zmaz TI

                        mov sbuf, #01010101b          ; vysli seriovo data 0101010101

                        jnb TI,$                                   ;cakaj, kym sa znak nevysle

                        clr TI                                       ;zmaz priznak uspesneho vyslania bitu

                        ajmp start                               ; a podme ho znova na zaciatok

 

 

  

END

 

 

 

V nasledujúcom príklade je realizovaný sériový príjem tou istou prenosovou rýchlosťou. Po nastaveniach sa čaká na prijatie znaku, t.j. na prerušenie od sériového kanála. 

 

 

$MOD2051

 

org 00h

ljmp program

 

 

org 100h

program:         mov ie,#10000000                 ;povolenie prerus. ser. kanala, ext1, ext0

                        mov scon, #01010000b         ;mod1 ser prenosu, povolenie prijimania

                        mov tmod, #00100000b         ;mod2 casovaca T1, gate=0, casovac T1

                        mov th1, #20                          ;baudrate=2400 bit/s

                        mov tcon, #01000000b          ;start T1

                                              

start:               ajmp start

 

 

org 023h

ljmp prijem                                                     ; po preruseni od ser. kanala skoc na obsluhu

 

 

org 150h

prijem: mov A, sbuf                                       ; daj do akumulatora prijaty znak

            mov P1, A                                          ; zobraz ho na porte P1

            clr RI                                                  ; zmaz priznak uspesne prijateho znaku, aby sa       

                                                                       ;mohol prijat dalsi

reti                                                      ;navrat z prerusenia

 

 

 

END