Stap 3: Testen het display
Nu dat we onze 4-cijferige weergave hebt verplaatst naar een eigen bestuur die we willen testen om ervoor te zorgen dat het werkt (en de onvermijdelijke problemen op te lossen). Dit betekent dat we willen om een eenvoudige driver die net weer een aantal en controleren van alle van de segmenten aan elk cijfer te schrijven. Zodra we ervan overtuigd zijn dat alles werkt zoals het moet dan kunnen we werken aan onze communicatie-code.
De manier waarop we de test code zullen schrijven is zodat we deze later gebruiken blijven kunnen door simpelweg het toevoegen van de communicatie routines. Dus we onze 4-cijferige display code kopiëren de laatste tutorial en alle van de dingen die te maken had met de ADC aangezien we niet dat meer gebruikt verwijderen. We veranderd ook de anode pinnen zodat zij PC0 door PC3 gebruiken aangezien het bedrading en codering gemakkelijker maakt.
Ik heb de code en een beeld van de werking van het externe beeldscherm bijgevoegd.
Ik hoef niet alle de code regel voor regel doorlopen, want het is meestal gewoon eenvoudige aanpassingen van de dingen die we al hebben gedaan. Er is echter één ding die heb ik moeten weten.
We gaan uiteindelijk wilt weergeven van getallen van 0000 tot 9999 op onze 4-cijferige display. Dit betekent dat we ruimte voor 10.000 nummers nodig. Een 8-bit register gaat echter alleen tot 255. Dus we gaan moeten meer bits gewijd aan het nummer we wilt weergeven. Laten we doen een snelle berekening om erachter te komen hoeveel bits dat we gaan nodig hebben. Elk cijfer is een macht van 2 en dus we willen om te zien welke kracht van twee geeft ons 10.000. Hiervoor gebruiken we de "natuurlijke logaritme":
2 ^ x = 10000
x ln(2) = 4 ln(10)
x = 4 ln(10)/ln(2) = 13.288
Dit vertelt me om weer te geven van 10000 moeten we meer dan 13 bits. Dus als ik 14 bits gebruiken zal dan heb ik meer dan genoeg. Als een selectievakje (of doe dit in de eerste plaats als u niet denkt dat wiskunde is leuk), ga enkel naar de "wiskunde is leuk" website automatische convertor hier:
http://www.mathsisfun.com/Binary-Decimal-hexadecim...
en het uitzoeken door simpelweg te converteren. Vindt u dat 14 cijfers cijfers tot 16383 en 13 cijfers slechts tot een maximum 8191 kunnen weergeven. Dus klopt onze berekening, dat we moeten meer dan 13 cijfers en minder dan 14. Dus we gebruiken 14. In feite, 9999 in binaire is: 0b10011100001111 die is 14 bits, maar het hoeft niet allemaal op.
Oke, dus de manier waarop we lossen het dilemma van meer dan 1 nodig registreren is het gebruik van 2 van hen. Dit geeft ons 16 bits en is dus genoeg om weer te geven van een willekeurig getal die we gooien op de 4-cijferige weergave.
Maar wanneer we de getallen over onze communicatie interface zij in binaire zullen sturen. Hoe we een binair getal converteren naar decimale cijfers weer te geven? Dit is lang niet zo gemakkelijk als je op het eerste gezicht zou denken. Laten we het uitzoeken.
We beginnen met een getal tussen 0 en 9999 en we willen de 4 cijfers van dat aantal, zodat we ze kunt weergeven. Er is geen functie in assembler, dat voor ons doen zal zodat we hebben om één onszelf. Het nummer begint als een binair getal van 2 bytes. Laat noemen het X voor nu. Wij willen om erachter te komen elk cijfer op zijn beurt van de hoogste naar de laagste. De manier vinden we de hoogste is net als in de omtrek van deze code:
cijfer = 0
Start:
X > 1000?
JA:
X = X - 1000
cijfer ++
goto start:
NR.:
retourneren cijfers
Zoals u zien kunt, dit ziet er heel simpel. We opstijgen slechts 1000 een op een tijdstip en elke keer dat we de waarde van "cijfers" verhogen. Zodra de X is niet langer groter dan 1000 zal er het aantal van 1000 's opgeslagen in "cijfers" en wij terug te sturen. Dit geeft ons het eerste getal voor onze weergave. Dan kunnen we hetzelfde als boven aan de resterende waarde van X behalve met 100 's in plaats van 1000 en zal dit ons het nummer van de 100 's, krijgen dan wij doen het weer met 10, en tot slot wanneer er geen links, het bedrag nog in X 10 zal tussen 0 en 9, en dus het zal onze laatste cijfer. Dus is dat hoe kunnen we onze 4 cijfers.
Echter! Het is lang niet zo eenvoudig in assembler! Een enorme moersleutel is dit plan gegooid vanwege het feit dat we twee bytes moeten te vertegenwoordigen van onze 14-cijferige binaire getal bevat. Hoe we de 1000 aftrekken? In 2-byte woorden, 1000 wordt vertegenwoordigd door 0b0000001111101000 en je ziet dat sommige is het in de eerste byte en sommige ervan is in de tweede byte. Dus in plaats van X = X-1000 kunnen we schrijven X als de twee bytes XH en XL dus dat X = XH:XL en dan doen onze aftrekken als volgt:
XH = XH - high(1000)
XL = XL - low(1000)
Dat lijkt eenvoudig genoeg toch? Nou, die het wordt nog erger! Stel dat we begonnen met X = 2001 en vinden we onze eerste cijfer (de 2) door 1000 's af te trekken. Laten we eens kijken hoe het zou werken:
We testen van X en vinden dat het is > 1000 en zodat we van elkaar aftrekt, sinds 2001 = 0b0000011111010001 in binaire onze aftrekken werken zou als volgt (aanbrengend de nummers):
XH = high(0b0000011111010001) - high(0b0000001111101000)
XL = low(0b0000011111010001) - low(0b0000001111101000)
die wordt
XH = 0b00000111 - 0b00000011 = 7-3 = 4
XL = 0b11010001 - 0b11101000 = 209-232 = - 23
We hebben een probleem! De lage byte bevat niet genoeg om de aftrekken! Dit is geen probleem omdat assembler aankan negatieven, maar het slechts tot-128 behandelen kan en zeker zal er momenten waarop het resultaat van de XL-aftrekken meer negatieve dan dat is, zou je denken. Dus wat doen we?
Nou, is de manier waarop die we omgaan met dit dezelfde manier wij doen het in elke aftrekken van de 5e rang. We moeten één van de cijfers van XH. Vergeet niet dat elk binaire cijfer in XH eigenlijk gelijk aan 256 is. We doen dit met de "sbc"-opdracht die wordt afgetrokken met carry.
Dan, zodra we gekregen van de 1000 's ontdoen hebben we overgaan tot de 100 's en het zelfde ding doen. In dat geval hebben we het zelfde probleem dat we lenen van 1's vanaf de hoge byte moeten zullen totdat onze resultaat minder dan 256 is zodat we blijven gebruiken van de sbc aan subract de hoge byte.
Ten slotte, wanneer we naar de 10 en de 1's plekken die wij niet langer hoeft te maken over het lenen van cijfers meer en dingen eenvoudiger zijn, we kunnen gewoon aftrekken het lage register.
Dus nu zie je hoe wij zijn gedwongen om te doen dingen nemen een blik op de code en u moet nu kunnen om erachter te komen hoe het werkt. Merk op dat er sommige dingen die wij doen moesten om getallen tussen 768 en 999 weergeven. Kun je denken aan waarom dat kan zijn? In ieder geval, beginnen we gewoon door het te geven een aantal weer te geven zodat wij onze display kunt testen. We zullen gewoon gebruik maken van 9876. Wij willen later het nummer een ander microcontroller vandaan via de interface twee-draads communicatie.
Oefening 1: Erachter te komen hoe het codefragment hieronder werkt.
Hier is de expliciete code die ik gebruik voor het omzetten van de twee byte binair naar decimaal voor de cijfers van de weergave:
loadCash: ; this computes the digit for each 7-seg of the display<br>cli ; disable interrupts while loading digits<br>push playercashH ; store high byte of playercash<br>push playercashL ; store low byte of playercash<br>ldi tempH,high(1000) ; set tempH:L to 1000<br>ldi tempL,low(1000) <br>rcall computeDigit ; find the 3rd digit<br>mov digit3,digit ; store the new 3rd digit<br>ldi tempH,0 ; set tempH:L to 100<br>ldi tempL,100 <br>rcall computeDigit ; find the 2nd digit<br>mov digit2,digit ; store the new 2nd digit<br>ldi tempH,0 ; set tempH:L to 10<br>ldi tempL,10 <br>rcall computeDigit ; find the 1st digit<br>mov digit1,digit ; store the new 1st digit<br>mov digit0,playercashL ; remaining is 0th digit<br>pop playercashL ; restore low byte of playercash<br>pop playercashH ; restore high byte of playercash<br>sei ; re-enable interrupts<br>ret
computeDigit: ; interrupts are already disabled while here<br> clr digit compareHigh: cpi playercashH,0 ; if both playercashH brne PC+3 cpi playercashL,0 ; and playercashL are zero then done breq returnDigit cp playercashH,tempH ; otherwise continue brlo returnDigit ; if less then move to next power of 10 brne PC+3 ; if high is greater then subtract cp playercashL,tempL ; if highs are equal and lows are less, brlo returnDigit ; then playercash is less so move to next power of 10 clc sub playercashL,tempL ; otherwise subtract power of 10 sbc playercashH,tempH ; otherwise subtract power of 10 inc digit ; and increment the current digit rjmp compareHigh ; and go back up to test again returnDigit: ; digit will now be the one to display in this spot ret
Volgende zullen we introduceren iets nieuws--TWI communicatie.