Zdravím, naprogramoval jsem tuto práci:
V assembleru sestavte program, který bude plnit funkci zařízení pro generování
světelných efektů. Světelné efekty budou zobrazovány na LED diodách kitu EVB5.1.
Ovládání programu bude realizováno pomocí tlačítek kitu EVB5.1 (nezapomeňte
ošetřit zákmity tlačítek). Nastavení, změna pracovního módu a rychlosti přepínání
jednotlivých sekvencí, bude možné pouze při pozastavení běhu aplikace, v tomto
případě bude na LED diodách zobrazován pracovní mód aplikace, nebo rychlost
přepínání sekvencí (podle aktuální změny parametru).
Požadavky na funkce programu:
Pracovní módy světelných efektů budou ve formě:
Běžícího světla.
Inverzního běžícího světla.
Obousměrného binárního čítače (0 – 255).
Požadavky na ovládání aplikace – pomocí tlačítek bude možné:
Nastavení rychlosti změny zobrazované kombinace.
Nastavení pracovního módu - přepínání mezi jednotlivými pracovními módy
aplikace.
Pozastavení a opětovné spuštění aplikace.
10
Běžící světlo bude pracovat v nekonečném pracovním cyklu zprava do leva a
následně zpět, stejně tak inverzní běžící světlo. Binární čítač bude čítat nejprve
vzestupně od 1 do 255 a po dosažení hodnoty 255 zpět k hodnotě 1, po dosažení
hodnoty 1 opět změní směr čítání na vzestupný do 255 a tak pořád do kola,
v nekonečném cyklu.
Změna (rychlost změny) stavu bude nastavitelná pomocí tlačítek kitu v rozsahu
deseti kroků v rozmezí cca 0,1 – 1Hz (to znamená 10x – 1x za sekundu).
Aktuální pracovní režim bude uchován v paměti EEprom (pracovní mód a rychlost),
ze kterého bude po restartu aplikace opětovně načten.
A jediné co mi na programu nejde, je to že po stisku reset tlačítka nezačne program tam kde přestal a já si nevím rady. Poradil by mi prosím někdo jak upravit tento program?
Zde je program v assembleru:
.nolist ;definice ATMEGA32
.Include "m32def.inc" ;pro každý program stejné
.list
.DEF REG=R16 ;promněná REG se ukládá do registru16
.DEF CITAC1=r23 ;promněná CITAC1 se ukládá do registru17
.DEF CITAC2=r25 ;promněná CITAC2 se ukládá do registru18
.DEF CITAC3=r19 ;promněná CITAC3 se ukládá do registru19
.def A=r20 ;promněná A se ukládá do registru20 , A je pomocná promněná na nastavení programového modu
.def POM=r21 ;promněná POM se ukládá do registru21 , POM je pomocná promněná pro zapsání konstanty pro čítač
.def B=r22 ;promněná B se ukládá do registru22, B je pomocná promněná pro nastavení rychlosti
.EQU DDR=DDRB ;zápis DDR je ekvivalentní zápisu DDRB
.EQU PORT=PORTB ;zápis PORT je ekvivalentní zápisu PORTB
.DEF CNT1=R0 ; počítadla
.DEF CNT2=R1 ; pro USTAL
.CSEG
.ORG 0
RJMP START ;při restartu program skočí do návěští START
.ORG INT0Addr ;definice přerušení
RJMP PRERUS0 ;připřerušení z PD2 skočí do návěští PRERUS0
START:
LDI REG, LOW (RAMEND) ;inicializace zásobníku
OUT SPL, REG ; nastav ukazatel SP na konec SRAM
LDI REG,HIGH(RAMEND) ;nejprve dolní byyty potom horní byty
OUT SPH,REG
SER REG
OUT DDR, REG ; aktivuj výstupy
SBI PORTD, 2 ; PRERUSENI !!NEMENIT!! S2 má pull – up rezistory
CBI DDRD, 0 ; nastavení pd0 jako vstup
SBI DDRD, 0 ; pd0 má pull – up rezistory, defaultní stav je 1
CBI DDRD, 1 ; pd0 má pull – up rezistory, defaultní stav je 1
SBI DDRD, 1 ; nastavení pd1 jako vstup
CBI DDRD, 3 ; pd0 má pull – up rezistory, defaultní stav je 1
SBI PORTD,3
; obě přerušení se spouští od sestupné hrany
; bity 0 a 1 jsou pro INT0, bity 2 a 3 jsou pro INT1
; kombinace "10" nastaví citlivost na sestupnou hranu
LDI REG,0b00001010
OUT MCUCR,REG
; povoleni přerušeni INT0
; bit 6 povoluje INT0
LDI REG, 0b01000000
OUT GICR, REG
LDI REG,0b00000000
SEI ;povoluje přerušení
SER REG ;do REG ulozi 0b11111111 (ldi REG, 0b11111111)
OUT DDR, REG ;na PORTB posle obsah registru DDRB, portb je výstupní
CLC ;vymaže se příznak C
RCALL EEPROM_readA ;nahraje a z eeprom
;LDI POM,8 ;do POM se nahraje rychlost 8 což je cca 0,1hz
RCALL EEPROM_readB ;vymaže se promněná B
; NEKONECNO: ;nekonečná smyčka ve které můžeme nastavit pomocí pd0 programový režim a pomocí pd3 rychlsot programu od nejrychlejší po nejpomalejší
; SBIS PIND,0 ;skip if bit in IO is set takže dokud bude na pd0 další příkaz se nevykoná
; RJMP VYBER
; RCALL USTAL ; ustal, smyčka pro ustálení zákmitu
; SBIS PIND,0
; RJMP VYBER
; SBIS PIND,1 ;skip if bit in IO is set takže dokud bude na pd1 další příkaz se nevykoná
; RJMP ZVYS
; RCALL USTAL ; ustal, smyčka pro ustálení zákmitu
; SBIS PIND,1
; RJMP ZVYS
; RJMP NEKONECNO
PRERUS0: ;co se vykoná když program přerušíme,
SEI ;nejprve se znovu povolí přerušení
SBIS PIND,0 ;poté obdoba nekonečné smyčky, můžeme nastavir programový režim
RJMP VYBER
RCALL USTAL ; ustal
SBIS PIND,0
RJMP VYBER
SBIS PIND,3 ; nebo se můžeme vrátit kde jsme skončili
RETI ;nefunkční při změně rychlosti
SBIS PIND,1 ;nebo můžeme nastavit rychlost od nejrychlejší po nejpomalejší
RJMP ZVYS
RCALL USTAL ; ustal
SBIS PIND,1
RJMP ZVYS
RJMP PRERUS0 ;program zůstane v přerušení dokud nevykonáme nějakou akci
ZVYS: ; návěští pro zvýšení promněné B tedy pro snížení rychlosti běhu programu
SBIS PIND,1 ; ošetření zákitu
RJMP ZVYS
INC B ;zvýšení B o 1
RCALL EEPROM_writeB
OUT PORT,B ;ukázání promněné B na LEDkách aby jsme věděli co se děje
CPI B,11 ;když je B>11 tak se skočí na VYMAZB a tím se B vynuluje, tedy v tomto případu se nastaví 1
BRGE VYMAZB
RJMP PRERUS0 ;skočí se zpět do přerušení a čeká se buď na programový režim nebo na návrat do stávajícího programu
VYBER: ;návěští pro výběr programového režimu
SBIS PIND,0 ;ošetření zákmitu
RJMP VYBER ;velmi podobná smyčka jako u rychlosti
INC A
RCALL EEPROM_writeA
OUT PORT,A
CPI A,0b00000100
BRGE VYMAZA
RJMP VYBERA ; jediný rozdíl je v tom že skočí na návěští VYBERA
VYBERA: ; to znamená že bu´d můžeme zvolit jiný programový režim nebo tlačítkem PD1 spustit program
SBIS PIND,0
RJMP VYBER
RCALL USTAL ; ustal
SBIS PIND,0
RJMP VYBER
SBIS PIND,3 ;při stisku PD1
RJMP VOLBA ;se skočí na návětší VOLBA
RCALL USTAL ; ustal
SBIS PIND,3
RJMP VOLBA
CPI A,0b00000100 ;pokud A>3 tak se vynuluje
BRGE VYMAZA
RJMP VYBERA
VYMAZB: ;návětší pro vynulování B
SER REG
OUT PORT,REG
LDI B,1
OUT PORT,B
RJMP PRERUS0
VYMAZA: ;návětší pro vynulování A
SER REG
OUT PORT,REG
CLR A
RJMP VYBER
VOLBA: ;návětší pro VOLBu programu do něj se skočí při zmáčknutí PD1
CPI A,0b00000001
BREQ CITAC
CPI A,0b00000010
BREQ SVETLA
CPI A,0b00000011
BREQ SVETLAINV
CITAC: ;návěští pro první program, čítač který čítá od 1 do 255 a poté od 255 do 1
RCALL ROZHODNI ;zde se vyvolá návěští ROZDONI které rozhodne o rychlosti programu v závislosti na proměné B
CLR REG
CITACINC:
INC REG ;přičtení 1
BRBS 3,NAPLNENO ;pokud se v příznaku přetečení objeví 1 (Overflow Flag) tak se skočí na návěští NAPLN, jinými slovy objeví se 9 bit
OUT PORT, REG ;na PORTB posle obsah registru DDRB
RCALL CEKEJ ;zavola podprogram CEKEJ
RJMP CITACINC ;skoci na navesti CITACINC,neboli nekonečná smyčka dokud se neobjeví OF
VYMAZANO:
CLR REG ;pro jistotu se REG vymaže
RJMP CITACINC
NAPLNENO:
SER REG ;pro jistotu se do REG nahrají samé jedničky
RJMP CITACDEC
CITACDEC:
DEC REG ;odečtení 1
BRBS 3,VYMAZANO ;pokud se v příznaku přetečení objeví 1 (Overflow Flag) tak se skočí na návěští NAPLN, jinými slovy objeví se -1 bit
OUT PORT, REG ;na PORTB posle obsah registru DDRB
RCALL CEKEJ ;zavola podprogram CEKEJ
RJMP CITACDEC ;skoci na navesti CITACDEC
SVETLA: ;návětší pro normální běh světel
RCALL ROZHODNI ;zde se vyvolá návěští ROZDONI které rozhodne o rychlosti programu v závislosti na proměné B
LDI REG,0b11111111 ;
OUT DDR, REG ; aktivuj výstupy
CLC ; 0 do C
SMYCKA:
OUT PORT, REG ; pošli
RCALL CEKEJ ; počkej 0,5 s
ROR REG ; posuň,ROR funguje tak že dělá mocninu dvou např 0010 po použí ROR vypadá 0001
BRCC SMYCKA3 ; když je Carry Flag = 0 skočí se do SMYCKY3
BRCS SMYCKA ;pokud ale je CF=1 opakuje se režim s ROR
SMYCKA3: ; posuneme z okraje hodnotu
ROL REG
RJMP SMYCKA2
SMYCKA1: ; posuneme z okraje hodnotu
ROR REG
RJMP SMYCKA
SMYCKA2: ;stejný režim jako SMYCKA ale na druhou stranu
OUT PORT, REG ;posli
RCALL CEKEJ ;pockej cca 0,5s
ROL REG ;posun
BRCC SMYCKA1
BRCS SMYCKA2
SVETLAINV: ; běh inverzního zobrazení světel
RCALL ROZHODNI ; znovu se vyvolá podprogram ROZHODNI a nastaví se rychlost
LDI REG,0b10000000 ; jedna LED je zhasnutá ostatní jsou rozsvícený , při 0 je LED rozsvícená je zde opačná logika
CLC ;vymaže se příznak C
RJMP SMYCKA4
SMYCKA4: ;znovu skoro identické jako s normáním během
OUT PORT, REG ;posli
RCALL CEKEJ ;pockej cca 0,5s
ROR REG ;posun
BRCC SMYCKA4 ; jediná vyjímka je zde kde se je Carry flag=0 až do konce běhu až poté se nastaví na 1
BRCS POSUN3 ; a můžeme skočit do smyčky která ledky roluje na druhou stranu
POSUN3:
ROL REG
RJMP SMYCKA5
POSUN4:
ROR REG
RJMP SMYCKA4
SMYCKA5: ;identické jako předchozí
OUT PORT, REG ;posli
RCALL CEKEJ ;pockej cca 0,5s
ROL REG ;posun
BRCC SMYCKA5
BRCS POSUN4
; čekací rutina čeká se podle toho jaká je hodnota v POM
CEKEJ:
mov CITAC1,pom
CLR CITAC2
CLR CITAC3
CEKEJA:
DEC CITAC3
BRNE CEKEJA
DEC CITAC2
BRNE CEKEJA
DEC CITAC1
BRNE CEKEJA
RET
USTAL: ;návětší pro Ustálení, velmi podobná funkce jako s Čekajícími smyčky prostě se decrementuje registr dokud v něm není 0
CLR CNT1 ;CNT1=0
CLR CNT2 ;CNT2=0
USTALS:
DEC CNT2 ; sniž CNT2
BRNE USTALS ; test konec
DEC CNT1 ; sniž CNT1
BRNE USTALS ; test konec
RET ; návrat
ROZHODNI: ;návětší pro ROZHODNutí která rychlost bude v čítači
CPI B,1
breq rych1
CPI B,2
breq rych2
CPI B,3
breq rych3
CPI B,4
breq rych4 ; Potřeba změni na BREQ po každém CPI
CPI B,5
breq rych5
CPI B,6
breq rych6
CPI B,7
breq rych7
CPI B,8
breq rych8
CPI B,9
breq rych9
CPI B,10
breq rych10
rych1:
ldi pom,6
rjmp PRERUS0
rych2:
ldi pom,12
rjmp PRERUS0
rych3:
ldi pom,18
rjmp PRERUS0
rych4:
ldi pom,24
rjmp PRERUS0
rych5:
ldi pom,30
rjmp PRERUS0
rych6:
ldi pom,36
rjmp PRERUS0
rych7:
ldi pom,42
rjmp PRERUS0
rych8:
ldi pom,48
rjmp PRERUS0
rych9:
ldi pom,54
rjmp PRERUS0
rych10:
ldi pom,60
rjmp PRERUS0
EEPROM_writeA:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_writeA
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Write data (r16) to data register
out EEDR,A
; Write logical one to EEMWE
sbi EECR,EEMWE
; Start eeprom write by setting EEWE
sbi EECR,EEWE
ret
EEPROM_readA:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_readA
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Start eeprom read by writing EERE
sbi EECR,EERE
; Read data from data register
in A,EEDR
ret
EEPROM_writeB:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_writeB
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Write data (r16) to data register
out EEDR,B
; Write logical one to EEMWE
sbi EECR,EEMWE
; Start eeprom write by setting EEWE
sbi EECR,EEWE
ret
EEPROM_readB:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_readB
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Start eeprom read by writing EERE
sbi EECR,EERE
; Read data from data register
in B,EEDR
ret