JEDNOČIPOVÉ PROCESORY
ATMEL AT 89C2051 

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

0 - program nemá žiadnu ochranu 
1 - program sa nedá z pamäte ROM prečítať 
2 - procesor sa nedá prečítať, ani preprogramovať 

<< 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.



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

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, @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číta to, čo je 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

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 

       

        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 skok na adresu 150h program: obsluha prerušenia EXT ... reti 

Tu je samotný program: 


$MOD2051

org 00h                              ;na adres  u 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:

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

TMOD 

GATE C/T M1 M0 GATE C/T M1 M0

       

Pričom:

TCON 

TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 

 

 

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 

RxD - prijímaie dát (pinP3.0) TxD - vysielanie dát (pin P3.1) 

SCON : Serial Control Register 

SM0 SM1  SM2 REN  TB8 RB8 TI RI 

 

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

sériové vysielanie: 

sériové prijímanie: 

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: 

Table 10. Baud Rate Sumary
Baud Rate  Crystal Frequency SMOD TH1 Reload Velue Actual Baud rate  Error
9600 12.000 Mhz 1 -7(F9H) 8923 7%
2400 12.000 Mhz 0 -13(F3H) 2404 0.16%
1200 12.000 Mhz 0 -26(E6H) 1202 0.16%
9200 11.059 MHz 1 -3(FDH) 19200 0
9600 11.059 MHz 0 -3(FDH) 9600 0
2400 11.059 MHz 0 -12(F4H) 2400 0
1200 11.059 MHz 0 -24(E8H) 1200 0

 

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