Tänkt ledsnurra som ställer till problem
Tänkt ledsnurra som ställer till problem
Har filat lite på en tråd som väl i dagsläget inte gör något alls. Tanken är att det skall bli en ledsnurra en dag. Har sett att många innan mig har klarat detta så ni skall nog kunna hjälpa mig. Vill att min kod nedan skall tända lysdioder i förhållande till textsträngen när ett externt interupt på Pin D2 dyker upp.
Main:
.include "m8def.inc"
.org 0x0000
rjmp Reset
.org INT0addr
rjmp Send
;***********************************************************;
Reset:
ser r16
out DDRB, r16 ;Deklarerar PortB som utgång
ser r16
out PortB, r16 ;Aktiverar pullup på utgång
ldi r16, 0b00000000
out DDRD, r16 ;Deklarerar PortD som ingång
ser r16
out PortD, r16 ;Aktiverar pullup på ingång
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, (1<<INT0)
out GIMSK, r16
ldi r16, $0F
out MCUCR, r16
sbi UCSRB, RXCIE
sei
Forever:
rjmp Forever
;***********************************************************;
Send:
ldi ZL, low(String*2)
ldi ZH, high(String*2)
Loop:
lpm r16, Z+
cpi r16, 0
breq Forever
rcall LightA
rjmp Loop
String:
.db "Arild",0
;***********************************************************;
LightA:
cpi r16, 'A'
brne LightB
ldi r17, 0x1F
out PortB, r17
rcall Delay
ldi r17, 0x24
out PortB, r17
rcall Delay
ldi r17, 0x44
out PortB, r17
rcall Delay
ldi r17, 0x24
out PortB, r17
rcall Delay
ldi r17, 0x1F
out PortB, r17
rcall Delay
ret
LightB:
osv...
Delay:
.....
Mitt problem är att det externa interuptet inte verkar fungera. Kan någon se om jag gör en jättemiss någonstans i min kod eller om jag helt enkelt tänker fel vid upp koppling. Ville inte lägga in hela koden här då det är för många rader men ni fattar idén.
Main:
.include "m8def.inc"
.org 0x0000
rjmp Reset
.org INT0addr
rjmp Send
;***********************************************************;
Reset:
ser r16
out DDRB, r16 ;Deklarerar PortB som utgång
ser r16
out PortB, r16 ;Aktiverar pullup på utgång
ldi r16, 0b00000000
out DDRD, r16 ;Deklarerar PortD som ingång
ser r16
out PortD, r16 ;Aktiverar pullup på ingång
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, (1<<INT0)
out GIMSK, r16
ldi r16, $0F
out MCUCR, r16
sbi UCSRB, RXCIE
sei
Forever:
rjmp Forever
;***********************************************************;
Send:
ldi ZL, low(String*2)
ldi ZH, high(String*2)
Loop:
lpm r16, Z+
cpi r16, 0
breq Forever
rcall LightA
rjmp Loop
String:
.db "Arild",0
;***********************************************************;
LightA:
cpi r16, 'A'
brne LightB
ldi r17, 0x1F
out PortB, r17
rcall Delay
ldi r17, 0x24
out PortB, r17
rcall Delay
ldi r17, 0x44
out PortB, r17
rcall Delay
ldi r17, 0x24
out PortB, r17
rcall Delay
ldi r17, 0x1F
out PortB, r17
rcall Delay
ret
LightB:
osv...
Delay:
.....
Mitt problem är att det externa interuptet inte verkar fungera. Kan någon se om jag gör en jättemiss någonstans i min kod eller om jag helt enkelt tänker fel vid upp koppling. Ville inte lägga in hela koden här då det är för många rader men ni fattar idén.
OK, tack för tipset med reti, skall prova det med en gång imorgon.
Angående tabellen så förstår jag vad du menar men besitter inte de programeringskunskaper som krävs för att upprätta en sådan. Provade mig fram och fick det att fungera i simulatorn med cpi.
Har du mgt tips på hur jag skulle börja för att börja bygga upp en sån tabell som du talar om?
Angående tabellen så förstår jag vad du menar men besitter inte de programeringskunskaper som krävs för att upprätta en sådan. Provade mig fram och fick det att fungera i simulatorn med cpi.
Har du mgt tips på hur jag skulle börja för att börja bygga upp en sån tabell som du talar om?
exemple:
När jag kollar lite närmare på din kod använder du "breq Forever" för att av sluta interupet vilket leder till att interupet inte enablas samt att du hoppar till baka från den adress du "kom" ifrån när interupet inträffade, så retur adressen ligger då kvar i stacken. Vilket inte är så bra då riskera över fylla stacken och då kommer du få massa knepiga fel, som exempel hoppa till baka till fel adress.
Hoppas exemplet och "förklaringen" var till någon hjälp ^^
Kod: Markera allt
test:
ldi ZL, BYTE1(test_string*2)
ldi ZH, BYTE2(test_string*2)
rcall print_string
for_ever:
rjmp for_ever
print_string:
lpm r16, Z+ ;Laddar första "bokstavenen"
cpi r16, 0 ;kollar om det är "slutet"
brne skip
ret
skip:
push ZL ;sparar pekaren så att den inte förstörs
push ZH
rcall print_char
pop ZH ;åter ställer pekaren
pop ZL
rjmp print_string
print_char:
;laddar pekare till tabel
ldi ZL, BYTE1(tabel*2) ;Sätter pekaren på tabellen
ldi ZH, BYTE2(tabel*2)
subi r16, 'a' ;Man kan "ta bort" de första elementen i tabellen efter som de inte används.
clr r17
;Flyttar pekarn så att den pekar på rätt "bokstav"
;Multipliserar r16 med 5 och lägger den till pekaren för att få rätt offset
;(addera fem gånger)
add ZL, r16
adc ZH, r17
add ZL, r16
adc ZH, r17
add ZL, r16
adc ZH, r17
add ZL, r16
adc ZH, r17
add ZL, r16
adc ZH, r17
lpm r16, Z+
out PORTB, r16
rcall delay
lpm r16, Z+
out PORTB, r16
rcall delay
lpm r16, Z+
out PORTB, r16
rcall delay
lpm r16, Z+
out PORTB, r16
rcall delay
lpm r16, Z+
out PORTB, r16
rcall delay
ret
tabel:
;a b
.db 0x7E,0x44,0x42,0x42,0x3c, 0x01,0x02,0x04,0x08,0x10;...osv
test_string:
.db "abc", 0
Hoppas exemplet och "förklaringen" var till någon hjälp ^^
subi r16, 'a' ;Man kan "ta bort" de första elemen
OK! Bra mycket smartare än ngt jag skulle kommit på. Har fått koden att fungera tillsammans med det jag redan skrivit. Har dock ngra frågetecken:
Säg att ascii värdet på a är 0x41 och första bokstaven är a, då blir ju r16=0
när man då adderar detta med ZL där också a ligger blir resultatet efter mult. med 5 a.
Men säg att andra bokstaven är b (ascii 0x42) => r16 = 1 ggr 5 =5
aha är det ngn slags räknare som på ngt sätt gör att man alltid pekar på rätt bokstav i tabellan (kanske var därför som du skrev det ovanför
Detta var till mycket stor hjälp, tack så mycket!
Jag försökte hänga med i registren men fattar inte riktigt vad denna rad gör. Jag förstår att den subtraherar det som finns i R16 med ascii-värdet på a, men varför och varför fungerar det oavsett vilken bokstav jag skriver?subi r16, 'a' ;Man kan "ta bort" de första elementen i tabellen efter som de inte används.
Säg att ascii värdet på a är 0x41 och första bokstaven är a, då blir ju r16=0
när man då adderar detta med ZL där också a ligger blir resultatet efter mult. med 5 a.
Men säg att andra bokstaven är b (ascii 0x42) => r16 = 1 ggr 5 =5
aha är det ngn slags räknare som på ngt sätt gör att man alltid pekar på rätt bokstav i tabellan (kanske var därför som du skrev det ovanför

Detta var till mycket stor hjälp, tack så mycket!
Kom bara att tänka på att mitt tankesätt ovan kanske är helt fel?
Om det skulle vara så, rätta mig gärna för jag vill förstå för att lära mig och inte bara kopiera in din smarta lösning
edit:
Märkte en sak till med (min) din kod, vi start pekar stackpeakren på adress 045F, efter ett varv (tillbaka till Forever) pekar den på 045D och efter ytterligare ett varv på 045B osv...
Dett trots att breq Forever är borta. Antar att detta inte är förväntat beteende men hittar inte hur jag skall komma till rätta med det.
Om det skulle vara så, rätta mig gärna för jag vill förstå för att lära mig och inte bara kopiera in din smarta lösning
edit:
Märkte en sak till med (min) din kod, vi start pekar stackpeakren på adress 045F, efter ett varv (tillbaka till Forever) pekar den på 045D och efter ytterligare ett varv på 045B osv...
Dett trots att breq Forever är borta. Antar att detta inte är förväntat beteende men hittar inte hur jag skall komma till rätta med det.
Näedå du tänker rätt. r16 används som offset till Z. D.v.s. adressen ligger i Z sedan plussas r16 på adressen för att peka på rätt position. Ungefär som index i BASIC "z(r16)". Om r16 = 0 så pekar den på första positionen i tabellen. Eftersom du inte använder ASCII tecken före 0x41 så är det onödigt att ha med dom i tabellen. Därav subtraheras r16 med 0x41 så du får 0 på första positionen där 'a' ligger.
Man kan säga att Z pekar på den position i minnet där tabellen börjar (position 0 i tabellen) och r16 läggs på som offset varefter du stegar igenom tabellen.
Adress_för_bokstav = Z + r16
Man kan säga att Z pekar på den position i minnet där tabellen börjar (position 0 i tabellen) och r16 läggs på som offset varefter du stegar igenom tabellen.
Adress_för_bokstav = Z + r16
Ditt problem med stacken beror troligt vis på att du inte använder rätt "hopp" instruktion, när du "avslutar" interupt. Använd alltid reti (om du inte är riktigt säker vad du gör) när du avslutar interupt.
Angående tabellen så har du förstått rätt, Varje "bokstav" behöver 5byte vilket är anledningen till att man multiplicerar r16 med 5.
Om du undra över någe mer så är det bara att säga till ^^
Angående tabellen så har du förstått rätt, Varje "bokstav" behöver 5byte vilket är anledningen till att man multiplicerar r16 med 5.
Om du undra över någe mer så är det bara att säga till ^^
Jätte tack för all hjälp hittills. Skall försöka kolla lite mer på varför stacken växer till veckan (är iväg på lite mini-semester). Hoppas jag kan finna orsaken så jag inte behöver störa dig om sådana små saker. Perfekt förklaring ovan, nu fattar jag precis vad koden gör och varför. Det gör ju saker och ting lite lättare. Återkommer när jag stöter på mer problem...
Jag löste problemet! Eller snarare ni löste det, men det räckte gott med era tips så fick jag till det. Hade inte riktigt fattat skillnaden mellan ret och reti i alla fall. Ändrade nu alla reti till ret utom det som avslutar interrupt rutinen och då pekade stackpekaren på samma adress efter ett "varv" som vid start.
Tack för den hjälp ni gett mig hittills!
Återkommer säkerligen när jag stöter på fler problem med mitt projekt.
God Jul!
Tack för den hjälp ni gett mig hittills!
Återkommer säkerligen när jag stöter på fler problem med mitt projekt.
God Jul!
Kanske en ganska så dum fråga men jag lyckas inte hitta svaret själv. Skulle ju iofs bara kunna koppla upp en krets och prova men då alla grejer jag beställt inte kommit ännu tänkte jag kolla med er först.
Undrar om det går att änvända PortB som output och samtidigt använda en extern kristall? På Atmega8:an som jag tänkt att använda så är ju Pb6 och Pb7 även de pinnar som en kristall skall kopplas in mellan. Samtidigt är jag inte riktigt säker på om jag behäver någon kristall (kanske kommer undan med den interna RC-oscillatorn). Hur som helst går det använda dessa båda pinnar till dubbla uppgifter (utgång samt inkoppling av kristall)?
Gott nytt år och god fortsättning!
Undrar om det går att änvända PortB som output och samtidigt använda en extern kristall? På Atmega8:an som jag tänkt att använda så är ju Pb6 och Pb7 även de pinnar som en kristall skall kopplas in mellan. Samtidigt är jag inte riktigt säker på om jag behäver någon kristall (kanske kommer undan med den interna RC-oscillatorn). Hur som helst går det använda dessa båda pinnar till dubbla uppgifter (utgång samt inkoppling av kristall)?
Gott nytt år och god fortsättning!
-
- EF Sponsor
- Inlägg: 2109
- Blev medlem: 27 augusti 2005, 20:57:58
- Ort: Borlänge