Ciele opakovania: Zrýchlený kurz mikropočítača 2051.Príklad riešenia semaforov križovatky s dvomi hlavnými a jednou vedľajšou cestou.; Program zabezpečuje cyklický výber kombinácie svetiel z tabuľky v poradí ktoré sa ; môže zmeniť stlačením jedným z dvoch tlačidiel ktoré využívajú prerušenia INT0 a INT1 ; a slúžia autobusom mestskej dopravy aby si zapli zelenú pri ich príchode na križovatku ; Program zobrazí údaje na porte P1 a porte P3.0 ktoré budú obsahovať farebné ; diódy $mod2051 ; DEFINÍCIE SYMBOLOV REGISTROV A PREMENNÝCH MAX EQU 012h ; Pozícia za Tabuľkou nad povoleným rozsahom STARTH1 EQU 000h ; Pozícia začiatku zelenej H1 STARTH2 EQU 004h ; Pozícia začiatku zelenej H2 STARTV EQU 008h ; Pozícia začiatku zelenej V BusH1 BIT 00h ; Príznakový bit žiadajúci prednosť H1 BusH2 BIT 01h ; Príznakový bit žiadajúci prednosť H2 ;Tu začne prvá inštrukcia programu ;Nasleduje systemová oblast pre uloženie 5 podprogramov obsluhy prerušení od ;HW udalostí a RESET-u. Nasledovné symboly sú definované v súbore mod2051 ; RESET CODE 000H ; RESET ADDRESS ; TIMER0 CODE 00BH ; TIMER 0 INTERRUPT VECTOR - prerušenie od ČASOVAČA 0 ; TIMER1 CODE 01BH ; TIMER 1 INTERRUPT VECTOR - prerušenie od ČASOVAČA 0 ; EXTERN0 CODE 003H ; EXTERNAL INTERRUPT 0 - prerušenie od HW vstupu INT0 ; EXTERN1 CODE 013H ; EXTERNAL INTERRUPT 1 - prerušenie od HW vstupu INT1 ; SERIAL CODE 023H ; SERIAL LINE INTERRUPT VECTOR - prerušenie od sériového portu ORG RESET ; Príkaz pre kompilátor - Nastav počítadlo adresy ; RESET je symbol pre adresu 0000h ljmp Start ; Skok na adresu Start (vid návestie Start:) ORG EXTERN0 ; INT0/P3.2 - podprogram pre obsluhu prerušenia INT0 setb BusH1 ; BIT 00=1 Žiadosť autobusa H1 o prednosť v jazde reti ORG EXTERN1 ; INT1/P3.3 - podprogram pre obsluhu prerušenia INT1 setb BusH2 ; BIT 00=0 Žiadosť autobusa H2 o prednosť v jazde reti ORG 0100h ; Miesto kde sme sa rozhodli umiestniť začiatok programu Start: mov B,#-1 ; Štartovacia hodnota registra B "počítadlo relatívnej pozície v Tabuľke" setb IT0 ; nastav bity IT0, IT1 aby reagoval na zmenu prechodu napätia setb IT1 ; log1(+5V)\ log0 (0V) ktoré spúšťa podprogram obsluhy prerušenia mov DPTR,#Tabulka ; naplň do registra DPTR (16bit) adresu "prekódovacej tabuľky" mov IE,#10000101b ; povoľ prerušenie INT0, INT1 nastavením bitov IE registra ; Opakuj: inc B ; B=B+1 "Číslo vykonávaného riadku v pracovnej Tabuľke" call TESTmaxS ; TEST či udaj v B neprekročil hranicu tabuľky - nastav 0 call Zobraz ; zobraz údaj na pozícii v tabuľke udanej v B registri call Pauza ; chvíľku zobrazuj ljmp Opakuj ; opakuj nekonečný cyklus hlavného programu Zobraz: mov A,B ; B-ty riadok v tabuľke zobraz 8 bitmi portu P1 a 1 bitom portu P3.0 call SetP30 ; podľa hodnoty B nastav/vynuľuj bit P3.0 vid. "Tabuľka" movc A,@A+DPTR ; z tabuľky vyber riadok mov P1,A ; zobraz údaj pomocou portu P1 ret ; Podprogram pre SetP30: cjne A,#09h,SetP30a ; Skoč na podpr. pre nastav. bitu 0 portu P3 pre pozície B=9 a B=10 v tabuľke setb P3.0 ; ak ÁNO nastav P3.0=1 ret SetP30a: cjne A,#0Ah,SetP30b ; je = 10 (0Ah)? ak NIE pokračuj na SetP30b setb P3.0 ; ak ÁNO nastav P3.0=1 ret SetP30b: clr P3.0 ; pre všetky ostatné prípady daj 0 bit portu P3.0=0 ret ; TEST vyhodnocuje jednak či B neprekročil hranicu Tabuľky a jednak v konkrétnych ; pozíciách testuje žiadosti o prednostnú zelenú na križovatke ; situácia sa môže takou stať pri pozícii 8 a pozícii 12 ; Na pozícii 8 môže dojsť k zmene pozície na 0 ak o ňu požiadal autobus H1 ; Na pozícii 12 môže dojsť k zmene pozície na 4 ak o ňu požiadal autobus H2 TESTmaxS: mov A,B ; TEST či hodnota B neprekročila hornú hranicu tabuľky cjne A,#STARTV,Pok0 ; POZÍCIA 8(STARTV): TEST žiadosti H1 jnb BUSH1,goV ; ak nežiada pokračuj V clr BUSH1 ; ak ÁNO vynuľuj príznak žiadosti H1 a nastav Pozíciu 0 v B mov B,#STARTH1 goV: ret Pok0: cjne A,#MAX,Pok1 ; POZÍCIA 12(MAX): TEST žiadosti H2 jnb BUSH2,goH1 ; ak nežiada pokračuj H1 na Pozícii 0 v B clr BUSH2 ; ak ÁNO vynuľuj príznak žiadosti H2 a nastav Pozíciu 4 v B mov B,#STARTH2 ret goH1: mov B,#STARTH1 Pok1: ret ; Nebola ani pozícia 8 ani pozícia 12 pokračuj ďalej Pauza: mov R1 #001h ; Program vykoná počet cyklov odpovedajúci súčinu R1xR2xR3 x 0.000002 sek pau3: mov R2 #0FFh pau2: mov R3 #0FFh pau1: djnz R3,pau1 djnz R2,pau2 djnz R1,pau3 ret ; Poradie H1 > H2 > V môžu narušiť žiadosti BusH1 a BusH2 ; ; -----Port P1----- P3.0 ============== ; 7 6 5 4 3 2 1 0 0 H2 H1 ; č ž z č ž z č ž z BusH1 ====+ +==== Tabulka: db 0D2h ; 0 H1 x x . x . . x . . <-----+ <-+ | | db 032h ; 1 . . x x . . x . . | | | V | db 032h ; 2 . . x x . . x . . | | db 052h ; 3 . x . x . . x . . | | ; BusH2 | | db 09Ah ; 4 H2 x . . x x . x . . <---------+ db 086h ; 5 x . . . . x x . . | | db 086h ; 6 x . . . . x x . . | | db 08Ah ; 7 x . . . x . x . . | | ; | | db 096h ; 8 V x . . x . . x x . ? ->--+ | db 090h ; 9 x . . x . . . . x 9=9h | db 090h ; 10 x . . x . . . . x 10=Ah | db 091h ; 11 x . . x . . . x . | ; 12 ? ->------+ ; Poznámka x=1 .=0 č_ervená ž_ltá z_elená ENDNa žltom podklade je program napísaný v assambleri I8051. program je písaný v klasickom textovom editore. Pri jeho písaní však musíme dodržiavať určité pravidlá ktoré nám uľahčia prácu:
Začíname sa oboznamovať s programovaním a inštrukciami.
Činnosť mikropočítača závisí od vnútornej štruktúry - majme to na pamäti
keď sa učíme inštrukcie. MOV A, R0 ; prenes obsah registra R0 do Acc ( Accregister označujeme A) MOV R0, B ; prenes obsah reg. B do registra R0 Vstupné a výstupné porty - registre: P0, P1, P2, P3 možno adresovať aj bitovo Pn.0 až Pn.7 kde n=0,1,2,3 Príklady:MOV P1,#FFH ; zapiš masku na port P1 hodnotou 0FFh pred čítaním (bity = log 1) MOV A, P1 ; načítaj obsah portu P1 do registra Acc ale len bity s log.1 masky ; maska sluzi formou logického súčinu maska * P1 (len 1*1=1, 0*x=0) MOV P3,A ; výstup obsahu akumulátora na port P3 SETB P3.4 ; nastav bit4 =1 portu P3 CLR P3.5 ; vynuluj bit5 =0 portu P3 RAM pamäť pre prácu s dátami: od adresy 00H - 7FH tj 127 bajtov.
; v PSW registri sú nastavené bity RS1,RS0 = 00 t.j. aktívny bank0 MOV R0,#3FH ; vlož do registra R0 hodnotu 3FH - objaví sa na drese 08H v RAM pamäti SETB RS0 ; pôvodne RS1,RS0 = 00 bank0 zmeníme na bank1 RS1, RS0 = 01 MOV R0,#3FH ; vlož do registra R0 hodnotu 3FH vloží ju na adresu 08H v RAM pamäti kde je ; mapovaný register R0 v banku1
STAV BIT 02H ; Príznak STAV bude bit s adresou 02H v bitovom poli ; t.j. definícia jednobitovej premennej SETB STAV ; nastav STAV =1 nastaví bit s por. číslom 02H v bitovom poli na 1 CLR STAV ; nuluj STAV =0 nuluje bit s por. číslom 02H v bitovom poli na 0
POCET EQU 30H ; priraď symbolu POCET hodnotu adresy 30H t.j. definícia premennej MOV POCET,#3FH ; vlož do bunky RAM pamäte konštantu 3FH t.j. priraď hodnotu premennej MOV A,POCET ; prečítaj hodnotu premennej do registra Acc MOV P1,#FFH ; pred čítaním z portu musíme nastaviť každý bit čítaného portu na logickú 1 MOV A, P1 ; načítaj obsah portu P1 do registra Acc ale len bity s maskou 1 ; maska je udaj zapísaný do portu buď pri resete (0FFh) alebo nami MOV P3,A ; výstup obsahu akumulátora na port P3 (môže plniť aj úlohu masky) SETB P3.4 ; nastav bit 4 =1 portu P3 CLR P3.5 ; nuluj bit 5 =0 portu P3 Oblasť RAM - RSF registre špeciálnych funkcií (80H-FFH) je rezervovaná pre mapovanie pracovných registrov, voľne použiteľných pre premenné a polia v programoch PSW, . Príklady:POCET EQU 30H ; priraď symbolu POCET hodnotu adresy 30H t.j. ; definícia premennej - toto je príkaz pre kompilátor MOV POCET,#3FH ; vlož do bunky číslo POCET v RAM pamäti konštantu 3FH t.j. ; priraď hodnotu premennej POCET - toto je inštrukcia Zásobníková pamäť - nazývaná aj FILO - first in last out - prvý dnu posledný von - je len vyhradená časť vnútornej RAM pamäti. Používa špeciálny register označený SP - Stack pointer - ktorý obsahuje adresu vrchola zásobníkovej pamäti - t.j. adresu posledného vloženého bajtu. Zásobníková pamäť môže byť umiestnená kdekoľvek vo vnútornej RAM pamäti. Zásobník sa rozširuje smerom k adresám s vyššou hodnotou adresy. Zásobníková pamäť má jedine dve operácie VLOŽ a VYBER.
Pri nekontrolovanom plnení a výbere môžu nastať problémy s pretečením alebo naopak podtečením zásobníka. Pri pretečení premažeme nad vyčleneným priestorom zásobníka nejaké premenné v RAM pamäti. Pri podtečení vyberieme zo zásobníka viac premenných než sme ich tam vložili - t.j. vyberieme nesprávne dáta, a naviac pri následnom vkladaní premažeme dáta pod zásobníkom. Ak my neurčíme inú adresu (napr.: MOV SP, #2Fh) pri resete sa nastaví adresa bunky 07h. Znamená to, že ukladané dáta zásobníka prekrývajú časť pamäte v ktorej sa nachádzajú bank1, bank2 a bank3 registrov R0 až R7 a ďalej nad nimi umiestnené bitové pole v internej RAM pamäti. Príklady:; príklad zmeny bázy zásobníka na adresu 2FH - ktorá sa nikdy nepoužije MOV SP,#2FH ; prvý bajt sa uloží na adresu 30H PUSH Acc ; ulož obsah Acc do zásobníka SP= SP+1 a <SP>= Acc POP Acc ; vyber udaj zo zásobníka do Acc Acc= <SP> a SP= SP-1 Registre určené na adresovanie v RAM alebo ROM pamätiach: R0, R1, DPTR, SP Príklady:; uloženie tabuľky v ROM pamäti TABULKA: DB 3FH ; definícia konštánt v tabuľke - symbol TABULKA EQU <adresa začiatku> DB 5FH ..... MOV DPTR,#TABULKA ; načítanie adresy tabuľky (16 bit) do datapointra MOV A,#0 ; pred nasledovnou operáciou sa nastaví relatívna adresa v Acc MOVC A,@A+DPTR ; načítanie konštanty z relatívnej adresy 0 (v Acc) v TABULKA do Acc ; po operácii v Acc je načítaná hodnota tu je to 3FH ;----------------------------------------------------------------------------------------------- ; príklad vynulovania poľa pomocou Index registra (adresového registra) v RAM pamäti POLE_A EQU 30H ; priraď symbolu POLE_A hodnotu adresy 30H t.j. definícia premennej poľa MOV R0,#POLE_A ; vlož do R0 adresu POLE_A v RAM MOV A, #0 ; nuľuj Acc MOV R2,#10 ; počet prvkov poľa do registra R2 OP: MOV @R0,A ; plň 0 do poľa POLE_A INC R0 ; zvýš adresu bunky v poli POLE_A DJNZ R2,OP ; zníž počítadlo nulovaných buniek, ak R2=0 KONIEC inak opakuj OP:
|