Tänkt ledsnurra som ställer till problem

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Tänkt ledsnurra som ställer till problem

Inlägg av Arild »

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.
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Du använder ret, istället för reti.
Skilnaden mella ret och reti är att reti enablar globala interupt som stängs av när ett interupt har inträfat.

Ett tips är att använda en tabel istället för "cpi", det spar program mine och så blir lite lättare att läsa "koden" ^^
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Inlägg av Arild »

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?
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

exemple:

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
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 ^^
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

subi r16, 'a' ;Man kan "ta bort" de första elemen

Inlägg av Arild »

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:
subi r16, 'a' ;Man kan "ta bort" de första elementen i tabellen efter som de inte används.
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?

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

Detta var till mycket stor hjälp, tack så mycket!
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Inlägg av Arild »

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.
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

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
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

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 ^^
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Inlägg av Arild »

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...
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Inlägg av Arild »

ang. att stacken växer tror jag att jag bytte ut alla ret mot reti (precis som du lärde mig tidigare ;-) ) Kanske kan hände att jag missade ngnstans. Får kolla en extra gång
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

'RET' är return på ett vanligt CALL
'RETI' är RETURN from INTERRUPT och ska alltså stå där man avslutar en interruptrutin, RESTEN SKA VARA 'RET'!!!
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Om du postar en ny "version" av coden kan jag "se" vad som är fel, och kan kanske ge tips. ^^
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Inlägg av Arild »

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!
Arild
Inlägg: 39
Blev medlem: 30 mars 2005, 13:12:02

Inlägg av Arild »

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!
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Från databladet sid 58, "When used as a clock pin, the pin can not be used as an I/O pin.".
Skriv svar