Inhoudsopgave:

AVR Assembler Tutorial 7: 12 stappen
AVR Assembler Tutorial 7: 12 stappen

Video: AVR Assembler Tutorial 7: 12 stappen

Video: AVR Assembler Tutorial 7: 12 stappen
Video: AVR Ассемблер. Урок 7. ШИМ. Управление серво. AVR Assembler. Lesson 7. PWM. Servo control. 2024, Juli-
Anonim
AVR-assemblagehandleiding 7
AVR-assemblagehandleiding 7

Welkom bij les 7!

Vandaag laten we eerst zien hoe je een bediendeel opruimt en vervolgens hoe je de analoge ingangspoorten gebruikt om met het bediendeel te communiceren. We zullen dit doen met interrupts en een enkele draad als invoer. We zullen het toetsenbord zo bedraden dat elke toetsaanslag een unieke spanning naar de analoge ingang stuurt, waardoor we aan de hand van de spanning kunnen onderscheiden op welke toets werd gedrukt. Vervolgens zullen we het ingedrukte nummer naar onze registeranalysator sturen om te laten zien dat alles gebeurt zoals het zou moeten. neem onderweg dingen in een paar fasen om te proberen erachter te komen hoe ze te vermijden. We zullen ook zien waarom het gebruik van de analoog naar digitaal converter niet de beste manier is om een toetsenbord te bedienen, ook al gebruikt het minder poorten op je microcontroller. In deze tutorial heb je nodig:

  1. een toetsenbord. Je kunt er een kopen of je kunt doen wat ik deed en er een opruimen.
  2. 2 vrouwelijke headers voor het toetsenbord (als u er een opruimt)
  3. aansluitdraden
  4. een breadboard
  5. 4 1 Kohm-weerstanden
  6. 1 15 Kohm-weerstand
  7. 1 3.3 Kohm-weerstand
  8. 1 weerstand van 180 ohm
  9. 1 680 ohm weerstand
  10. een digitale multimeter
  11. uw analysator uit Tutorial 5

Misschien wilt u de eerste paar stappen overslaan als u al een toetsenbord heeft en er geen hoeft op te ruimen.

Hier is een link naar de volledige verzameling van mijn AVR-assembler-tutorials:

Stap 1: Zoek een toetsenbord op

Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen

Lang geleden, toen zelfs je grootouders nog maar kinderen waren, gebruikten mensen deze vreemd uitziende apparaten, die lange kabels in de muur hadden gestoken, om met elkaar te communiceren. Ze werden "telefoons" genoemd en waren meestal goedkope plastic dingen die een vervelend geluid maakten als iemand je belde (niet dat de beltonen van "Justin Bieber" van tegenwoordig niet even irritant zijn). In elk geval hadden deze apparaten toetsenborden die heel eenvoudig bedraad waren en dus gemakkelijk te vinden zijn en ze hebben 2 extra toetsen ("herkiezen" en "flash") van de toetsenborden die u kunt kopen en die u misschien opnieuw wilt gebruiken als "pijltjestoetsen", "menutoetsen" of iets anders. Dus we beginnen met het opruimen van een toetsenbord van een oude telefoon. Neem eerst de telefoon (ik gebruik een GE zoals op de foto's) en wrik hem uit elkaar om de bedrading te onthullen. Neem dan een beitel en verwijder de kleine plastic knoppen die het toetsenbord vasthouden en verwijder het toetsenbord.

Stap 2: Zoek een toetsenbord op

Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen

Neem nu een PVC-zaag en snijd het plastic rond de sleutelgaten en snij dan rond de rand om de diepte goed te krijgen en laat een dun toetsenbord achter.

Plaats vervolgens het toetsenbord weer met de kleine pinnen die overblijven nadat u de toppen er in de laatste stap af hebt geknipt en gebruik een soldeerbout om het hete strijkijzer eenvoudig in elk pengat te prikken, waardoor het plastic zal smelten en het over de onderkant van het toetsenbord vormen nieuwe "knoppen" die het toetsenbord op zijn plaats houden zoals voorheen.

Ik vind het leuk om de drie luidsprekers op te ruimen en misschien de andere dingen zoals schakelaars en wat-niet die op het bord staan. Deze keer ga ik echter niet op zoek naar de schakelaars en zo omdat we op dit moment andere doelen hebben. Er zit ook een TA31002 lineair IC in dat een telefoonbel is. De datasheet is gemakkelijk online te vinden en te downloaden met de pin-out en functies. Dus ik laat het voorlopig aan het bord gesoldeerd en speel er later mee. Ik wil hem graag aansluiten op een oscilloscoop en kijken welke coole signalen ik eruit kan halen. Misschien maak je er zelfs een deurbel van. Wie weet.

Hoe dan ook, als je klaar bent met het vernietigen van de telefoon en het opruimen van de onderdelen, zullen we het maken van ons toetsenbord voltooien.

Stap 3: Zoek een toetsenbord op

Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen
Een toetsenbord opruimen

Gebruik een desoldeerlont en verwijder de lintkabels van de onderkant van het toetsenbord en zorg ervoor dat de gaten in de printplaat vrij zijn en bevestig vervolgens twee vrouwelijke headers op het bord waar de gaten zich bevinden. U zult waarschijnlijk uw headers moeten knippen zodat het 4-pins headers zijn.

Nu de headers zijn bevestigd, kunt u deze aansluiten op een breadboard, een multimeter nemen en de toetsen testen door de multimeter over willekeurige pinnen te steken en de weerstand te meten. Hiermee kunt u de sleutels in kaart brengen. Het is moeilijk te zien hoe de toetsen op de uitgangen zijn aangesloten door naar het circuit te kijken, maar als u een multimeter gebruikt, kunt u deze op twee willekeurige pinnen aansluiten en vervolgens op de knoppen drukken totdat u een nummer op het scherm ziet in plaats van een open circuit. Dit wordt de pin-out voor die sleutel.

Wijs op deze manier alle sleutels toe om pinnen uit te voeren.

Stap 4: Bedraad het toetsenbord

Bedraad het toetsenbord
Bedraad het toetsenbord
Bedraad het toetsenbord
Bedraad het toetsenbord

Volg nu het bedradingsschema en sluit het toetsenbord aan op uw breadboard.

Hoe dit gaat werken, is dat we 5V aan de linkerkant plaatsen en de rechterkant naar GND. De eerste pin aan de rechterkant in het diagram gaat in de eerste van onze analoge pinnen op de Atmega328p-microcontroller. Als er geen knoppen worden ingedrukt, is het signaal 0V, en wanneer elk van de verschillende knoppen wordt ingedrukt, zal de invoer naar de analoge poort variëren tussen 0V en 5V met een verschillende hoeveelheid, afhankelijk van welke toets werd ingedrukt. We kozen de weerstandswaarden zodat elk pad een weerstand zou bevatten die anders was dan de rest. De analoge poort op de microcontroller neemt een analoog signaal en splitst dit op in 1024 verschillende kanalen tussen 0V en 5V. Dit betekent dat elk kanaal een breedte heeft van 5V/1024 = 0,005 V/kanaal = 5 mV/kanaal. De analoge poort kan dus ingangsspanningen onderscheiden zolang deze meer dan 5 mV verschillen. In ons geval hebben we weerstandswaarden gekozen zodat elke twee toetsaanslagen een spanningssignaal sturen dat meer dan dit verschilt, zodat de microcontroller gemakkelijk moet kunnen beslissen welke toets werd ingedrukt. Het grote probleem is dat het hele systeem veel ruis maakt, dus we zullen een reeks spanningen moeten kiezen om aan elke druk op de knop toe te wijzen -- maar daar komen we later op terug.

Merk op dat we een toetsenbord met 14 knoppen kunnen bedienen met slechts een enkele invoerlijn naar de controller. Dat is een van de handige aspecten van analoge ingangen.

Onze eerste poging om het toetsenbord te bedienen zal zijn om een toetsaanslag een interrupt te laten veroorzaken, de interrupt-subroutine zal de analoge ingangspoort lezen en beslissen welke toets werd ingedrukt, en dan zal het dat nummer uitvoeren naar onze registeranalysator-subroutine die de sleutelwaarde in binair op onze 8 LED's die we hebben ingesteld in Tutorial 5.

Stap 5: Verbind het toetsenbord met uw analysator

Sluit het toetsenbord aan op uw analysator
Sluit het toetsenbord aan op uw analysator
Sluit het toetsenbord aan op uw analysator
Sluit het toetsenbord aan op uw analysator

De afbeeldingen laten zien hoe we het toetsenbord op de microcontroller willen aansluiten, zodat we de uitvoer op ons analysatordisplay kunnen zien. In wezen verbinden we eenvoudig de uitvoer van het toetsenbord naar PortC-pin 0, die ook ADC0 wordt genoemd op de ATmega328P.

Er zijn echter een paar extra dingen. We gaan ook een knop aansluiten op PD2. D.w.z. neem een draad van je 5V-rail naar een knop en van de andere kant van de knop naar PD2, en tot slot willen we de AREF-pin loskoppelen van onze 5V-rail en in plaats daarvan losgekoppeld laten. We kunnen een ontkoppelingscondensator van 0,1 microfarad plaatsen als we dat willen. Dit is een keramische condensator met een 104 erop. De eerste twee cijfers zijn het getal en het laatste cijfer is de macht van 10 we vermenigvuldigen het met om een antwoord te krijgen in picofarads (pico betekent 10^-12), dus 104 betekent 10 x 10^4 picofarads, wat hetzelfde is als 100 nanofarads (nano betekent 10^-9), wat hetzelfde is als 0,1 microfarads (micro betekent 10^-6). Hoe dan ook, het enige dat dit doet, is de AREF-pin stabiliseren wanneer we deze als onze referentiepin kunnen gebruiken.

We willen ook een weerstand van 1 Mohm tussen PD2 en aarde. We gaan PD2 instellen als een uitgangspin op 0V en we zullen op een positieve rand op die pin triggeren. We willen dat de rand onmiddellijk verdwijnt wanneer we de knop loslaten, dus we zullen deze "pull down" -weerstand invoegen.

De reden dat we de knop willen, is omdat we onze analoog-naar-digitaal-converter willen activeren vanaf pin INT0 op de chip, die ook PD2 is. Uiteindelijk zouden we willen dat de toetsaanslag zowel de ADC activeert als de invoer kan worden geconverteerd zonder een aparte knop, maar vanwege de manier waarop de timing werkt, zullen we beginnen met een aparte knop om de ADC te activeren en zodra we alles strijken de bugs eruit hebben en er zeker van zijn dat alles naar behoren werkt, dan zullen we de ruis- en timingproblemen aanpakken die gepaard gaan met triggering van dezelfde druk op de knop die we willen lezen.

Dus voorlopig is de manier waarop het werkt, dat we een toets ingedrukt houden, dan op de knop drukken om de ADC te activeren, en dan loslaten en hopelijk verschijnt de binaire waarde van de knop die we hebben ingedrukt op de analysator.

Dus laten we wat code schrijven die dat zal bereiken.

Stap 6: Welke tuimelschakelaars moeten we instellen?

Welke tuimelschakelaars moeten we instellen?
Welke tuimelschakelaars moeten we instellen?

Laten we eerst nadenken over hoe we dit gaan coderen, zodat de controller de invoer van het toetsenbord kan lezen en deze kan omzetten in een numerieke waarde die overeenkomt met de knop die werd ingedrukt. We gaan de analoog naar digitaal converter (ADC) gebruiken dat is ingebouwd in de Atmega328p. We zullen AREF gebruiken als onze referentiespanning en onze toetsenborduitgang wordt aangesloten op PortC0 of PC0. Merk op dat deze pin ook ADC0 wordt genoemd voor Analoog-naar-Digitaal Converter 0. Het is misschien een goed idee om Paragraaf 12.4 over interrupts voor de ATmega328P en ook hoofdstuk 24 over de Analoog-naar-Digitaal Converter door te lezen voordat we gestart zijn of in ieder geval die secties gereed hebben voor referentie. Om de microcontroller zo in te stellen dat hij weet wat hij met een analoog ingangssignaal moet doen en hoe hij met ons programma moet omgaan, moeten we eerst een paar van de verschillende ADC's instellen gerelateerde registerbits. Deze zijn in wezen gelijk aan de oude tuimelschakelaars op de eerste computers. Je zet ofwel een schakelaar AAN of UIT, of zelfs verder naar achteren zou je kabels tussen het ene stopcontact en het andere steken, zodat elektronen die die splitsing in de weg bereiken, een poort gesloten en een andere open zouden vinden, waardoor het een ander pad in het doolhof van circuits en dus het uitvoeren van een andere logische taak. Bij het coderen in assembler hebben we nauwe toegang tot deze functies van de microcontroller, wat in de eerste plaats een van de aantrekkelijke dingen is om het te doen. Het is meer "hands on" en er gebeurt veel minder "achter de schermen" als het ware. Beschouw het instellen van deze registers dus niet als een vervelende taak. Dit is wat assembler interessant maakt! We krijgen een heel persoonlijke relatie met de innerlijke werking en logica van de chip en zorgen ervoor dat deze precies doet wat we willen - niet meer en niet minder. Geen verspilde klokcycli. Dus hier is een lijst met de schakelaars die we moeten instellen:

  1. Schakel de Power Reduction ADC-bit, PRADC, uit, dit is bit 0 van het PRR-register, want als deze bit is ingeschakeld, wordt de ADC uitgeschakeld. Het vermogensreductieregister is in wezen een manier om verschillende dingen die stroom verbruiken uit te schakelen wanneer u ze niet nodig hebt. Omdat we de ADC gebruiken, willen we ervoor zorgen dat deze niet op deze manier wordt uitgeschakeld. (Zie PRADC op pagina 46)
  2. Selecteer het analoge ingangskanaal als ADC0 door MUX3…0 uit te schakelen in het ADC Multiplexer Selection (ADMUX) register (zie tabel 24-4 pagina 249). Deze zijn standaard al uitgeschakeld, dus we hoeven dit niet echt te doen. Ik neem het echter op, want als je ooit een andere poort dan ADC0 gebruikt, moet je deze schakelaars dienovereenkomstig schakelen. Verschillende combinaties van MUX3, MUX2, MUX1, MUX0 stellen u in staat om een van de analoge poorten als uw ingang te gebruiken en u kunt deze ook direct wijzigen als u naar een heleboel verschillende analoge signalen tegelijk wilt kijken.
  3. Schakel de REFS0- en REFS1-bits in het ADMUX-register uit, zodat we AREF als onze referentiespanning zullen gebruiken in plaats van een interne referentie (zie pagina 248).
  4. Zet het ADLAR-bit aan in ADMUX zodat het resultaat "links aangepast" is, we zullen deze keuze in de volgende stap bespreken.
  5. Stel de ADC0D-bit in het Digital Input Disable Register (DIDR0) in om de digitale invoer uit te schakelen naar PC0. We gebruiken die poort voor analoge invoer, dus we kunnen net zo goed de digitale invoer uitschakelen.
  6. Stel ISC0 en ISC1 in in het External Interrupt Control Register A (EICRA) om aan te geven dat we op de stijgende flank van een spanningssignaal naar de INT0-pin (PD2) willen triggeren, zie pagina 71.
  7. Wis bits INT0 en INT1 in het External Interrupt Mask Register (EIMSK) om aan te geven dat we geen interrupts op deze pin gebruiken. Als we interrupts op deze pin zouden inschakelen, zouden we een interrupt-handler op adres 0x0002 nodig hebben, maar in plaats daarvan stellen we het zo in dat een signaal op deze pin de ADC-conversie activeert, waarvan de voltooiing wordt afgehandeld door de ADC-conversie complete interrupt op adres 0x002A. Zie pagina 72.
  8. Stel de ADC Enable (ADEN)-bit (bit 7) in het ADC-besturings- en statusregister A (ADCSRA) in om de ADC in te schakelen. Zie pagina 249.
  9. We zouden een enkele conversie kunnen starten door de ADC-startconversiebit (ADSC) in te stellen elke keer dat we het analoge signaal wilden lezen, maar voor nu hebben we liever dat het automatisch wordt gelezen wanneer iemand op de knop drukt, dus in plaats daarvan zullen we de ADC inschakelen Autotrigger Enable (ADATE) bit in het ADCSRA-register zodat triggering automatisch gebeurt.
  10. We hebben ook de ADPS2..0-bits (de AD Prescalar-bits) ingesteld op 111, zodat de ADC-klok de CPU-klok is gedeeld door een factor 128.
  11. We zullen de bron van de ADC-triggering selecteren als PD2, ook wel INT0 (External Interrupt Request 0) genoemd. Dit doen we door de verschillende bits in het ADCSRB-register om te wisselen (zie Tabel 24-6 op pagina 251). We zien aan de tabel dat we ADTS0 uit, ADTS1 aan en ADTS2 uit willen, zodat de ADC die pin activeert. Merk op dat als we de analoge poort continu wilden samplen, alsof we een continu analoog signaal zouden lezen (zoals geluidsbemonstering of zoiets), we dit in de Free Running-modus zouden zetten. De methode die we gebruiken om triggering op PD2 in te stellen, activeert een ADC-lezing van de analoge poort PC0 zonder een onderbreking te veroorzaken. De onderbreking komt wanneer de conversie is voltooid.
  12. Schakel de ADC Interrupt Enable (ADIE) bit in het ADCSRA-register in, zodat wanneer de analoog-naar-digitaal-conversie is voltooid, deze een interrupt genereert waarvoor we een interrupt-handler kunnen schrijven en op.org 0x002A kunnen plaatsen.
  13. Stel de I-bit in SREG in om interrupts in te schakelen.

Oefening 1: Zorg ervoor dat u de relevante secties in de datasheet voor elk van de bovenstaande instellingen leest, zodat u begrijpt wat er aan de hand is en wat er zou gebeuren als we ze zouden wijzigen in alternatieve instellingen.

Stap 7: Schrijf de onderbrekingshandler

In de laatste stap zagen we dat we het zo hebben ingesteld dat een stijgende flank gedetecteerd op PD2 een analoog naar digitaal conversie op PC0 zal activeren en wanneer deze conversie voltooid is, zal het een ADC Conversion Complete interrupt geven. Nu willen we iets doen met deze interrupt. Als u Tabel 12-6 op pagina 65 bekijkt, ziet u een lijst met mogelijke onderbrekingen. We hebben de RESET-interrupt op adres 0x0000 en de Timer/Counter0 Overflow-interrupt op adres 0x0020 al gezien in eerdere Tutorials. Nu willen we kijken naar de ADC-interrupt die we zien in de tabel op adres 0x002A. Dus aan het begin van onze assembleertaalcode hebben we een regel nodig die luidt:

.org 0x002Arjmp ADC_int

die naar onze interrupt-handler met het label ADC_int springt wanneer de ADC een conversie heeft voltooid. Dus hoe moeten we onze interrupt-handler schrijven? De manier waarop de ADC werkt, is door de volgende berekening uit te voeren:

ADC = Vin x 1024 / Vref

Dus laten we eens kijken wat er gebeurt als ik op de "herkiezen"-knop op het toetsenbord druk. In dat geval zal de spanning op PC0 veranderen naar een waarde, zeg 1,52V, en aangezien Vref 5V is, hebben we:

ADC = (1,52V) x 1024 / 5V = 311.296

en dus zou het verschijnen als een 311. Als we dit terug wilden converteren naar een spanning, zouden we de berekening gewoon omkeren. We hoeven dit echter niet te doen, omdat we niet geïnteresseerd zijn in de werkelijke spanningen, alleen om ze te onderscheiden. Wanneer de conversie is voltooid, wordt het resultaat opgeslagen in een 10-bits getal dat in ADCH- en ADCL-registers is geplaatst en we hebben ervoor gezorgd dat het "links aangepast" is, wat betekent dat de 10-bits beginnen bij bit 7 van ADCH en naar beneden gaan naar bit 6 van ADCL (er zijn in totaal 16 bits in deze twee registers en we gebruiken er maar 10, dus 1024 kanalen). We zouden het resultaat "rechts aangepast" kunnen hebben als we wilden door het ADLAR-bit in het ADMUX-register te wissen. De reden dat we voor links aangepast hebben gekozen, is omdat onze signalen ver genoeg uit elkaar liggen dat de laatste twee cijfers van het kanaalnummer niet relevant zijn en zijn waarschijnlijk gewoon ruis, dus we zullen de toetsaanslagen onderscheiden met alleen de bovenste 8 cijfers, met andere woorden, we hoeven alleen maar naar ADCH te kijken om erachter te komen op welke knop is gedrukt. Onze interrupt-handler moet dus gewoon het nummer uit de ADCH lezen register, converteer dat nummer naar een toetsenbordwaarde en stuur die waarde vervolgens naar onze registeranalysator-LED's, zodat we kunnen verifiëren dat het indrukken van een "9", bijvoorbeeld, ervoor zorgt dat de LED's die overeenkomen met "00001001" oplichten. Voordat we dat doen hoewel we eerst moeten zien wat er in ADCH verschijnt als we op de verschillende knoppen drukken. Laten we dus gewoon een eenvoudige interrupt-handler schrijven die de inhoud van ADCH naar het display van de analysator stuurt. Dus dit is wat we nodig hebben:

ADC_int:lds analyzer, ADCH; laad de waarde van ADCH in onze analyzersbi EIFR, 0; wis de externe interruptvlag zodat deze klaar is om opnieuw te gaanreti

Inmiddels zou je in staat moeten zijn om de code uit onze analyser in tutorial 5 te kopiëren en deze interrupt en de schakelinstellingen toe te voegen en uit te voeren. Oefening 2: Schrijf de code en voer deze uit. Zorg ervoor dat u de ADCH-weergave op het display van uw analysator krijgt. Probeer meerdere keren op dezelfde toets te drukken. Krijg je altijd dezelfde waarde in ADCH?

Stap 8: Breng de toetsaanslagwaarden in kaart

Breng de toetsaanslagwaarden in kaart
Breng de toetsaanslagwaarden in kaart

Wat we nu moeten doen, is de waarden in ADCH omzetten in getallen die overeenkomen met de toets die is ingedrukt. We doen dit door de inhoud van ADCH voor elke toetsaanslag uit te schrijven en dat vervolgens om te zetten in een decimaal getal zoals ik deed in de afbeelding. In onze routine voor het afhandelen van interrupts zullen we een hele reeks waarden beschouwen als overeenkomend met elke toetsaanslag, zodat de ADC alles in dat bereik aan een bepaalde toetsdruk toewijst.

Oefening 3: Voer deze ma-p.webp

Dit is wat ik voor de mijne heb (de jouwe zal zeer waarschijnlijk anders zijn). Merk op dat ik het heb ingesteld met een reeks waarden voor elke toetsaanslag.

ADC_int:; Externe interrupt-handlerclr-analysator; bereid je voor op nieuwe nummerds buttonH, ADCH; ADC wordt bijgewerkt wanneer ADCH wordt gelezen clccpi buttonH, 240brlo PC+3; als ADCH groter is, dan is het een 1ldi-analysator, 1; dus laad-analysator met een 1rjmp-retour; en retourneer clccpi buttonH, 230; als ADCH groter is dan een 2brlo PC+3ldi analyser, 2rjmp return clccpi buttonH, 217brlo PC+3ldi analyzer, 3rjmp return clccpi buttonH, 203brlo PC+3ldi analyser, 4rjmp return clccpi buttonH, 187brlo PC+3ldi analyzer, ccpjmp return, 155brlo PC+3ldi-analysator, 6rjmp retour clccpi-knopH, 127brlo PC+3ldi-analysator, 255; we zullen flash instellen als alle onrjmp return clccpi buttonH, 115brlo PC+3ldi analyzer, 7rjmp return clccpi buttonH, 94brlo PC+3ldi analyzer, 8rjmp return clccpi buttonH, 62brlo PC+3ldi analyzer, 9rjmp return clccpi buttonH, 37brlo PC+3ldi analyzer, 0b11110000; sterretje is bovenste helft onrjmp return clccpi buttonH, 28brlo PC+3ldi analyzer, 0rjmp return clccpi buttonH, 17brlo PC+3ldi analyzer, 0b00001111; hekje is onderste helft onrjmp return clccpi buttonH, 5brlo PC+3ldi analyzer, 0b11000011; opnieuw kiezen is bovenste 2 onderste 2rjmp return ldi-analysator, 0b11011011; anders is er een fout opgetreden return:reti

Stap 9: code en video voor versie 1

Ik heb mijn code voor deze eerste versie van het toetsenbordstuurprogramma bijgevoegd. In deze moet u op de toets drukken en vervolgens op de knop om ervoor te zorgen dat de ADC de invoer van het toetsenbord leest. Wat we liever hebben is geen knop, maar het signaal om de conversie uit te voeren komt van de toetsaanslag zelf. Oefening 3: Monteer en upload deze code en probeer het. Mogelijk moet u de verschillende conversiedrempels wijzigen om overeen te komen met uw toetsdrukspanningen, omdat deze waarschijnlijk verschillen van de mijne. Wat gebeurt er als je een invoer van het toetsenbord probeert te gebruiken voor zowel de ADC0 als voor de externe interrupt-pin in plaats van via een knop? Ik zal ook een video bijvoegen van de werking van deze eerste versie van onze keypress-driver. Dat zul je merken in mijn code is er een sectie die de Stack Pointer initialiseert. Er zijn verschillende registers die we misschien willen pushen en uit de stapel willen halen wanneer we variabelen manipuleren en wat niet, en er zijn ook registers die we later misschien willen opslaan en herstellen. SREG is bijvoorbeeld een register dat niet wordt bewaard voor alle onderbrekingen, dus de verschillende vlaggen die worden ingesteld en gewist als gevolg van bewerkingen, kunnen worden gewijzigd als er zich ergens een onderbreking voordoet. Het is dus het beste als u SREG aan het begin van een interrupt-handler op de stapel duwt en deze er vervolgens weer uit knalt aan het einde van de interrupt-handler. Ik heb het in de code geplaatst om te laten zien hoe het wordt geïnitialiseerd en om te anticiperen op hoe we het later nodig zullen hebben, maar aangezien het ons niet kan schelen wat er met SREG gebeurt tijdens interrupts in onze code, heb ik de stapel hiervoor niet gebruikt. dat ik de shift-bewerking heb gebruikt om verschillende bits in registers in te stellen bij het initialiseren. Bijvoorbeeld in de regel:

ldi-temp, (1<> st EICRA, temp

De opdracht "<<" in de eerste regel code hierboven is een shift-bewerking. Het neemt in wezen het binaire getal 1, dat 0b00000001 is, en schuift het naar links met het getal ISC01. Dit is de positie van het bit met de naam ISC01 in het EICRA-register. Aangezien ISC01 bit 1 is, wordt het nummer 1 verschoven naar de linker 1-positie om 0b00000010 te worden. Evenzo is de tweede, ISC00, bit 0 van EICRA en dus is de verschuiving van het getal 1 nulposities naar links. Als je nog eens kijkt naar het bestand m328Pdef.inc dat je in de eerste tutorial hebt gedownload en sindsdien evrr gebruikt, zul je zien dat het slechts een lange lijst van ".equ"-statements is. Je zult zien dat ISC01 gelijk is aan 1. De assembler vervangt elk exemplaar ervan door 1 voordat hij zelfs maar iets begint te assembleren. Het zijn gewoon namen voor registerbits om ons mensen te helpen bij het lezen en schrijven van code. Nu is de verticale lijn tussen de twee verschuivingsbewerkingen hierboven een logische "of" -bewerking. Hier is de vergelijking:

0b00000010 | 0b00000001 = 0b00000011

en dit is wat we laden (met "ldi") in temp. De reden dat mensen deze methode gebruiken om waarden in een register te laden, is dat je de naam van het bit kunt gebruiken in plaats van alleen een getal, waardoor de code veel gemakkelijker te lezen is. Er zijn ook twee andere technieken die we hebben gebruikt. We gebruiken de instructies "ori" en "andi". Hiermee kunnen we respectievelijk bits SET en CLEAR zonder een van de andere bits in een register te veranderen. Bijvoorbeeld, toen ik gebruikte

ori temp, (1

deze "of"s temp met 0b00000001 die een 1 in het nulde bit plaatst en de rest ongewijzigd laat. Ook toen we schreven

andi temp, 0b11111110

dit verandert het nulde bit van temp in een 0 en laat de rest ongewijzigd.

Oefening 4: Je moet de code doornemen en ervoor zorgen dat je elke regel begrijpt. Misschien vind je het interessant om betere methoden te vinden om dingen te doen en een beter programma te schrijven. Er zijn honderd manieren om dingen te coderen en ik ben er vrij zeker van dat je een veel betere manier kunt vinden dan de mijne. U kunt ook (de hemel verhoede!) fouten en weglatingen vinden. In dat geval hoor ik dat graag, zodat ze gerepareerd kunnen worden.

Oké, laten we nu eens kijken of we die overbodige knop kunnen verwijderen…

Stap 10: Code voor versie 2

De eenvoudigste manier om van de knop af te komen, is door hem helemaal te verwijderen, de invoer naar PB2 te vergeten en de ADC in "Free Running Mode" te schakelen.

Met andere woorden, verander eenvoudig het ADCSRB-register zodat ADTS2, ADTS1 en ADTS0 allemaal nullen zijn.

Stel vervolgens de ADSC-bit in ADCSRA in op 1, waarmee de eerste conversie wordt gestart.

Upload het nu naar uw microcontroller en u zult zien dat het juiste nummer op het display verschijnt terwijl u op de knop drukt en alleen terwijl u op de knop drukt. Dit komt omdat de ADC continu de ADC0-poort bemonstert en de waarde weergeeft. Wanneer u uw vinger van de knop haalt, zal de "button bounce" ervoor zorgen dat een paar willekeurige waarden zeer snel optreden en dan zal het terugkeren naar 0V-invoer. In onze code zien we deze 0V verschijnen als 0b11011011 (omdat de toetsdruk `0' al de 0b00000000 weergavewaarde gebruikt)

Dit is echter niet de oplossing die we willen om twee redenen. Eerst willen we de knop niet ingedrukt houden. We willen er één keer op drukken en het nummer laten zien (of gebruiken in een nieuwe code in een latere tutorial). Ten tweede willen we de ADC0 niet continu samplen. We willen dat het een enkele meting doet, het omzet en vervolgens slaapt totdat een nieuwe toetsdruk een nieuwe conversie activeert. De vrijlopende modus is het beste als het enige dat u wilt dat de microcontroller doet, voortdurend een analoge invoer leest, bijvoorbeeld als u realtime temperaturen of zoiets wilt weergeven.

Dus laten we nog een andere oplossing zoeken…

Stap 11: Hoe komen we van de knop af? Versie 3

Hoe komen we van de knop af? Versie 3
Hoe komen we van de knop af? Versie 3

Er zijn talloze manieren waarop we verder kunnen. Eerst konden we hardware toevoegen om van de knop af te komen. We kunnen bijvoorbeeld proberen een transistor in het circuit te plaatsen op de uitgangslijn van de toetsaanslag, zodat er een klein straaltje stroom van de uitgang nodig is en een 5V-puls naar de onderbrekingspen PD2 wordt gestuurd.

Dat zou echter op zijn minst waarschijnlijk te veel lawaai maken en in het slechtste geval zou het niet genoeg tijd geven voor een nauwkeurige toetsaanslag, aangezien de spanningsuitgang van het toetsenbord geen tijd zou hebben om te stabiliseren voordat de ADC-waarde wordt vastgelegd.

Dus we komen liever met een software-oplossing. Wat we zouden willen doen is een interrupt toevoegen aan de PD2-pin en er een interrupt-handler voor schrijven die een enkele lezing van de toetsenbordpin oproept. Met andere woorden, we verwijderen de autotrigger-interrupt van de ADC en voegen een externe interrupt toe die de ADC erin oproept. Op die manier komt het signaal om de ADC te lezen nadat het PD2-signaal al is opgetreden en dit kan de zaken voldoende tijd geven om te stabiliseren tot een nauwkeurige spanning voordat de PC0-pin wordt gelezen en geconverteerd. We zouden nog steeds een onderbreking van de ADC-voltooiing hebben die het resultaat aan het einde naar het display van de analysator stuurt.

Zin? Nou, laten we het doen…

Bekijk de bijgevoegde nieuwe code.

U ziet de volgende wijzigingen:

  1. We hebben een rjmp toegevoegd op adres.org 0x0002 om de externe INT0-interrupt af te handelen
  2. We hebben het EIMSK-register gewijzigd om aan te geven dat we willen onderbreken op de INT0-pin
  3. We hebben de ADATE-pin in het ADCSRA-register gewijzigd om autotriggering uit te schakelen
  4. We hebben de ADCSRB-instellingen verwijderd, omdat ze niet relevant zijn wanneer ADATE is uitgeschakeld
  5. We hoeven de externe trigger-vlag niet langer opnieuw in te stellen, aangezien de INT0-interrupt-routine dit automatisch doet wanneer deze is voltooid. wis die vlag met de hand.

Nu noemen we in de interrupt-handler eenvoudig een enkele conversie van de ADC.

Oefening 5: Voer deze versie uit en kijk wat er gebeurt.

Stap 12: Code en video voor de werkende versie

Zoals we bij de laatste versie zagen, werkt de knoponderbreking niet erg goed omdat de onderbreking wordt geactiveerd op een stijgende flank naar pin PD2 en vervolgens roept de interrupthandler de ADC-conversie aan. De ADC krijgt dan echter de spanningswaarde voordat deze is gestabiliseerd en dus leest hij onzin.

Wat we nodig hebben is om een vertraging te introduceren tussen de interrupt op PD2 en de ADC-lezing op PC0. Dit doen we door een timer/teller, een counter overflow interrupt en een delay routine toe te voegen. Gelukkig weten we dit al uit Tutorial 3! Dus we zullen de relevante code daar gewoon kopiëren en plakken.

Ik heb de resulterende code gegeven en een video die deze in werking laat zien.

U zult merken dat de metingen niet zo nauwkeurig zijn als men zou hopen. Dit komt waarschijnlijk door een aantal bronnen:

  1. we tikken op de spanningsuitgang van het toetsenbord om op PD2 te activeren, wat de uitlezing in PC0 beïnvloedt.
  2. we weten niet echt hoe lang we moeten wachten na de trigger om de beste meting te krijgen.
  3. het duurt een paar cycli voordat de ADC-conversie is voltooid, wat betekent dat we niet snel op het toetsenbord kunnen schieten.
  4. er is waarschijnlijk ruis in het toetsenbord zelf.
  5. enzovoort…

Dus hoewel we erin geslaagd zijn om het toetsenbord te laten werken, en we het nu in toepassingen kunnen gebruiken door de toetsaanslagwaarden op een andere manier te gebruiken in plaats van ze alleen naar het display van de analysator te sturen, is het niet erg nauwkeurig en het is erg vervelend. Daarom denk ik dat de beste manier om toetsenborden te bedraden is om simpelweg elke uitgang van het toetsenbord in een andere poort te steken en te beslissen welke toets wordt ingedrukt door welke poorten een spanning zien. Dat is gemakkelijk, zeer snel en zeer nauwkeurig.

In feite zijn er maar twee redenen waarom men een toetsenbord zou willen besturen zoals we hier hebben gedaan:

  1. Het gebruikt slechts 2 van de pinnen op onze microcontroller in plaats van 8.
  2. Het is een geweldig project om verschillende aspecten van de ADC op de microcontroller te laten zien, die verschillen van de standaard dingen die je daar kunt vinden, zoals temperatuurmetingen, het draaien van potentiometers, enz. Ik wilde een voorbeeld van getriggerde enkele metingen en externe pin auto-triggering in plaats van alleen de vrij draaiende CPU-opslokkende modus.

Hoe dan ook, hier is een laatste paar oefeningen voor je:

Oefening 6: Herschrijf de ADC-conversiecompleet interrupt-handler om een opzoektabel te gebruiken. D.w.z. Zodat het de analoge waarde test met het eerste item in de tabel en als het groter is, keert het terug van de interrupt, zo niet, dan verhoogt het Z naar het volgende item in de tabel en vertakt het weer terug naar de test. Dit zal de code verkorten en de interruptroutine opschonen en er mooier uit laten zien. (Ik zal een mogelijke oplossing geven als de volgende stap) Oefening 7: Sluit je toetsenbord aan op 8 pinnen op de microcontroller en schrijf de eenvoudige driver ervoor en ervaar hoeveel leuker het is. Kun je een paar manieren bedenken om onze methode beter te laten werken?

Dat is alles voor deze tutorial. Ik heb de definitieve versie met wijzers bijgevoegd. Naarmate we dichter bij ons uiteindelijke doel komen, zullen we in Tutorial 9 nogmaals het toetsenbord gebruiken om te laten zien hoe we schermen met zeven segmenten ermee kunnen bedienen (en iets interessants bouwen dat de extra toetsen op het toetsenbord van de telefoon gebruikt) en dan zullen we schakel in plaats daarvan over op het besturen van dingen met het indrukken van een knop (aangezien die methode beter past bij het eindproduct waar we met deze tutorials naartoe bouwen) en we zullen het toetsenbord gewoon op de plank leggen.

Tot de volgende keer!

Aanbevolen: