Delay rutin i AVR assembler

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sebbe
Inlägg: 120
Blev medlem: 11 februari 2004, 18:18:47

Delay rutin i AVR assembler

Inlägg av sebbe »

Hej!

jag sitter här på microprocessor lektionen i skolan och försöker göra en bra delay rutin men får f*n inte till det. jag har frågat lärarn men han är inte heller så duktig på det här så jag får inget vettigt svar

jag har kommit så här långt

Kod: Markera allt

DELAY:
	
	ldi Delay1, 100    ;ladda 100 till registret som jag har döpt till Delay1
	ldi Delay2, 100    ;ladda 100 till registret som jag har döpt till Delay2
	ldi Delay3, 100    ;ladda 100 till registret som jag har döpt till Delay3

DLY:

	dec Delay1 ;dra av ett från Delay1
	brne DLY  ;kolla om nån flagga är set (är inte riktigt säker på vad den gör) om delay1 är != 0 så hoppar sen till DLY anars gå vidare
	ldi Delay1, 100 ;ladda 100 till delay1 igen
	dec Delay2 ;dra av ett och hoppa tillbacka till DLY och börja om men delay1
	brne DLY ;kolla om delay2 är 0 anars hoppa till DLY
	ldi Delay2, 100 ;ladda 100 till delay2
	dec Delay3 ;dra av ett från delay3
	brne DLY kolla om delay3 är 0
	ret ;gå tillbacka
koden räknar altså först till 100 100gånger och sedan räknar det 100 gånger
(hoppas ni fattar ;))

som jag har räknat det så borde det bli rätt om man kör processorn i 1mhz och vill ha en delay på 1s eftersom delayen blir 100*100*100 = 1000000
men delayen tar mycke längre tid än 1sekund

hoppas ni förstår av jag menar ;)
tack på förhand

mvh
Sebastian
Användarvisningsbild
GrodanB
Inlägg: 245
Blev medlem: 11 februari 2006, 16:46:25
Ort: Göteborg
Kontakt:

Inlägg av GrodanB »

Varje instruktion ingår i delayen...

Om en intruktion tar 1 cykel så skall du göra 1 000 000 instruktioner för att få en delay på 1s.

Så om du behöver 2 instruktioner för att räkna ner en räknare skall du ha 50 i räknaren...

Decrement
Test and Jump_if_done

Så du måste kolla hur många instruktioner du kör under en körning för att veta hur länge den väntar...

Men detta är inte en bra metod... har du inte en räknare eller timer du skulle kunna använda istället?
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Du skall räkna hur många klockcykler du fördröjer, då blir det rätt.
Din kod tar nämligen mer än 1000000 cykler. Du gör ju betydligt mer än att bara räkna ned registren.

Mvh
Nisse
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Med 1mhz kommer det att ta MYCKET längre tid, du kanske menar 1MHz?
(m = milli = 1/1000, M = Mega = 1000000)

Du kanske glömmer att 'dec', 'brne' och 'ldi' tar sin egen tid. Då jag inte håller på med AVR vet jag inte HUR lång tid men med lite logik kommer första steg att ta 3 CPU-klock:

Kod: Markera allt

1 clk	dec Delay1 ;dra av ett från Delay1
1/2 clk	brne DLY  ;kolla om nån flagga är set, om delay1 är != 0 så hoppar sen till DLY annars gå vidare
BRNE = Branch if Not Equal, det betyder att den kollar Ackumulatorns Z-flagga då om man jämför 2 tal vid att subtrahera dom från varandra och de är lika blir resultatet ju noll vilket setter Zero-flaggan.

Så enl. min uträkning bör ovanstående enkla steg ta 3*99 + 2 CPU-klock = 299 CPU-klock.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Sebbe, varför har du labels som heter t.ex "DLY" men du saknar stor
bokstav i början på meningar och (som Icecap noterade) i "mhz" !?

Har inte utvecklingsmiljön någon "stopwatch" funktion så att du kan
ta tid på rutinen ?

Sen får du nog läsa på lite generellt om hur processorn fungerar.
Du måste självklart räkna *alla* instruktioner... :-)

Min gissning är att läraren nog ser problemet man kanske inte *vill* svara... :-)
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Här är ett bra program som jag brukar använda:
http://www.home.unix-ag.org/tjabo/avr/AVRdelayloop.html

Mvh
Nisse
sebbe
Inlägg: 120
Blev medlem: 11 februari 2004, 18:18:47

Inlägg av sebbe »

Tack för alla bra svar :D

sodjan: Hehe nä det där med svenska är jag inte så bra på ;)
Det var en miss med M:et självklart ska det vara ett stort M


Kod: Markera allt

DELAY:
	
	ldi Delay1, 100
	ldi Delay2, 100
	ldi Delay3,100

DLY:

	dec Delay1    ;(1clk * 100) *100*100
	brne DLY       ;+ (0.5 * 100)*100*100
	ldi Delay1, 100 ; +1clk *100*100
	dec Delay2 
	brne DLY   
	ldi Delay2, 100  ; +1clk *100
	dec Delay3 
	brne DLY 
	ret 
totalt 1510100clk ~ 1,5s har jag räknat rätt då ?

då får jag ta och räkna lite på det där och se om jag får till det

tack för hjälpen
Sebastian
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Varför har du inte räknat cykler på alla instruktioner ?
Sen (jag kan inte AVR så bra) så rent spontant så skulle jag
förvänta att en "branch" tar lite längre tid en än DEC, men det
kasnke inte är så... :-)
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

En instruktion tar ALDRIG en halv CPU-klock!!!!

dec Delay1 ;(1clk * 100) *100*100
brne DLY ;+ (0.5 * 100)*100*100

Hur ska en instruktion som "alltid" tar minst 2 cyklar plötsligt ta en halv? Speciellt när en halv inte kan göras?
Användarvisningsbild
maha
EF Sponsor
Inlägg: 1685
Blev medlem: 22 november 2005, 09:47:02
Ort: Jakobstad, Finland

Inlägg av maha »

sebbe har helt enkelt missuppfattat databladet. Det står "1 / 2", alltså "1 eller 2" klockcykler, inte "0,5" klockcykler.

2 klockcykel vid TRUE och 1 klockcykel vid FALSE.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Som jag gissade...
Och det gör timingen lite mer "spännande" att beräkna eftersom tiderna
varierar... :-)
Användarvisningsbild
maha
EF Sponsor
Inlägg: 1685
Blev medlem: 22 november 2005, 09:47:02
Ort: Jakobstad, Finland

Inlägg av maha »

Tja det går ju att sätta in en NOP i början på FALSE-delen så blir det ju lika.

Edit: Men jag håller med, lite mer spännande blir det absolut.
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Lite allmänna tips om delayer:
Har man inte tillgång till en timer så kan man skriva en nästlad for-loop som du gjort.
Har microprocessorn en inbyggd timer så är det bättre att använda den. Den går dessutom att användas på (minst) två sätt:
Variant 1:
Låt timern räkna fritt och slå runt när den når maxvärde.
En fördröjning på n timerticks görs såhär (pseudo):
*pTMR_REG = 0; //nollställ räknarens register
while(pTMR_REG < n);

Denna variant tillåter att andra avbrott körs under tiden while-loopen väntar, utan att delay-tiden förlängs.

Variant 2, lite mer avancerat:
Använd avbrott och låt tilltänkt händelse ske i avbrottsrutinen. Ger bra precision på själva händelsen.
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Exemple på en delay, som anväder en "24bitar" variabel istället för nästlad loopar.

Kod: Markera allt


#define delay 200000
	ldi r16, BYTE1(delay)
	ldi r17, BYTE2(delay)
	ldi r18, BYTE3(delay)


loop:
	subi r16, 1		//1
	sbci r17, 0		//1
	sbci r18, 0		//1
	brne	loop		//2
Användarvisningsbild
bengt-re
EF Sponsor
Inlägg: 4829
Blev medlem: 4 april 2005, 16:18:59
Skype: bengt-re
Ort: Söder om söder
Kontakt:

Inlägg av bengt-re »

Variant 2 enligt Ojsan är bra, men har ett litet problem med PICár iaf och troligen även på AVR eftersom man inte vet om det är en en eller två cykels instruktion som körs när avbrottet kommer och detta ger ett jitter på 1 cykel - oftast inget problem, men vid videogenerering så stör det och gör linjerna taggiga. Går lösa genom att läsa av timerreg och om denna har slagit om en till så lägg till en NOP. Det ökar latencyn med 3 cykler, men tar bort jittret iaf. Kör man med prescaler så blir det rörigare, men oftast så är ett 1 cykels jitter inget att bry sig om, men som sagt vid videogrnerering så slår det 0,2/48 av en rad det är tillräckligt för att vara störande iaf.
Skriv svar