AVR Assembler Övningsexempel 4 (6 / 9 steg)

Steg 6: Pekare och uppslagstabeller



Någon av er som har erfarenhet av att använda C eller C++ redan har erfarenhet av pekare. Vi kommer att använda samma sak här i samband med "uppslagstabeller".

Uppslagstabeller är ett annat sätt att compactifying vår kod att göra det kortare, elegantare och lättare att förstå.

Först kan skriva koden och sedan kommer vi att förklara vad som händer. Först, längst upp i vårt program får vi ett avsnitt som heter "siffror:" följt av vissa "DB" assembler direktiv. Dessa direktiv "definiera byte" och vad de gör är de rum de byte sekventiellt i ett visst avsnitt "Programminne" definieras av etikettnumren. Så att när hex koden är laddad på mikrokontroller, innehåller en viss del av flash-minne som lagrar alla program instruktionerna dessa byte en efter den andra i ordningen.

nummer:
DB 0b01111111, 0b11011110, 0b01011110, 0b11010010
DB 0b01010010, 0b11000000

Då kan vi faktiskt få dessa siffror när vi vill dem eftersom de alltid kommer att vara placerad på vissa angivna programmet minnesplatser. Kom ihåg hur vi behandlat avbrott? Vi placerade en instruktion på exakt 0x0020 i programminnet. Vi visste att om en timer overflow avbryta uppstod cpu skulle kontrollera den exakta platsen och utföra oavsett kommando vi lagt där. Bra uppslagstabeller fungerar på ett mycket liknande sätt.

Vi kommer att skriva om våra "dice:" märkt subrutin, som är den som berättar mikrokontroller vilket stift att slå på att få vilket nummer på en dö, så att i stället för en lång och ful i koden, den kan använda en loop och göra saker helt enkelt. Här är den nya koden:

Dice:
LDI ZH, high(2*numbers)
LDI ZL, low(2*numbers)
LDI temp, 0
Kolla:
inkl härda; Increment temp
CP die1, temp; Jämför die1 med 1
brne PC + 2. om inte lika inte ställa in die1
LPM die1, Z; Ladda die1 med nummer 1
CP die2, temp; Jämför die2 med 1
brne PC + 2. om inte lika inte ställa in die2
LPM die2, Z; Ladda die2 med nummer 1
CPI temp, 6. om temp klar 6 vi
breq PC + 3. om lika går till ret
adiw ZL, 1; öka till nästa nummer
rjmp kontroll. i uppslagstabellen
ser härda; Återställ temp
ret

Du ser att det är mycket kortare. I själva verket, när du befinner dig är upprepa samma uppsättning instruktioner om och om igen i en subrutin och enda som är olika varje gång att något visst antal är olika, det är ett perfekt tillfälle att använda en uppslagstabell. I de fall där du vill använda en "ögla" eller en "switch-fall" rutin i C eller några andra språk, som är en bra tid att använda en uppslagstabell i assembler.

Uppslagstabeller har rykte om sig att vara komplicerat men jag tror inte det är välförtjänt. Jag ska försöka att förklara det på ett enkelt sätt här.

Låt oss börja med atmega328p minne karta. Det finns tre olika typer av ledigt minne för att lagra saker. Den "programminne" som lagrar vårt program, den "SRAM dataminne" som innehåller alla de register som vi använder som allmänna syftet arbetar register, input/output portar, och alla de journaler som vi använder för att växla lite och kontroll som det är gjort, och slutligen "EEPROM" minne, som vi kommer att införa i en senare handledning (om jag förra det lång) och används för att lagra information som inte kommer att försvinna när vi slår av strömmen. Mycket användbart om du gör ett spel och du vill lagra somebodies poäng tills nästa gång de spelar!

Vi vet att varje byte av en viss typ av minne har en adress. Till exempel den första byten i koden vi utför är på 0x0000 och timer overflow avbrottshanterare är på 0x0020, etc. Du kommer att märka att eftersom vi har mer än 256 byte minne för i våra programminne utrymme inte kan vi bara använda adresser 0x00 upp till 0xFF. I själva verket har vi 32k flashminne i programmet minnesutrymme. Detta innebär att vi behöver adresser från 0x0000 upp till 0x7FFF.

Antag nu, att vi vill läsa vad som är på en viss adress i minnet? Till exempel när processorn blir ett bräddavlopp avbrott det går till 0x0020 och utför den instruktion som vi placerat där. Vad händer om vi vill placera instruktioner eller data eller vad på vissa specifika adress i programminne och sedan använda det i vårt program? Vi kan, förutom att våra generella registrerar endast rymmer 8 bitar (1 byte) mellan 0x00 och 0xFF, och som vi har sett, en adress har 2 byte att skriva ner (mellan 0x0000 och 0x7FFF). Så finns det inte tillräckligt med utrymme i ett allmänt register (dvs. en variabel som r16) att hålla en programminne adress. Vi kan inte säga "ldi r16, 0b0000000000000010" till exempel, eftersom R16 är inte tillräckligt stor. Så om vi har något sätt att lagra fullständiga adress hur kan vi gå dit under programmet? Vi kan bara plocka upp telefonen, ringa cpu och säga "kan du gå och köra vad vi lagras på 0x2a7f vänligen" du måste ha denna adress i ett r16 eller något och sedan "mov" det eller "out" det därifrån.

Så är här vad den ATmel folken har gjort för att lösa detta dilemma. De har dubbla utlovat några av våra generella register. Särskilt om man tittar på tabellen 7-2 på sidan 12 i databladet, kan du se hur de generella register är organiserade. Den registren r26, r27, r28, r29, r30 och r31 kan också kombineras till par kallas X, Y och Z. Så att X är r26 och r27 tillsammans, Y är r28 och r29 tillsammans, och Z är r30 och r31 tillsammans. Så om vi tar Z till exempel först hälften av det är r30 och andra hälften av det är r31. Så om vi vill lagra en programminne adress lagrar vi bara hälften av det i r30 och den andra hälften av det i r31 och sedan vi berätta cpu att leta upp Z om vi vill prata om hela tillsammans. De har genomfört två instruktioner som gör detta. Först är spm som står för "Store programminne" och den andra är lpm som står för "Load programminne". Så nu om vi vill få vad någonsin instruktion eller data lagras på minnesadress 0x24c8 till exempel, vi skulle sätta den adressen i r30 och r31 och sedan när vi vill få data skulle vi bara lpm det till en variabel genom att göra

LPM r16, Z

som kommer att gå till minnesadress Z ta oavsett data vi lagt där och sticka den i r16. Häftiga med detta är att om vi lägger till 1 till Z med hjälp

adiw Z, 1

då kommer Z nu "peka" nästa minnesadress efter den första. Så att om vi håller oss en hel lista med siffror i minnet en efter den andra vi kan gå igenom dem genom uppräkning Z.

Hur vi använda detta i vårt program?

Tja, eftersom varje nummer på tärningen visas genom att slå på och av olika hamnar som PC2 och PB5 vi lagra bara numret som gör detta för varje nummer på tärningen. Till exempel om vi "ut" 0b11010010 till PortC det kommer att ställa PC0 till 0, PB1 1, etc och slå på de motsvarande lysdioderna för att ge oss vårt nummer på tärningen. I detta fall nummer 4.

Så vi kommer att använda en "uppslagstabell" kallas "siffror:" att lagra alla dessa olika die konfigurationer och förenkla vår kod.

Jag tror att om du läser koden ovan, och leta upp olika instruktionerna i bruksanvisningen, kan du lätt räkna ut hur det fungerar. Bara konstig del är den första biten där vi initiera pekaren Z.

LDI ZH, high(2*numbers)
LDI ZL, low(2*numbers)

Vad detta innebär är initialiserar pekaren Z att peka på vår lista som heter "nummer". Anledningen till de 2 gånger framför är att vi vill ha adressen till "nummer" skiftat till vänster ett utrymme (det är vilka tider av två gör att binära tal). Detta lämnar gratis längst till höger lite (den minst signifikanta biten) som sedan används för att avgöra vilka byte programminne hänvisar vi till. Detta beror på att programmet minne är 2 byte (16 bitar) brett. Så till exempel i våra uppslagstabellen har vi två första siffror som
DB 0b01111111, 0b11011110

Eftersom programmet minnesutrymme är 16 bitar bred båda dessa nummer faktiskt kommer att sitta på samma programminne adress så det sättet ta vi den första eller den andra är därför vi behöver "times av 2" eller vänster SKIFT bitar. När den "minst signifikanta biten" av Z är 0 den pekar till den första av vår lista: 0b01111111, och när den minst signifikanta biten av Z är en 1 den kommer att peka på den andra ett på vår lista: 0b11011110.

Som ni kan se, ändras att lägga till 1 till Z den minst signifikanta bit från 0 till 1 och sedan lägga till 1 till Z igen steg Program minnen adress och LSB går tillbaka till en nolla. Så ser du att det fungerar bra för att plocka ut våra hela lista över lagrade nummer ett i taget genom att helt enkelt öka Z.

Märker att när vi flytta adressen till "nummer" lämnat genom att multiplicera med 2 till fri upp den minst signifikanta biten att använda för att välja den första eller andra byten lagras på den adressen vi förlorar den "mest signifikanta biten" i adressen. Detta innebär att vi bara kan lagra våra lookup tabelldata i adresser där den mest signifikanta biten spelar ingen roll - dvs alla våra namngiven data kommer att ha den samma mest signifikanta biten. Detta innebär att vår adress är effektivt 15 bitar lång. 2 ^ 15 är 32768 olika adresser tillgängliga för våra lagrade data. Vi ska titta på detta mer i detalj i nästa tutorial så oroa dig inte om det är lite förvirrande på denna punkt.

Nu vet du hur man använder uppslagstabeller och X, Y och Z pekare för att förenkla skrivandet kod.

Låt oss nu ge det fullständiga programmet med dessa innovationer ingår.

Se Steg
Relaterade Ämnen

AVR Assembler Övningsexempel 7

Välkommen till Övningsexempel 7!Idag vi första visar hur du rensar en knappsats och sedan visar hur du använder Analog ingång hamnarna för att kommunicera med knappsatsen.Vi kommer att göra med avbrott och en enda tråd som indata. Vi kommer tråd knap...

AVR Assembler Övningsexempel 9

Välkommen till Övningsexempel 9.Idag kommer vi att visa hur du kan styra både 7-segment display och en 4-siffrig display med våra ATmega328P och AVR assembler kod. I samband med detta får vi ta omvägar till hur du använder stacken för att minska anta...

AVR Assembler handledning 11

Välkommen till handledning 11!I den här korta guiden kommer vi slutligen att bygga den första delen av vårt sista projekt.Det första du bör göra är att gå till det allra sista steget i denna tutorial och titta på videon. Sedan komma tillbaka hit. [pa...

AVR Assembler Tutorial 1

Jag har beslutat att skriva en serie tutorials om hur man skriver assembler program för den Atmega328p som är mikrokontroller används i Arduino. Om människor förblir intresserad fortsätter jag att lägga ut en en vecka eller så tills jag får slut på l...

AVR Assembler handledning 6

Välkommen till Tutorial 6!Dagens handledning kommer att vara kort där vi kommer att utveckla en enkel metod att kommunicera data mellan en atmega328p och en med två portar ansluta dem. Vi kommer ta sedan tärningarna rullen från läraren 4 och registre...

AVR Assembler handledning 8

Välkommen till Tutorial 8!I denna kort tutorial ska vi ta lite av en skenmanöver från att införa nya aspekter av assembler programmering att visa hur man flytta våra prototyper komponenter till ett separat "tryckta" kretskort. Anledningen är att...

AVR Assembler Tutorial 2

Denna handledning är en fortsättning på "AVR Assembler Tutorial 1"Om du inte har gått igenom Tutorial 1 bör du sluta nu och göra att man först.I den här guiden kommer vi fortsätta vår studie av assembler programmering av den atmega328p som använ...

AVR Assembler handledning 10

Välkommen till handledning 10!Ledsen att det tog så lång tid för att få denna nästa avbetalning ut men detta är en ganska hektisk tid på året. I alla fall, är här det!Vi har kommit långt och du förmodligen redan är kompetenta nog att skriva många int...

AVR Assembler handledning 5

Idag kommer vi att ta en närmare titt på de olika minnesplatserna i Atmega328p mikrokontroller och se om vi bättre kan förstå hur saker lagras, där de lagras och hur pekare och uppslagstabeller fungerar.Handledningen kommer att delas upp i två delar....

AVR Assembler handledning 3

Välkommen till tutorial nummer 3!Innan vi börjar vill jag göra en filosofisk punkt. Inte vara rädd för att experimentera med kretsar och den kod som vi konstruerar i dessa tutorials. Ändra sladdar runt, lägga till nya komponenter, ta komponenter ut,...

Utveckling styrelsen för Attiny84 mikrokontroller

Detta är en utveckling styrelse för Attiny84 mikrokontroller. Tha Attiny84 chip har 11 pins adresserbara med Arduino IDE, 8k flashminne för lagring av program och 512 byte ram tillgängligt för variablerna stack och program.En funktion av den Attiny84...

Hur man ladda program till en Arduino UNO från Atmel Studio 7

I denna korta Instructable kommer vi att lära sig att ladda ett program till en Arduino UNO ombord med Atmel Studio istället för Arduino IDE. Detta är användbart när du behöver utveckla ett program med fler advance funktioner eller på ett annat språk...

MRETV - Video, ljud och mycket mer från en standard Arduino!

MRETV - Video, ljud och mycket mer från en standard Arduino!Nu uppdaterad för Arduino 1.6.6 November 2015!Använd endast två resistorer och två dioder för att generera full skärm video. Text 47 x 29 8 x 8 tecken, dubbla vertikala upplösningen (47 x 57...

Enklaste AVR parallell port programmerare

Hej, är detta min första instructables, som handlar om avr programmerare. Detta är den enklaste krets med vilka AVR (Atmega serie, Attiny serien, AT90S serien) microcontrollers kan programmeras. Det finns en hel del programmerare, men detta är enkel...

Älskling, jag krympte Arduino: flytta från Arduino till ATtiny och skriva din kod i ren AVR-C

Arduino är en stor hård- och mjukvaruplattform, men med alla dess funktioner är det också lite uppsvälld och ofta behöver du bara en liten del av alla funktioner. Projektet kräver ibland för att ha mindre och billigare enheter. Vad du behöver är ATti...

Mitt svar på WS2811 med en AVR sak

första off - vill sägaBra om du Alan Burlison.Detta är inte menat att uppsamlare du på något sätt. Din kod gjorde det det måste göra. Stor framgång. Min första reaktion i en forum kommentar var faktiskt riktat mot folk som när det gäller icke-arbetan...

Fattig mans AVR speldosa

detta är en enkel AVR speldosa, kostar ca 10$ för att bygga.DISCLAIMER: Detta projekt är vad man skulle kalla en SMOP, "en enkel fråga om programmering". Det innebär att det är av trivial komplexitet men långa... så om du kan tolerera tristess i...

Montering av Dragon Rider 500 för användning med AVR Dragon

inte länge sedan företaget Atmel kom ut med ett bra verktyg för användning med AVR microcontrollers kallas AVR Dragon. Denna lilla USB-enhet ger proffs och amatörer både förmågan att använda: I System programmering (ISP), JTAG, felsöka tråd och hög s...

16-nyckel knappsatsen avkodning med en AVR MCU

detta instructable visar dig hur gränssnittet en 16-nyckel knappsats till din AVR microcontroller och läsa nyckeln när en tangent är nedtryckt. Jag ska presentera knappsatsen först, sedan 74HC922 16-nyckel dekodern IC som pin-saving mekanism, sedan s...