AVR Assembler Tutorial 10 (9 / 10 stap)

Stap 9: Hoe werkt de TWI-interrupt?


U moet eerst gaat u naar de volgende stap en de definitieve code downloaden en monteren zodat kunt u in deze stap (ik wil houden van de definitieve code en video in de laatste stap voor degenen die willen gewoon overslaan alle mijn brabbelen en uitsluitend stormloop naar de code.)

De TWI is verwarrend op het eerste, omdat het werkt anders dan andere interrupts. Meestal wanneer een interrupt optreedt en de bijbehorende interrupt handler wordt uitgevoerd, de I vlag in SREG automatisch is ingesteld op 0, zodat wereldwijde interrupts zijn uitgeschakeld, toen de de "RETI" om terug te keren uit de interrupt wordt uitgevoerd, de I vlag in SREG is automatisch ingesteld op 1 opnieuw global interrupts re-toe te laten en ook de individuele interrupt-vlag die overeenkomt met de interrupt (dat wil zeggen de bits in het register van de controle voor dat interrupt) is uitgeschakeld zodat de systeem opnieuw zal reageren op dat soort interrupt (Zie de status registreren beschrijving op bladzijde 11). Als we interrupts mogen te blijven op binnen een interrupt zouden we krijgen "geneste interrupts". Je kan dit doen door eigenlijk Re-enabling hen terwijl binnen uw interrupt routine, maar u normaal gesproken niet zou willen doen dit omdat een andere oproep tot de dezelfde interrupt zou u vervolgens eject vanuit de interrupt alleen Voer deze opnieuw in bij de bovenkant.

Oefening 3: Probeer het! Inschakelen global interrupts aan het begin van uw TWI routine, dan ergens binnen de set de TWIE bit in het TWCR-register en zien wat er gebeurt met de volgende keer dat de vlag TWINT is ingesteld.

Dit is echter niet hoe de TWI-interrupt werkt! TWINT is de interrupt-vlag. In de het blijft niet vastgestelde TWI tijdens de interrupt handler, verandert het de hele tijd. Dat komt omdat de TWI moet de interrupt-vlag gebruiken om te communiceren. Dus we kunnen niet gewoon laten op. In plaats daarvan we uitschakelen onderbreekt met behulp van TWIE = 0, zodat de CPU niet ons terug naar de interruptvector uitwerpen wanneer TWINT weer in een 1 verandert. Anyway, dit kan nog steeds verwarrend lijken dus we gaan om het te bespreken in het kader van onze code. Wanneer is precies TWINT = 1 en wanneer is TWINT = 0 in onze TWI routine?

Laten we het uitzoeken.

In plaats van heen en weer springen in het gegevensblad om erachter te komen wat er gaande is. Laten we onze roller dobbelstenen gebruiken en weer te geven. Dan zullen we absoluut duidelijk is van welke bits zijn ingesteld en wanneer.

Allereerst de volgende definitie aan het begin van uw dobbelstenen roller code toe te voegen:

.def test = r23

Ga nu naar beneden naar de tw_transmit-routine en recht aan de bovenkant van het, wanneer de PC de subroutine binnenkomt, zet de volgende regel

LDS-test, SREG

Ten slotte, afdalen naar de twee plaatsen in de code waar we het verzenden van de gegevens aan de weergave. In het tweede voorbeeld waar we doorgeven dat de lage byte, worden de dicetotal vervangen door test. Nu wanneer we druk op de knop, wordt de inhoud van het SREG-register, toen we eerst de subroutine, toegestuurd aan de weergave.

Nu, als we dit monteren en draaien, vinden we dat een 0000 op het display verschijnt. Dit betekent dat de I vlag van SREG zoals het zou moeten zijn omdat wij niet in staat global interrupts in onze dobbelstenen roller stellen heb is uitgeschakeld.

Nu de code wijzigen zodat die test TWCR in plaats van SREG ladingen en Bekijk de inhoud van TWCR.

Dat vinden wij, en dat de TWEN vlag is de enige op in TWCR. Wat betekent de TWI is ingeschakeld als het ook zou moeten zijn, want we zijn met behulp van de TWI.

Nu laat onze test-lijn naar een andere locatie verplaatst. Verplaats het neer op net nadat we de TWCR ingesteld voor de eerste keer. Dit is wanneer we de start-voorwaarde sturen. Het resultaat is een 36 onze tentoongesteld. Dit betekent dat TWCR 0b00100100 is.

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

Zo is de TWSTA-bit op zoals het zou moeten zijn omdat wij enkel de start-voorwaarde geladen, en de TWEN is op zoals het ook hoort. Maar kijk! In de vorige regel geladen we TWINT = 1 in het TWCR-register en wanneer wij onmiddellijk het register gekopieerd en het bekeken vinden we dat TWINT 0! Waarom is dat? Zie je dat "instellen van TWINT = 1" doet iets anders dan het gewoon opzetten dat beetje in TWCR gelijk is aan een. Als je kijkt op de onderkant van pagina 17 waar ze beschrijven toezending van een start-voorwaarde zult u zien dat ze zeggen, "TWINT moet worden geschreven op 1 om de TWINT markering wissen"... Dus wat er hier eigenlijk gebeurt wanneer u een 1 naar TWINT schrijven daarin de waarde van TWINT gelijk is aan nul! Dat komt omdat TWINT beide * controles * de TWINT vlag en * is * de TWINT vlag. Dan zegt het dat de TWI de seriële bus 2-draads test en genereren van een start-voorwaarde, zodra de bus vrijkomt. Vervolgens, nadat een start-voorwaarde heeft toegezonden, de TWINT markering is ingesteld door de hardware. Dit betekent dat TWINT 1 worden zal wanneer dit is voltooid. We weten al dat dit het geval is omdat onze volgende lijn een tw_wait-subroutine die gewoon testen TWINT is houdt tot het wordt 1 en vervolgens het register van de status leest. Het feit dat het verzenden van een 1 naar TWINT alleen om het te hebben ingesteld op 0 de bron van tal van verwarring voor mensen die proberen is te begrijpen hoe de I2C-protocol werkt. De sleutel is om te beseffen dat de TWCR een active "control" registreren evenals een heleboel aan-uitschakelaars. Het verzenden van een 1 tot TWINT wist de interrupt-vlag en deze vlag gebeurt te zijn het dezelfde TWINT bit in het TWCR-register zo het resultaat is TWINT = 0.

Nu laat onze test variabele zodanig wijzigen dat in plaats daarvan het TWSR status register worden gekopieerd. Verplaats de locatie niet gewoon nog niet. Alleen draaien als is en ontdek wat in het status register onmiddellijk wanneer we de TWCR vertellen voor het verzenden van een start-voorwaarde maar voordat die voorwaarde heeft toegezonden.

Ik krijg 251. Dit is in binaire 0b11111011. Het gegevensblad zegt, in de sectie 22.5.5 op pagina 213, dat de TWSR registreren alleen bevat statusinformatie wanneer de TWINT-vlag is ingesteld (niet vergeten wanneer we het hebben over "vlaggen" dan de woorden "de vlag is ingesteld" middelen TWINT = 1, wanneer we spreken over "controle interrupts" dan de woorden "stelt u de markering" dat het schrijven van een 0 naar TWINT betekenen zou, resulterend in TWINT = 1... bizar maar dat is de manier waarop zijn werken). Aangezien we TWSR aan het lezen bent wanneer TWINT = 0, dat wil zeggen de interrupt uitstaat en TWI is bezet, betekent dit dat het mogen geen statusinformatie, in plaats daarvan, het gedeelte gaat verder met te zeggen dat het bevatten moet "een speciale status code die aangeeft dat er geen relevante informatie beschikbaar is". Nou dan. Ik denk dat we nu weten wat de "speciale statuscode" is. Het is 248. Met andere woorden zijn alle van de bits ingesteld met uitzondering van de 3 dat we meestal maskeren. Nu een vraag die je zou kunnen vragen is "Hoe zit het prescaler bits in TWSR, hebben ze invloed op deze speciale statuscode?" Vergeet niet dat wij hen maskeren wanneer we lezen van de statuscodes willen, dus wanneer de TWSR is net het lezen van de TWI recht omhoog zou niet op uiterlijk vertoon deze prescaler bits? Nou, ga omhoog naar de top en de prescaler bits ingesteld op een andere waarde. Vindt u dat als we beide de prescaler bits verrekend (zodat de prescaler waarde nu 1 is en SCL draaien op een hogere frequentie!) en draaien we 248, dat is 0b11111000, als we alleen TWPS0 ingesteld op 1 en start het weer (deze tijd precaler zou 4) vindt u het dat het nu 249 leest. Als u instelt dat alleen TWPS1 1 (dus de prescaler nu 16 is) u 250 krijgt en met beide ingesteld als we normaal hebben hebben we u 251. Zo we zien dat de ware "speciale statuscode" 248, wat betekent dat alle stukjes van het deel van de 'status' van TWSR is ingesteld op 1 en de andere 3 bits blijven zoals ze waren.

Nu verplaatsen de "LDS-test, TWSR" commando om nadat we voor de interrupt wachten (d.w.z. na TWINT = 1).

Als we druk op de knop zien we 0011 Toon omhoog op het scherm, dat wil zeggen het decimale getal 11. Wat betekent de statuscode 11? Nou, herinneren dat de laatste twee bits van het TWSR-register zijn onze prescaler bits die, in ons geval, van beide 1. Wij nood te halen afhelpen daarvan (Vergeet niet hoe wij hen maskeren wanneer we willen de status controleren?) dus laat aftrekken 3 van ons resultaat (3 is wat deze twee bits geven wanneer ze worden omgerekend naar een decimaal getal). Dus de status eigenlijk 8 is, of 0x08 in hexadecimaal. Dat is precies wat we verwachten.

Nu de test regel omlaag verplaatsen onder het punt waar we het adres van de slaaf in het TWDR-register invoeren Vindt u dat het nog steeds 11 leest. Het blijft dus 11 totdat we eigenlijk iets anders met de TWI doen. Dicking rond met de andere registers als TWDR heeft geen invloed op de status register. Alleen verandert wanneer de TWI actief is.

Nu zet hieronder de volgende keer dat we de control register en u laden vindt dat het weer de "speciale status"... je krijgt het beeld.

Als één van de laatste test, ga naar het gedeelte waar we de dicetotal verzenden het display en de volgende 3 regels toevoegen aan het begin van die sectie:

LDI temp, 0b00000100
St TWCR, temp
LDS-test, TWCR

U zien wat dit doet. Het houdt de TWEN op zodat de TWI ingeschakeld blijft, maar nu we TWINT schrijven = 0 in het register van de controle. Dan lezen we uit de waarde van het besturingselement-register. Wat krijgen we? We krijgen 132 verschijnen op het display! Dit is in binaire 0b10000100. Met andere woorden, aanstaat de TWEN bit als we het instellen, maar nu de TWINT bit ingeschakeld is. Wij verzonden TWINT = 0 aan het besturingselement registreren en het resultaat is TWINT = 1. Nu zie je waarom gelijk? Verzenden van TWINT = 0 aan het besturingselement ingesteld register eigenlijk de interrupt-vlag. Dus het resultaat de interrupt is-vlag is op, is het een 1.

Oke. Nu weten we wat er gebeurt in de rol van de dobbelstenen met het TWINT beetje het TWCR-register. Het enige potentieel verwarrende deel was toen we ingesteld TWINT = 1 en lees vervolgens het alleen te vinden zijn waarde was 0 en wanneer wij stellen TWINT = 0 vonden we de waarde was 1. Ik denk dat je nu zien waarom dit is en hoe het werkt. Het instellen van waarden aan de TWCR is hetzelfde als het verzenden van opdrachten naar de TWI. De TWINT = 1 opdracht betekent "het commando in de TWCR", maar de waarde die worden ingesteld in de TWINT bit wanneer deze opdracht wordt uitgevoerd is de "clear de interrupt-vlag" wat betekent "de TWI opstarten en sommige gegevens verzenden". De interrupt-vlag (de werkelijke waarde in de bit) is wat betreft, TWINT = 0 betekent interrupt-vlag is uitgeschakeld, de TWI is bezig om iets te doen. Wanneer TWINT terug tot 1 gaat betekent de interrupt-vlag is ingesteld en u kunt nu dingen opnieuw wijzigen. Aan de andere kant, voor zover de * opdrachten * u verzenden naar de TWCR, het schrijven van TWINT = 0 * ingesteld * de interrupt-vlag en resultaten in TWINT = 1, en de TWI uitgeschakeld zodat u kunt het gegevensregister wijzigen. Heb ik lang genoeg het dode paard verslaan? Ik doe dit alleen omdat het is zo verwarrend als f... goed. je krijgt het idee. Als u nog steeds verward bent gewoon spelen met het voor een tijdje.

Nu onderzoeken figuur 22-10 waarin de dingen gebeuren tijdens een typische transmissie. Nu dat we begrijpen hoe TWINT werkt het is duidelijk wat de waarde daadwerkelijk in dat iets op een gegeven moment tijdens de uitzending. In de witte afdelingen TWINT = 0 en in het zwart afdelingen TWINT = 1. Wanneer de omschrijving zegt om "ervoor dat TWINT is geschreven op een" je weet nu dat dit in TWINT resulteert = 0, dat wil zeggen de interrupt-vlag is uitgeschakeld, of "uitschakelen". De bovenstaande geciteerde verklaring over ervoor te zorgen dat TWINT wordt weggeschreven naar een moet de bron van alleen maar verwarring naar mensen wanneer zij proberen om erachter te komen hoe de TWI werkt. Het is vervelend dat de schrijvers van het gegevensblad niet de tijd nemen om echt uitleggen wat er gebeurt. Andere interrupt-vlaggen in AVR werken op dezelfde manier, bijvoorbeeld de Timer/teller overloop vlag die wij behandeld in de vorige tutorials. Een 1 schrijven naar de TOV0-bit van de TIFR0 Timer/Counter0 onderbreken vlag Register ook * wist * de vlag en dus resulteert in een logica 0 in dat beetje. Maar in het geval van andere interrupt-vlaggen die we meestal hoeft niet te stellen en hen duidelijk met software de hardware zorgt voor dat. Het is alleen omdat in het geval van de TWI we moeten instellen en schakelt u de vlag terwijl hij in de werkelijke interrupt routine die wij nood voor kopzorg zowat het en er het potentieel voor verwarring bestaat.

Laten we nu onze dobbelstenen roller code terugzetten naar de zin die op watertje en overgaan op onze 4-cijferige display.

In de 4-cijferige display code toevoegen een nieuw General-Purpose journaal genaamd "test" als we met de dobbelstenen rol deden. In onze tw_int interrupt handler, voegt u de volgende twee regels aan het begin van onze tw_return-label, dat wil zeggen aan het eind net voordat je terug naar de belangrijkste:

LDI playercashH, 0
MOV playercashL, test

zodat het display laten wat er in het register van de test zien zal. Laat nu sommige dingen testen.

Eerste test laten we SREG op verschillende plaatsen in de interrupt handler. Ter "LDS-test, SREG" rechts boven wanneer de interrupt voor het eerst wordt aangeroepen. Vindt u dat er 0 staat. Dit betekent dat de "I" vlag automatisch gewist wordt zodra we de interrupt handler invoeren. U vindt ook dat het uit tijdens de gehele interrupt blijft. Dit is de normale manier dat SREG zich gedraagt.

Nu laten we eens testen TWSR. Hier is waar we iets dat vreemd lijkt misschien vinden. Als we testen net na de interrupt heet krijgen we 96 opdagen. Waarom is dit? Nou, u zult zich herinneren dat TWSR statuscodes in hexadecimaal worden. Als u 96 naar hexadecimaal converteren vindt u dat er 60. Dat is de waarde die we krijgen moeten wanneer de interrupt voor het eerst wordt aangeroepen.

Oefening 4: Wat is de "speciale statuscode" gebruikt in de slave-ontvanger?

Nu kijken naar het TWDR-register wanneer u de interrupt voor het eerst invoert. Vindt u dat gelijk aan het adres dat we hebben opgezet voor de slaaf, is zo hoort het ook sinds lezen van die het adres van de TWI in het gegevensregister is hoe we wisten dat wij heetten.

Tot slot, laten we kijken TWCR en het bit TWINT. Als je "LDS-test, TWCR" aan het begin wanneer de handler wordt eerst ingevoerd krijg je 197 oftewel 0b11000101. Dit betekent dat TWINT = 1, TWEA = 1, TWEN = 1, en TWIE = 1. Dit is precies hoe we dingen opgezet in onze sectie van de Reset van het programma (gaan kijken, zie?) behalve dat nu de TWINT interrupt-vlag ingeschakeld is. Dat is ook normaal, aangezien we hebben zojuist de interrupt, zouden we niet hier als iets dat markering niet instellen.

Ga nu naar de bovenkant van uw programma naar de Reset-sectie en voeg de volgende twee regels:

LDI temp, 0
St TWDR, temp

alsof we gingen voor het initialiseren van registreren onze gegevens TWDR op nul. Wat gebeurt er nu als u het register van de TWCR aan het begin van de interrupt? Krijg je 205.

Oefening 5: Waarom krijg je 205?

Nu zou u de waarden van registers elders in de code te testen. Ik denk dat u zult vinden dat ze zijn zoals u verwacht.

Gerelateerde Artikelen

AVR Assembler Tutorial 2

AVR Assembler Tutorial 2

Deze tutorial is een voortzetting van het "AVR Assembler Tutorial 1"Als je niet hebt doorlopen Tutorial 1 moet je nu stoppen en dat men eerst doen.In deze tutorial zullen we onze studie van assembly language programmering van de atmega328p in de
AVR Assembler Tutorial 11

AVR Assembler Tutorial 11

Welkom bij Tutorial 11!In deze korte tutorial, zijn we eindelijk het eerste deel van onze laatste project bouwen.Het eerste wat dat u moet doen is gaat u naar de allerlaatste stap van deze tutorial en Bekijk de video. Dan kom hier terug. [onderbreken
AVR Assembler Tutorial 1

AVR Assembler Tutorial 1

Ik heb besloten om een serie tutorials over hoe te schrijven van assembler programma's voor de Atmega328p die het gebruikt in de Arduino microcontroller is schrijven. Als mensen geïnteresseerd blijven blijft ik stak een een week of zo totdat ik oprak
AVR Assembler Tutorial 6

AVR Assembler Tutorial 6

Welkom bij Tutorial 6!Today's tutorial zullen kort waar zullen we het ontwikkelen van een eenvoudige methode om gegevens tussen een atmega328p en een andere met twee poorten verbinden hen te delen. Wij zullen vervolgens nemen de dobbelstenen rol van
AVR Assembler Tutorial 8

AVR Assembler Tutorial 8

Welkom bij Tutorial 8!In deze korte tutorial gaan we een beetje een afleiding van de invoering van nieuwe aspecten van assembly language programmering te laten zien hoe onze prototyping componenten verplaatsen naar een aparte "gedrukt" printplaa
AVR Assembler Tutorial 9

AVR Assembler Tutorial 9

Welkom bij Tutorial 9.Vandaag zullen wij tonen hoe de controle van zowel een 7-segment display en een 4-cijferige weergave met behulp van onze ATmega328P en AVR assembler code. In de loop doen die we nemen van omleidingen moeten zal op how to use van
AVR Assembler Tutorial 7

AVR Assembler Tutorial 7

Welkom bij Tutorial 7!Vandaag gaan we naar eerste show hoe opruimen van een toetsenbord, en vervolgens laten zien hoe de analoge input poorten gebruiken om te communiceren met het toetsenblok.We zullen dit doen met behulp van interrupts en een enkele
AVR Assembler Tutorial 5

AVR Assembler Tutorial 5

Vandaag gaan we nemen een kijkje op de verschillende geheugenlocaties in de Atmega328p microcontroller en zien als we beter begrijpen kunnen hoe de dingen worden opgeslagen, waar ze worden opgeslagen en hoe de pointers en opzoektabellen werken.De tut
AVR Assembler Tutorial 4

AVR Assembler Tutorial 4

Welkom bij de handleiding voor nummer 4!In deze tutorial zullen we bouwen een circuit om te simuleren het rollen van twee dobbelstenen. Dan zullen we eerst een brute-force-programma welk doet naar de job schrijven. Dan zullen we dat programma op vers
AVR Assembler Tutorial 3

AVR Assembler Tutorial 3

Welkom op tutorial nummer 3!Voordat we beginnen wil ik een filosofische opmerking maken. Wees niet bang om te experimenteren met de circuits en de code die we proberen op te in deze tutorials bouwen. Draden rond wijzigen, nieuwe onderdelen toe te voe
Een geavanceerde benadering van programmering van Arduino & AVR

Een geavanceerde benadering van programmering van Arduino & AVR

Dit instructable is een must read voor iedereen die vertrouwd is met core AVR chips en Arduino.Nou, om meer specifieke, bij het lezen van de instructable, zal u zitten kundig voor:1) weten het juiste verschil tussen AVR en Arduino.2) programmering Ar
Programmeerbare LED

Programmeerbare LED

geïnspireerd door diverse LED Throwies, knipperende LEDs en soortgelijke instructables ik wilde doen van mijn versie van een LED aangestuurd door een microcontroller.Het idee is om de LED knipperende reeks Herprogrammeerbare. Deze herprogrammering ka
De generator van willekeurige golfvorm, voor ~ 20$

De generator van willekeurige golfvorm, voor ~ 20$

een willekeurige golfvorm generator (AWG) is een nuttige maar vaak duur stuk van testapparatuur (ebay voor lacht). Gebruiken om te bepalen component frequentiebereik, genereren van vervoerder signalen, als een LCR-meter als u een bereik, tune resonan
Star Trek deurbel Hack

Star Trek deurbel Hack

Ik heb altijd al een fan van de Star Treks en als zodanig ik was erg opgewonden toen mijn kamergenoot bracht het huis van een originele serie stijl Star Trek comm panel. Ik had nog nooit gezien een van deze, maar een snelle zoektocht nam ons mee naar