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
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
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.
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:
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.
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å...
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.
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.