Stap 7: Codering van de Master
Ten slotte moeten we voldoende begrip van wat er gaande is achter de schermen die we kunnen gaan door mijn code, lijn door lijn, voor zowel de Master en de Slave-microcontrollers. Houd er rekening mee dat als je kijkt naar de bijgevoegde code vindt u overvloedig opmerkingen rond alles wat die we hier bespreken.
Laten we beginnen met enkele nieuwe lijnen die wij aan onze Reset sectie toevoegt:
lds temp,PRR<br>andi temp,0b01011111<br>sts PRR,temp<br>ldi temp,255<br>sts TWBR,temp<br>ldi temp,(1--TWPS1)|(1--TWPS0)<br>sts TWSR,temp<br>ldi temp, (1--TWINT)|(1--TWEN)<br>sts TWCR,temp
waar u zult zich herinneren dat de "-" tekens moeten worden overgelaten operatoren verplaatsen.
Oke. We weten al wat de bovenstaande code doet omdat we het eerder hebben besproken. Het eerste deel is gewoon uitgeschakeld van de macht vermindering register bits voor de timer/teller en de TWI. Het tweede deel wordt ingesteld de SCL-bitsnelheid en dan schakelt de TW-interrupt en functie van de TWI.
Het volgende wat dat we doen is een regel toevoegen aan onze belangrijkste routine die de subroutine TWI roept. Hier ' tis:
main:<br>rcall button_push<br>rcall random<br>rcall dice<br>rcall cycle<br>rcall tw_transmit<br>rcall display<br>rjmp main
Merk op dat we noemen de tw_transmit-subroutine rechts nadat we tonen de geanimeerde dobbelstenen rollen en vlak voordat we het resultaat van de dobbelstenen wordt weergegeven roll op de dobbelstenen rol LEDs.
Nu krijgen we aan onze Master TWI-subroutine:
tw_transmit:<br>ldi temp, (1--TWINT)|(1--TWSTA)|(1--TWEN)<br>sts TWCR,temp
TWEN laat de TWI, TWSTA stuurt een "start"-voorwaarde beneden de draad die het vallen pulse tijdens een hoge SCL fietsen dat we bespraken eerder, en schrijven TWINT = 1 toe aan het besturingselement registreren schakelt de interrupt-vlag (d.w.z. resultaten in TWINT = 0) en begint met het overbrengen van een datapakket.
rcall tw_wait
Dit is een subroutine schreven we dat gewoon zit wachten voor de TWI-interface om onze opdracht te voltooien.
lds temp,TWSR<br>andi temp,0b11111000<br>cpi temp,0x08<br>brne ERROR
Dit alles controleren het status register om te zien wat daar. Wanneer de TWI iets doet laadt het de huidige status van de lijnen in dit register. Zodat u kunt controleren en ervoor te zorgen dat de opdracht die u eigenlijk het aan de lijn maakte en werd erkend door de slaaf. De tweede regel wordt onze prescaler bits ingesteld op nul (Onthoud, wij hebben hen ingesteld op 1 om de frequentie van onze SCL als 490Hz). Moet deze op nul instellen, zodat we het status register met de codes die zijn gegeven in tabel 22-2 vergelijken kunt. Merk op dat de statuscode 0x08 betekent de start-voorwaarde was verzonden en erkend. Nou, wat is 0x08 binair? Het is 0b00001000. Zodat u zien dat als we was vergeten om te maskeren de eerste drie bits, onze TWSR 0b00001011 bevatten zou = 0x0b en de comparsion zou mislukken. Als u niet de prescaler bits ingesteld zoals we deed en hen net als nullen liet moet u zou niet deze bits maskeren. De boven eindigt met een einde aan een foutafhandelingsroutine dat we hebben om te schrijven die zou gebeuren als we niet de juiste statuscode krijgen. Nu laten we uitkiezen welke slaaf die we praten willen met:
ldi temp,0b10100000<br>sts TWDR,temp<br>ldi temp,(1--TWINT)|(1--TWEN)<br>sts TWCR,temp
Eerst vullen we de gegevensregister, TWDR, met het adres van de slaaf en de bits lezen/schrijven. De slaaf van de 7-bits adres dat we willekeurig gekozen (het vermijden van degene die het gegevensblad vertelde ons niet te gebruiken) is 0b1010000 en wij overstag een 0 op het einde te betekenen wij willen "Write" naar de slaaf. Als we een 1 op het einde had geplakt zou dat betekenen willen we "Lezen" van de slaaf. Toen we de TWI lijnen weer op door het schrijven van TWINT = 1 toe aan het register van de controle om te wissen de interrupt. De TWEN = 1 is er gewoon zodat het blijft 1 en de TWI blijft "ingeschakeld". Dit stuurt de 8 gegevensbits langs de SDA-lijn naar de slaaf en de slaaf zal de lijn op grond ontvangstbevestiging. We wachten op de overdracht te voltooien met behulp van onze routine van de tw_wait (hieronder besproken aan het einde) en controleren van de status register om ervoor te zorgen het kreeg alle verzonden en precies zoals wij boven met het startschot deden erkend:
rcall tw_wait<br>lds temp,TWSR<br>andi temp,0b11111000<br>cpi temp,0x18<br>brne ERROR
Nu willen we eigenlijk onze om gegevens te verzenden. Aangezien we het adres van de slaaf, en het beetje schrijven gestuurd, het zal zitten, kwijlen in afwachting, voor 32653 klokcycli ;) klaar om te lezen de volgende 8 bits uit de SDA draad en stuur ze rechtstreeks in het eigen TWDR register is. Wij willen sturen dat de dobbelstenen rollen. Dus is hier hoe we het doen:
ldi temp,0<br>sts TWDR,temp<br>ldi temp,(1--TWINT)|(1--TWEN)<br>sts TWCR,temp<br>rcall tw_wait<br>lds temp,TWSR<br>andi temp,0b11111000<br>cpi temp,0x28<br>brne ERROR
Eerst wij 0 in het gegevensregister laden, dan wij zet de lijnen en stuur het. Dan wachten we op de overdracht te voltooien, en ten slotte controleren we de status om te controleren of het is verzonden en erkend. De reden die wij een nul verzonden is omdat we ze gaan voor het verzenden van 2 bytes. De eerste byte zal get geladen in "playercashH" door de slaaf, en de tweede byte worden in "playercashL" krijgen geladen door de slaaf. Vergeet niet dat wij uiteindelijk sturen twee bytes willen, zodat we de 4-cijferige weergave kan opvullen. We hoeven ze niet ditmaal dus we gewoon een nul voor de eerste sturen. Maar ik zet het hier omdat het laat zien hoe meer dan één byte van de gegevens verzenden en ook wij zal zitten using op deze manier de volgende keer.
sts TWDR,dicetotal<br>ldi temp,(1--TWINT)|(1--TWEN)<br>sts TWCR,temp<br>rcall tw_wait<br>lds temp,TWSR<br>andi temp,0b11111000<br>cpi temp,0x28<br>brne ERROR
Het bovenstaande moet nu zijn vrij eenvoudig te begrijpen. We gewoon Laad-up van het gegevensregister opnieuw, ditmaal met de totale rollen op de twee dobbelstenen, en stuur het opzij, de status controleren nadat de lijnen gaan dood. De slaaf zal deze belasting in playercashL. We zijn nu klaar. Zodat we op onze exit-opdrachten springen:
rjmp tw_return
Hier is onze foutafhandeling. Ik ben ervan uitgaande dat dit nooit zal worden uitgevoerd, zodat alles wat het doet is een Stop signaal afgeven aan de lijn en dan springen terug naar het begin en probeer het hele ding opnieuw.
ERROR:<br>ldi temp,(1--TWINT)|(1--TWSTO)|(1--TWEN)<br>sts TWCR,temp<br>rjmp tw_transmit
Tot slot het opruimen en afsluiten:
tw_return:<br>ldi temp,(1--TWINT)|(1--TWSTO)|(1--TWEN)<br>sts TWCR,temp<br>ret
Dit slechts een signaal stop langs de lijn (want we hebben de TWSTO stop tuimelschakelaar gespiegeld), global interrupts schakelt weer in, en keert terug naar de "main". Om te eindigen de bespreking van de kapitein code, is hier de tw_wait-routine:
tw_wait:<br>lds temp,TWCR<br>sbrs temp,TWINT<br>rjmp tw_wait<br>ret
Nu laten we eens kijken naar de Slave-code.