AVR Assembler Övningsexempel 9 (5 / 7 steg)
Steg 5: Tryck 'n Pop
Det finns endast ett fåtal "allmänna ändamål registrerar" som vi har till vårt förfogande och när de används finns inte mer. Så det är bra namnge programmering praxis att bara använda dem för ett par variabler som används som tillfällig lagring som du behöver för att läsa från och skriva till, portar och SRAM med, eller annat som du kommer att behöva i subrutiner överallt och så du dem. Så vad jag har gjort, nu när vi har initierats och lära sig att använda stacken, är att gå igenom koden och hitta de namngivna generella journaler som används inom en enda subrutin eller avbrott och ingen annanstans i koden och ersätta dem med en av våra temp register och en push och pop till stacken. I själva verket, om du tittar på koden skriven för mindre microcontrollers, eller om du går tillbaka i tiden till när alla marker var mindre, ser du endast ett par generella register som hade att användas till allt, så du kunde inte bara lagra ett värde där och lämna den ensam sedan du var säker på att behöva detta register för andra saker. Så ser du pushin' och en Poppin ' överallt i koden. Kanske bör jag har heter våra temp generella register AX och BX som en respektfull kudos till de svunna dagarna.
Ett exempel kommer att göra detta mer tydligt.
Tillkännagivande att komplett avbrott ADC_int använder vi en generell i våra Analog till Digital konvertering registrerar att namnet vi har buttonH som vi brukade ladda värdet av ADCH och jämföra det med våra uppslagstabell för analog till knapp tryck på omvandlingar. Vi använder endast buttonH registret inom ADC_int subrutinen och ingen annanstans. Så istället kommer vi att använda våra variabel temp2 som vi använder som en tillfällig variabel som vi kan använda inom någon viss subrutin och dess värde inte kommer att påverka någonting utanför denna subrutin (dvs det värde vi ge det i ADC_int inte användas någon annanstans).
Ett annat exempel är i vår försening makro. Vi har ett register som vi har döpt "millisekunder" som innehåller våra fördröjning i millisekunder. I detta fall är det i ett makro och vi minns att vägs makro arbete är att assembler placerar hela koden till plats i programmet där det kallas. I det här fallet vill vi bli av med variabeln "millisekunder" och ersätta den med en av våra tillfälliga variabler. I detta fall kommer att jag göra det lite annorlunda för att visa dig hur även om värdet av variabeln kommer att behövas någon annanstans kan vi fortfarande använda det med hjälp av stacken. Så i stället för millisekunder använder vi "temp" och för att vi inte skruva upp andra saker som också används värdet för temp vi helt enkelt börjar makrot "delay" genom att "trycka" temp på stacken, då vi använder det i stället för millisekunder, och sedan i slutet av makrot vi "pop" sitt tidigare värde tillbaka från stacken.
Resultatet är att vi har "lånat" temp och temp2 för tillfälligt bruk och sedan återställt dem till deras tidigare värden när vi är färdiga.
Här är den ADC_int avbrott rutinen efter att ha gjort denna förändring:
ADC_int:
Tryck temp; rädda temp eftersom vi ändra den här
push temp2; Spara temp2
LDS temp2, ADCH; Ladda knapptryckning
LDI ZH,high(2*numbers)
LDI ZL,low(2*numbers)
CPI temp2, 0
breq avkastning. om buller utlösare inte ändrar 7segnumber
setkey:
LPM temp, Z +; Ladda från tabellen och bokföra ökning
CLC
CP temp2, temp; jämföra knapptryckning med tabellen
brlo PC + 4. om ADCH är lägre, försök igen
LPM 7segnumber, Z; annars ladda keyvalue tabell
Inc siffran. öka det fyrsiffriga numret
rjmp avkastning. och retur
adiw ZH:ZL, 1. Increment Z
rjmp setkey; och gå tillbaka till toppen
återkomst:
pop temp2; återställa temp2
pop härda; återställa temp
Reti
Observera att hur stacken fungerar är att först på är sist avstängd. Precis som en bunt med papper. Ser du att i våra två första raderna vi trycka på värdet av temp på stacken, då vi driva temp2 på stacken, då vi använder dem i subrutinen för andra saker, och slutligen vi återställa dem till deras tidigare värden igen på första poppar temp2 off (eftersom det var den sista som sköt på det är överst i stacken och kommer att vara den första vi pop backa) och då poppar Temp.
Så hädanefter kommer vi alltid att använda denna metod. Den enda gången vi faktiskt kommer att utse ett register för något annat än en temp variabel är när vi behöver det överallt. Registret kallas "svämmar över" är exempelvis en som vi använder på flera olika ställen i programmet och så vill vi ge den ett namn. Naturligtvis kan vi fortfarande använda det så vi har gjort med temp och temp2 eftersom vi skulle återställa det värdet när vi är klar. Men det skulle spaghettify saker för mycket. De är namngivna av en anledning och vi har temp och temp2 redan utsett för det jobbet.