AVR Assembler Övningsexempel 4 (5 / 9 steg)
Steg 5: makron
Makron är mycket lik de subrutiner som vi diskuterade i sista steget förutom att de tar "argument". Med andra ord, är makron i huvudsak "funktioner". I själva verket är den största skillnaden mellan assembler och alla "högre nivå" språk som människor använder att någon har sammanställt ett gäng av ofta använda funktioner i makron. Vi kommer här att använda makron för att uppnå samma ändamål, med en viktig skillnad, våra makron kommer att vara precis där i koden för oss att se och ändra som vi gillar.
Vår filosofi i dessa tutorials är att bli av med alla "svarta lådor" och ta reda på vad som händer bakom kulisserna. Vi vill inte att något händer om vi inte vet om det och berättade den att göra det. Det är därför det kallas "Befalla lina assembler programmering". Vi använder kommandoraden istället för några Java baserad IDE som arduino en (faktiskt, jag använder kommandoraden även med arduino programmering). Ett java ide fönster är som en svart låda till mig. Jag kan aldrig vara helt säker på att det inte finns antaganden som görs i kulisserna när du kommunicerar mina instruktioner till mikrokontroller och gillar jag inte. Jag också inte gillar hur uppsvälld och processorn konsumerar java är. I själva verket, är det också varför vi använder "avra" i stället för ATmel assembler IDE. Jag inser att när du är en expert coder, eller en nybörjare, du redan vet, eller du inte bryr dig, vad som händer bakom kulisserna, men här vi kommer att offra bekvämligheten för att undvika svart-boxness och fetma.
Nu vad är makron? Tja kanske du har märkt när man läser genom program som vi använder "delay" subrutinen överallt. Inte bara från inuti main, men från inuti andra subrutiner. Detta leder till spaghetti och vi gillar inte spagetti. (Rita linjer mellan varje subrutin kodblock i diagrammet när en blockera samtal en annan och du kommer snabbt se att "delay" subrutinen orsakar diagrammet se ut som en skål med spaghetti)
Här är hur "delay" brukar kallas:
LDI millisekunder, 50; fördröjning (upp till 250 ms)
rcall fördröjning
Du ser att vi först ange variabel (dvs arbeta register) "millisekunder" med värdet 25 och sedan vi kallar subrutinen "fördröjning". Subrutinen kommer att försena 25 ms och sedan tillbaka. Bortsett från spaghetti är ett annat problem med detta sätt att göra saker som om vi glömmer att ange värdet för millisekunder omedelbart innan vi kallar subrutinen vi har ingen aning vad förseningen blir. Det blir oavsett värde lägger vi på millisekunder någon annanstans. Detta är ett riskabelt sätt att skriva kod. Så för att lösa allt detta vi helt enkelt skriva en "makro". Här ' tis:
.Macro fördröjning
CLR svämmar över
LDI millisekunder
sec_count:
cpse flödar över, millisekunder
rjmp sec_count
.endmacro
Det är ett assembler direktiv att vi lägger överst i vårt program att gör samma försena saker vi hade i vår försening subrutin, det kallas fördröjning, men den har den viktiga skillnaden att vi satt de variabel "millisekunder" inuti! Symbolen (et-tecken noll) står för vad vi placera bredvid fördröjning när vi kallar den. Här är hur vi kallar det sedan. Om vi ville ha en fördröjning av 25ms någonstans i vårt program skriva vi helt enkelt
dröjsmål 25
och assembler kommer att ersätta den i makrot med 25 och vi får vår försening av 25 ms.
Varför kan du väl skriva makron som har många fler argument om du vill. I så fall skulle du använda och och så vidare. När du anropar funktionen skulle måste du ange alla argumenten motsvarar dessa @ saker i makrot.
Jag tror nu kan du se hur de gjorde kommandot Arduino språk "delay(20)" rätt?
Övning 2: lägga till ett makro i programmet och ändra alla subrutiner så att de kallar makron i stället för en försening subrutin. (Obs! I en av incidenterna måste söka runt för att räkna ut vad förseningen är tänkt för att vara! Jag lämnade medvetet ut ldi millisekunder i så fall)