AVR Assembler handledning 10 (9 / 10 steg)

Steg 9: Hur fungerar på TWI avbryta?



Du bör först gå till nästa steg och hämta den final koden och sätta ihop det så att du kan använda det i det här steget (jag gillar att hålla den final koden och video i det sista steget för dem som vill bara hoppa över alla mitt babblande och bara köra koden.)

Det tolerabla VECKOINTAGET är förvirrande först eftersom det fungerar annorlunda än andra avbrott. Vanligtvis när ett avbrott inträffar och den motsvarande avbrottshanterare avrättas, jag flaggan i SREG automatiskt anges till 0 så att globala avbrott är inaktiverade, sen när det "RETI" utförs för att återgå från avbrottet, jag flaggan i SREG anges automatiskt 1 igen till re-möjliggöra globala avbrott och även enskilda avbrott flagg motsvarar avbrottet (dvs. biten i avstämningsregister för att avbryta) rensas så att den systemet svarar igen på den typen av avbrott (se status registrera beskrivning på sidan 11). Om vi tillät avbrott kvar på inuti ett avbrott skulle vi få "kapslade avbrott". Du kan göra detta genom faktiskt att aktivera dem inuti din avbrott rutin men du skulle inte normalt vill göra detta eftersom ett annat anrop till samma avbrott skulle då kasta ut dig från avbrott bara för att ange det igen på toppen.

Övning 3: Prova det! Aktivera global avbrott i början av din TWI rutin, då någonstans inuti uppsättning TWIE bet i TWCR registret och se vad som händer nästa gång flaggan TWINT har angetts.

Detta är dock inte hur på TWI avbryta fungerar! TWINT är avbrott flagga. I TWI inte återstår det in under avbrottshanterare, ändrar hela tiden. Det är därför det tolerabla VECKOINTAGET behöver använda flaggan avbrott för att kommunicera. Så vi inte kan bara lämna det på. I stället vi inaktivera avbrott med TWIE = 0 så att Processorn inte kasta ut oss tillbaka till avbrottsvektorn när TWINT ändras tillbaka till en 1. Detta kan ändå, fortfarande verka förvirrande så vi kommer att diskutera det i samband med vår kod. Exakt när är TWINT = 1 och då är TWINT = 0 i vår TWI rutin?

Låt oss lista ut.

Istället för att hoppa fram och tillbaka i databladet till räkna ut vad som pågår. Låt oss använda våra dice rulle och Visa. Då vi kommer att vara helt tydlig med vad bitarna anges och när.

Starta genom att lägga till följande definition till toppen av dice rulle koden:

def test = r23

Nu gå ner på tw_transmit rutin och rätt på toppen av det, när datorn först träder subrutinen, sätta följande rad

LDS test, SREG

Slutligen, gå till de två platserna i koden där vi överföra uppgifterna till displayen. Den andra en där vi överför den låga byten, ersätta dicetotal med test. När vi trycker på knappen, skickas nu innehållet i registret SREG, när vi först kom in subrutin, till displayen.

Nu, när vi monterar detta och kör det, finner vi att en 0000 visar upp på displayen. Detta innebär att jag flagga SREG inaktiveras som det ska vara eftersom vi inte aktiverar global avbrott i vår dice rulle.

Nu ändra koden så att testa laddar TWCR i stället för SREG och visa innehållet i TWCR.

Vi finner att och att TWEN flagga är enda på i TWCR. Vilket betyder att det tolerabla VECKOINTAGET aktiveras som det också ska vara eftersom vi använder det tolerabla VECKOINTAGET.

Nu kan flytta våra test linje till en annan plats. Flytta ner det till precis efter vi satt TWCR för första gången. Detta är när vi skickar startvillkoret. Resultatet är en 36 på vår bildskärm. Detta innebär att TWCR är 0b00100100.

TWCR = (TWINT, TWEA, TWSTA, TWSTO, TWWC, TWEN, -, TWIE) = (0,0,1,0,0,1,0,0)

Så är det TWSTA lite på som det ska vara eftersom vi precis laddat startvillkoret, och TWEN är på som det också ska vara. Men titta! I föregående rad vi lastade TWINT = 1 i TWCR register och när vi omedelbart kopieras registret och tittade på det finner vi att TWINT är 0! Varför är det? Du ser att "Ange TWINT = 1" gör något annat än bara ställa in det lite i TWCR lika med ett. Om du tittar längst ner på sidan 17 där de beskriver överföring en startvillkoret kommer du se att de säger, "TWINT måste skrivas till 1 för att avmarkera flaggan TWINT"... Så vad som faktiskt händer här är när du skriver en 1 till TWINT anges det värdet för TWINT lika med noll! Det beror på TWINT båda * kontroller * TWINT flagga och * är * flaggan TWINT. Det säger sedan att det tolerabla VECKOINTAGET testar 2-tråds USB-bussen och generera en startvillkoret så fort bussen blir fri. Efter en startvillkoret har överförts, ange sedan flaggan TWINT av hårdvara. Detta innebär att TWINT blir 1 när detta är färdigt. Vi vet redan att detta är fallet eftersom våra mycket nästa rad är en tw_wait subrutin som bara håller testa TWINT tills det blir 1 och därefter läser statusregistret. Det faktum att skicka en 1 till TWINT bara för att det anges till 0 är källan till massor av förvirring för människor som försöker förstå hur I2C-protokollet fungerar. Viktiga är att inse att TWCR är en aktiv "kontroll" registrera samt en massa vippströmbrytare. Skicka en 1 till TWINT rensar flaggan avbrott och denna flagga råkar vara den samma TWINT lite i TWCR register så resultatet är TWINT = 0.

Nu kan ändra våra testvariabeln så att det kopierar TWSR statusregistret istället. Flytta inte på plats ännu. Bara köra det som är och ta reda på vad som finns i statusregistret omedelbart när vi berättar TWCR att överföra en startvillkoret men innan detta villkor har överförts.

Jag får 251. Detta är binär 0b11111011. Databladet säger, i avsnittet 22.5.5 på sidan 213, att TWSR registrerar endast innehåller relevanta statusinformationen när flaggan TWINT har angetts (minns när vi talar om "flaggor" sedan orden "flaggan är inställd" medel TWINT = 1, när vi talar om "styra avbrott" då orden "ange flaggan" skulle innebära skriva 0 till TWINT, vilket resulterar i TWINT = 1... bisarrt men det är så dess arbeten). Eftersom vi läser TWSR när TWINT = 0, dvs avbrottet är avstängd och TWI är upptagen, innebär det att det inte bör innehålla relevanta statusinformation, i stället avsnittet fortsätter med för att säga att den bör innehålla "en särskild status kod som indikerar att det finns någon relevant information". Ja då. Jag antar att vi nu vet vad "särskild status code". Det är 248. Med andra ord ställs alla bitar utom 3 att vi oftast mask. Nu en fråga som du kan fråga är "hur är det med prescaler bitar i TWSR, påverkar de här speciell statuskoden?" kom ihåg att vi dölja dem när vi vill läsa statuskoder, så om det tolerabla VECKOINTAGET bara läser TWSR rakt upp skulle inte det visar dessa prescaler bitar? Tja, gå upp till toppen och anger de prescaler bitarna till ett annat värde. Du kommer att hitta det om vi iväg båda av prescaler bitar (så att prescaler värdet är nu 1 och SCL kör på en högre frekvens!) och köra den vi får 248, som är 0b11111000, om vi bara TWPS0 till 1 och köra det igen (denna gång precaler skulle vara 4) hittar du att det nu lyder 249. Om du anger bara TWPS1 till 1 (så prescaler är nu 16) får du 250 och med både som vi normalt har det vi har sett dig 251. Så vi ser att sanna "kod för särskilda status" är 248, vilket betyder att alla bitar av den "status" delen av TWSR har angetts till 1 och de andra 3 bitarna bo som de var.

Nu flyttar "lds test, TWSR" kommandot för att efter vi vänta på avbrottet (dvs. efter TWINT = 1).

När vi trycker på knappen ser vi 0011 Visa upp på displayen, dvs decimal nummer 11. Vad betyder statuskoden 11? Tja, minns att de sista två bitarna i TWSR register är våra prescaler bitar som i vårt fall är båda 1. Vi måste bli av med dem (minns hur vi dölja dem när vi vill kontrollera status?) så låter subtrahera 3 från våra resultat (3 är vad dessa två bitar ger konverteras till decimaltal). Så status är faktiskt 8, eller 0x08 i hexadecimalt. Vilket är exakt vad vi förväntar oss.

Nu flytta Testlinjen under den punkten där vi anger adressen till slav i registret TWDR. Hittar du att det fortfarande lyder 11. Så förblir den 11 tills vi faktiskt gör något annat med det tolerabla VECKOINTAGET. Dicking runt med register som TWDR inte påverkar statusregistret. Den ändras endast när TWI är aktiv.

Nu flytta det under nästa gång vi ladda kontroll registret och du kommer att finna att det blir "särställning" igen... du får bild.

Som en sista test, gå till avsnittet där vi skickar dicetotal display och lägga till de följande 3 raderna i början av avsnittet:

LDI temp, 0b00000100
STS TWCR, temp
LDS test, TWCR

Du ser vad detta innebär. Det håller TWEN på så att det tolerabla VECKOINTAGET förblir aktiv, men nu skriver vi TWINT = 0 i registret över kontrollen. Då läser vi ut värdet av kontroll registret. Vad får vi? Vi få 132 visar på displayen! Detta är binär 0b10000100. Med andra ord är TWEN lite på som vi det, men nu är det TWINT lite på. Vi skickade TWINT = 0 för att kontrollera register och resultatet är TWINT = 1. Du ser nu varför rätt? Skicka TWINT = 0 till kontrollen register faktiskt definierar flaggan avbrott. Så resultatet är avbrottet flaggan är på, är det en 1.

Okej. Nu vet vi vad som händer i dice rullen med TWINT bit av TWCR registret. Det bara potentiellt förvirrande var när vi satt TWINT = 1 och sedan läsa bara för att finna dess värde var 0, och när vi TWINT = 0 Vi hittade dess värde var 1. Jag tror att du nu se varför detta är och hur det fungerar. Ställa in värden till TWCR är samma som skickar kommandon till TWI. TWINT = 1 kommandot betyder "köra kommandot i TWCR", men det värde som få in i den TWINT bit när det kommandot utförs är "klartext flaggan avbrott" som betyder "starta upp det tolerabla VECKOINTAGET och skicka några data". När det gäller avbrott flagga (det faktiska värdet i lite) är berörda, TWINT = 0 betyder att avbryta flagga är avstängd, det tolerabla VECKOINTAGET är upptagen med något. När TWINT går tillbaka till 1 betyder avbryta flaggan är satt och du kan nu ändra saker igen. Å andra sidan, så långt den * kommandon * du skicka till TWCR, skriver TWINT = 0 * apparater * flaggan avbrott och resultat TWINT = 1, och det tolerabla VECKOINTAGET stängs av så att du kan ändra data registret. Har jag slå den döda hästen tillräckligt länge? Jag gör bara detta eftersom det är lika förvirrande som f... väl. du får idén. Om du fortfarande förvirrad bara leka med det ett tag.

Nu undersöka figur 22-10 som visar de saker som händer under en typisk överföring. Nu när vi förstår hur TWINT fungerar det är tydligt vad det faktiskt värdet i den biten är vid en given tidpunkt under överföringen. I vita avsnitten TWINT = 0, och i svarten avsnitten TWINT = 1. När beskrivningen säger att "se till att TWINT är skriven till en" du vet nu att detta leder till TWINT = 0, dvs de avbrott flagga är avstängd eller "ta bort". Det ovan citerade uttalandet om att se till att TWINT är skriven till en måste vara källan till inget annat än förvirring för människor när de försöker lista ut hur det tolerabla VECKOINTAGET fungerar. Det är irriterande att författarna av databladet inte tar sig tid att verkligen förklara vad som händer. Andra avbrott flaggor i AVR fungerar på samma sätt, till exempel Timer/Counter overflow flaggan som vi behandlat i tidigare tutorials. Skriver en 1 till TOV0 lite i TIFR0 Timer/Counter0 avbryta flagga Register också * Clear * flaggan och så resulterar i en logik 0 i den biten. Men i fallet med andra avbrott flaggor vi inte behöver oftast att ställa in och rensa dem med programvara, hårdvara tar hand om som. Det är bara för att vid det tolerabla VECKOINTAGET vi behöver installera och avmarkera flaggan medan inuti den faktiska avbrott rutin som vi behöver tänka på det och det finns potential för förvirring.

Låt oss nu återställa vår dice rulle kod till som det var och flytta över till våra 4-siffrig display.

Lägg till en ny generell Journal kallas "test" som vi gjorde med dice rullen i 4-siffriga-display koden. Sedan i våra tw_int avbrottshanterare, Lägg till följande två rader i början av vår tw_return etikett, dvs i slutet precis innan du går tillbaka till huvudsidan:

LDI playercashH, 0
MOV playercashL, test

så att displayen visar vad är i test registret. Kan nu testa några saker.

Första låt oss testa SREG på olika ställen i avbrottshanterare. Lägga "lds test, SREG" i rätt överst när avbrottet anropas först. Hittar att det lyder 0. Detta innebär att "I" flagga automatiskt är avmarkerad när vi går in i avbrottshanterare. Du hittar också att det förblir avstängd under hela avbrottet. Detta är det normala sättet som SREG fungerar.

Nu låt oss testa TWSR. Här är där vi hittar något som kan tyckas märkligt. Om vi testa den precis efter avbrottet kallas få vi 96 visar. Varför är detta? Tja, minns ni att TWSR statuskoder finns i hexadecimalt. Om du konverterar 96 till hexadecimalt hittar du att det är 60. Vilket är det värde som vi får när avbrottet anropas först.

Övning 4: Vad är "special statuskoden" används i slav mottagaren?

Nu titta på TWDR registret när du först ange avbrottet. Hittar du att det är lika med den adress som vi har satt upp för slav, som sig bör sedan behandlingen adressen från TWI in i data-registret är hur vi visste vi kallades.

Slutligen, låt oss titta på TWCR och TWINT lite. Om du sätter "lds test, TWCR" precis i början när hanteraren först anges får du 197 som är 0b11000101. Detta innebär att TWINT = 1, TWEA = 1, TWEN = 1 och TWIE = 1. Detta är exakt hur vi ställer saker in i våra Reset avsnitt av programmet (leta, se?) förutom att nu TWINT avbrott flaggan är på. Vilket är också normalt eftersom vi har just gått in på avbryta, vi skulle inte vara här om något inte ange att flagga.

Gå till toppen av din program i avsnittet Återställ nu och Lägg till följande två rader:

LDI temp, 0
STS TWDR, temp

som om vi skulle initiera registrera våra data TWDR till noll. Vad händer nu när du kolla TWCR registret i början av avbrottet? Du får 205.

Övning 5: Varför får man 205?

Nu kan du vilja testa värdena för register på andra ställen i koden. Jag tror hittar du att de är som förväntat.

Se Steg
Relaterade Ämnen

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 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 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,...

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 Ö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 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 Övningsexempel 4

Välkommen till tutorial nummer 4!I den här guiden kommer vi att bygga en krets som kommer att simulera rullning av två tärningar. Sedan kommer vi först skriva en brute force-program som gör jobbet. Sedan kommer vi förenklar det programmet på olika sä...

En avancerad metod för Arduino & AVR programmering

Detta instructable är ett måste läsa för alla som är bekanta med core AVR chips och Arduino.Tja, mer konkret, när jag läste den instructable kommer du att kunna:1) vet väl skillnaden mellan AVR och Arduino.2) programmering Arduino med WinAVR & använd...

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

Ä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...

65xx teknik-församlingen språk programmering med W65C02SXB-handledning 1

Western Design Center (WDC) har beslutat att skriva en serie tutorials på hur du kommer igång med vår 65xx teknik och hur man skriver assembler program för 65xx familjen för ICs. Denna handledning kommer att baseras på använda det Standard W65C02 chi...

AVR fuse grunderna: kör en avr med en extern klocka

säkringar är bland de svåraste ämnen som jag stött på samtidigt lära sig om programmering microcontrollers. Även efter att söka och läsa flitigt, kunde jag fortfarande inte lyckas rensa mitt begrepp om dem. Men sedan jag började lära dem ta en i tage...

AVR programmering med Arduino, AVRdude och AVR-gcc

AVR är en gemensam, billig typ av mikro-controller som kan verka skrämmande att arbeta med, men oroa dig inte! När du har Ställ in grundläggande kunskap och kan de bli inte bara nyttigt, men viktigt att nya projektidéer som du drömmer upp!Denna handl...

Idiot's Guide till programmering AVR: s på de billiga (med Arduino IDE!)

Mikrokontroller är, utan tvekan, fantastiska små saker. De är mångsidiga, kraftfull och mycket små. Tyvärr, den sistnämnda drag också delas av både min plånbok och mina kunskaper i programmering. Min förståelse av C är dålig, och jag har knappt råd a...