Indholdsfortegnelse:

AVR Assembler Tutorial 7: 12 trin
AVR Assembler Tutorial 7: 12 trin

Video: AVR Assembler Tutorial 7: 12 trin

Video: AVR Assembler Tutorial 7: 12 trin
Video: Getting Started with Atmel Studio 7 - Episode 12 - AVR® MCU Simulator Debugging 2024, November
Anonim
Vejledning til AVR -samler 7
Vejledning til AVR -samler 7

Velkommen til selvstudium 7!

I dag vil vi først vise, hvordan man fjerner et tastatur, og derefter viser, hvordan man bruger de analoge inputporte til at kommunikere med tastaturet. Vi vil gøre dette ved hjælp af afbrydelser og en enkelt ledning som input. Vi tilslutter tastaturet, så hvert tastetryk sender en unik spænding til den analoge indgang, som giver os mulighed for at skelne ved den spænding, som tasten blev trykket på. Derefter udsender vi det tryk, der er presset til vores registeranalysator for at vise, at alt sker, som det skal. Der er en række faldgruber, som du kan løbe ind i, når du bruger Analog to Digital Converter (ADC) i ATmega328p, og så vil vi tage tingene i et par faser på vejen for at prøve at finde ud af, hvordan man undgår dem. Vi vil også se, hvorfor brug af den analoge til digitale konverter ikke er den bedste måde at styre et tastatur på, selvom den bruger færre porte på din mikrokontroller. I denne vejledning skal du bruge:

  1. et tastatur. Du kan købe en, eller du kan gøre, hvad jeg gjorde, og rense en.
  2. 2 kvindelige overskrifter til tastaturet (hvis du fjerner en)
  3. tilslutning af ledninger
  4. et brødbræt
  5. 4 1 Kohm modstande
  6. 1 15 Kohm modstand
  7. 1 3.3 Kohm modstand
  8. 1 180 ohm modstand
  9. 1680 ohm modstand
  10. et digitalt multimeter
  11. din analysator fra selvstudium 5

Det kan være en god idé at springe de første trin over, hvis du allerede har et tastatur og ikke behøver at rense et.

Her er et link til den komplette samling af mine AVR-assembler-selvstudier:

Trin 1: Ryd et tastatur 1

Rens et tastatur 1
Rens et tastatur 1
Rens et tastatur 1
Rens et tastatur 1
Rens et tastatur 1
Rens et tastatur 1
Rens et tastatur 1
Rens et tastatur 1

For længe siden, da selv dine bedsteforældre var børn, plejede folk at bruge disse underlige apparater, der havde lange kabler tilsluttet væggen, til at kommunikere med hinanden. De blev kaldt "telefoner" og var normalt billige plastik ting, der lavede en irriterende lyd, når nogen ringede til dig (ikke at dagens "Justin Bieber" ringetoner ikke er lige så irriterende). Under alle omstændigheder havde disse enheder tastaturer på dem, som ganske enkelt var kabelforbundne, og det er derfor let at skrabe, og de har 2 ekstra taster på dem ("genopkald" og "flash") fra tastaturerne, du kan købe, som du måske vil genbruge som "piletaster", "menutaster" eller noget andet. Så vi starter med at fjerne et tastatur fra en gammel telefon. Tag først telefonen (jeg bruger en GE som vist på billederne) og lir den fra hinanden for at afsløre ledningerne. Tag derefter en mejsel og tag de små plastikknapper af, der holder tastaturet på, og fjern tastaturet.

Trin 2: Ryd et tastatur 2

Rens et tastatur 2
Rens et tastatur 2
Rens et tastatur 2
Rens et tastatur 2
Rens et tastatur 2
Rens et tastatur 2

Tag nu en PVC -sav og skær plasten rundt omkring nøglehullerne og skær derefter rundt i kanten for at få dybden til højre og efterlade et tyndt tastatur.

Sæt derefter tastaturet på igen ved hjælp af de små pinde, der er tilbage, efter at du havde klippet toppen af dem i det sidste trin, og brug et loddejern til blot at stikke det varme jern ind i hvert pindehul, som vil smelte plasten og sprede det ud over bunden af tastaturet, der danner nye "knapper", som holder tastaturet på plads som før.

Jeg kan godt lide at rense de tre højttalere og måske de andre ting som switches og hvad der ikke er på tavlen. Denne gang har jeg dog ikke tænkt mig at rense switches og sådan noget, fordi vi har andre mål i øjeblikket. Der er også en TA31002 lineær IC derinde, som er en telefonringning. Databladet findes let og downloades online, hvilket giver pinout og funktioner. Så jeg vil lade det lodde til brættet for nu og derefter lege med det senere. Jeg vil gerne tilslutte det til et oscilloskop og se, hvilke seje signaler jeg kan få ud af det. Måske endda lave en dørklokke ud af det. Hvem ved.

Anyway, når du er færdig med at ødelægge telefonen og rydde delene, afslutter vi vores tastatur.

Trin 3: Rens et tastatur 3

Rens et tastatur 3
Rens et tastatur 3
Rens et tastatur 3
Rens et tastatur 3
Rens et tastatur 3
Rens et tastatur 3

Brug en aflodningsvæv, og fjern båndkablerne fra bunden af tastaturet, og sørg for, at hullerne i printkortet er klare, og fastgør derefter to hunhoveder på brættet, hvor hullerne er. Du bliver sandsynligvis nødt til at klippe dine overskrifter ned, så de er 4-benede overskrifter.

Nu hvor overskrifterne er fastgjort, kan du koble det til et brødbræt, tage et multimeter og teste nøglerne ved at stikke multimeteret over tilfældige stifter og måle modstanden. Dette giver dig mulighed for at kortlægge nøglerne. Det er svært at se, hvordan nøglerne er forbundet til output ved at se på kredsløbet, men hvis du bruger et multimeter, kan du tilslutte det til to pins og derefter trykke på knapperne, indtil du ser et tal på skærmen i stedet for et åbent kredsløb. Dette vil være pinout for den nøgle.

Kort alle nøglerne til output pins på denne måde.

Trin 4: Tilslut tastaturet

Tilslut tastaturet
Tilslut tastaturet
Tilslut tastaturet
Tilslut tastaturet

Følg nu ledningsdiagrammet, og led tastaturet til dit brødbræt.

Hvordan dette kommer til at fungere er, at vi sætter 5V ind på venstre side, og højre side går til GND. Den første pin til højre i diagrammet går ind i den første af vores analoge ben på Atmega328p mikrokontroller. Når der ikke er trykket på nogen knapper, vil signalet være 0V, og når der trykkes på hver af de forskellige knapper, vil indgangen til den analoge port ligge mellem 0V og 5V med en anden mængde, afhængigt af hvilken tast der blev trykket på. Vi valgte modstandsværdierne, så hver sti ville indeholde en modstand, der var forskellig fra resten. Den analoge port på mikrokontrolleren tager et analogt signal og opdeler det i 1024 forskellige kanaler mellem 0V og 5V. Det betyder, at hver kanal har en bredde på 5V/1024 = 0,005 V/kanal = 5 mV/kanal. Så den analoge port kan skelne indgangsspændinger, så længe de adskiller sig med mere end 5 mV. I vores tilfælde har vi valgt modstandsværdier, så to tastetryk sender et spændingssignal, der adskiller sig mere end dette, så mikrokontrolleren let skal kunne bestemme, hvilken tast der blev trykket på. Det store problem er, at hele systemet er meget støjende, så vi bliver nødt til at vælge en række spændinger, der skal tilknyttes hvert enkelt tryk på knappen - men vi kommer ind på det lidt senere.

Bemærk, at vi er i stand til at styre et tastatur med 14 knapper ved hjælp af kun en enkelt indgangslinje til controlleren. Det er et af de nyttige aspekter ved analoge indgange.

Nu er vores første forsøg på at styre tastaturet at få et tastetryk til at forårsage en afbrydelse, afbrydelsesprogrammet vil læse den analoge indgangsport og afgøre, hvilken tast der blev trykket på, og derefter vil det udsende dette nummer til vores registeranalysator -underprogram, der vil vise nøgleværdi i binært på vores 8 lysdioder, som vi konfigurerede i selvstudie 5.

Trin 5: Tilslut tastaturet til din analysator

Led tastaturet til din analysator
Led tastaturet til din analysator
Led tastaturet til din analysator
Led tastaturet til din analysator

Billederne viser, hvordan vi vil koble tastaturet til mikrokontrolleren, så vi kan se output på vores analysator display. I det væsentlige kører vi simpelthen output fra tastaturet til PortC pin 0, som også kaldes ADC0 på ATmega328P.

Der er dog et par ekstra ting. Vi kommer også til at koble en knap til PD2. Dvs. tag en ledning fra din 5V -skinne til en knap og fra den anden side af knappen til PD2, og endelig vil vi afbryde AREF -stiften fra vores 5V -skinne og i stedet lade den være afbrudt. Vi kunne indsætte en 0,1 mikrofarad afkoblingskondensator, hvis vi ville. Dette er en keramisk kondensator med en 104 skrevet på. De to første cifre er tallet og det sidste ciffer er effekten på 10 vi multiplicerer det med for at få et svar i picofarads (pico betyder 10^-12), Så 104 betyder 10 x 10^4 picofarads, hvilket er det samme som 100 nanofarads (nano betyder 10^-9), hvilket er det samme som 0,1 mikrofarad (mikro betyder 10^-6). Anyway, alt dette gør er at stabilisere AREF -stiften, når vi kan bruge den som vores referencestift.

Vi ønsker også en 1 Mohm modstand mellem PD2 og jord. Vi kommer til at indstille PD2 som en output pin på 0V, og vi vil udløse på en positiv kant ved den pin. Vi vil have, at kanten forsvinder med det samme, når vi slipper knappen, så vi vil indsætte denne "pull down" -modstand.

Grunden til, at vi vil have knappen, er, fordi vi vil udløse vores Analog-til-Digital-konverter fra pin INT0 på chippen, som også er PD2. Til sidst vil vi gerne have, at tastetrykket både udløser ADC og også giver input til at blive konverteret uden at have en separat knap, men på grund af den måde, timingen fungerer på, begynder vi med at have en separat knap til at udløse ADC'en, og når vi stryger alle fejlene ud og er overbeviste om, at alt fungerer korrekt, så tager vi fat på de støj- og timingproblemer, der følger med udløser fra det samme knap tryk, som vi vil læse.

Så nu fungerer måden, vi holder en tast nede, tryk derefter på knappen for at udløse ADC'en, og slip derefter og forhåbentlig vises den binære værdi af den knap, vi skubbede, på analysatoren.

Så lad os skrive en kode, der vil opnå det.

Trin 6: Hvilke vippekontakter skal vi indstille?

Hvilke vippekontakter skal vi indstille?
Hvilke vippekontakter skal vi indstille?

Lad os først tænke på, hvordan vi skal kode dette, så controlleren kan læse input fra tastaturet og omdanne det til en numerisk værdi, der svarer til den knap, der blev trykket på. Vi skal bruge Analog to Digital Converter (ADC) der er indbygget i Atmega328p. Vi bruger AREF som vores referencespænding, og vores tastaturudgang tilsluttes PortC0 eller PC0. Bemærk, at denne pin også kaldes ADC0 for Analog-to-Digital Converter 0. Det kan være en god ide, at du læser afsnit 12.4 om afbrydelser til ATmega328P og også kapitel 24 om Analog-til-Digital-konverter, før vi får startede eller i det mindste have disse sektioner klar til reference. For at konfigurere mikrokontrolleren, så den ved, hvad den skal gøre med et analogt indgangssignal, og hvordan den interagerer med vores program, skal vi først indstille et par af de forskellige ADC relaterede register bits. Disse svarer i det væsentlige til de gamle vippekontakter på de første computere. Du slår enten en kontakt til eller fra, eller endnu længere tilbage vil du tilslutte kabler mellem en stikkontakt og en anden, så elektroner, der når den gaffel på vejen, finder en port lukket og en anden åben, hvilket tvinger den ad en anden vej i labyrinten af kredsløb og dermed udføre en anden logisk opgave. Når vi koder i samlingssprog, har vi tæt adgang til disse funktioner i mikrokontrolleren, hvilket er en af de attraktive ting ved at gøre det i første omgang. Det er mere "hands on" og langt mindre foregår "bag kulisserne" som det var. Så tænk ikke på at indstille disse registre som en kedelig opgave. Det er det, der gør montagesprog interessant! Vi får et meget personligt forhold til chipets indre virke og logik og får det til at gøre præcis, hvad vi vil have det - hverken mere eller mindre. Ingen spildte urcyklusser. Så her er en liste over de kontakter, vi skal indstille:

  1. Sluk for strømreduktion ADC -bit, PRADC, som er bit 0 i PRR -registret, da hvis denne bit er tændt, vil den lukke ADC'en. Strømreduktionsregistret er i det væsentlige en måde at lukke for forskellige ting, der bruger strøm, når du ikke har brug for dem. Da vi bruger ADC, vil vi sikre os, at den ikke er deaktiveret på denne måde. (Se PRADC på side 46)
  2. Vælg den analoge indgangskanal, der skal være ADC0, ved at slå MUX3… 0 fra i ADC Multiplexer Selection (ADMUX) -registret (se tabel 24-4 side 249) disse er allerede slukket som standard, så vi behøver ikke rigtig at gøre dette. Imidlertid inkluderer jeg det, da hvis du nogensinde bruger en anden port end ADC0, skal du skifte disse switches i overensstemmelse hermed. Forskellige kombinationer af MUX3, MUX2, MUX1, MUX0 giver dig mulighed for at bruge en hvilken som helst af de analoge porte som dit input, og du kan også ændre disse med det samme, hvis du vil se på en masse forskellige analoge signaler på én gang.
  3. Sluk for REFS0 og REFS1 bits i ADMUX -registret, så vi vil bruge AREF som vores referencespænding frem for en intern reference (se side 248).
  4. Tænd ADLAR -bit i ADMUX, så resultatet er "venstrejusteret", vi vil diskutere dette valg i det næste trin.
  5. Indstil ADC0D -bit i Digital Input Disable Register (DIDR0) for at slukke digital input til PC0. Vi bruger den port til analog indgang, så vi kan lige så godt deaktivere den digitale indgang til den.
  6. Indstil ISC0 og ISC1 i External Interrupt Control Register A (EICRA) for at angive, at vi ønsker at udløse på den stigende kant af et spændingssignal til INT0 -stiften (PD2), se side 71.
  7. Ryd bits INT0 og INT1 i External Interrupt Mask Register (EIMSK) for at angive, at vi ikke bruger afbrydelser på denne pin. Hvis vi skulle aktivere afbrydelser på denne pin, ville vi have brug for en interrupt -behandler på adressen 0x0002, men i stedet konfigurerer vi den, så et signal på denne pin udløser ADC -konverteringen, hvis afslutning håndteres af ADC -konverteringen fuldstændig afbrydelse kl. adresse 0x002A. Se side 72.
  8. Indstil ADC Enable (ADEN) bit (bit 7) i ADC kontrol og statusregister A (ADCSRA) for at aktivere ADC. Se side 249.
  9. Vi kunne starte en enkelt konvertering ved at indstille ADC start -konverteringsbiten (ADSC) hver gang vi ville læse det analoge signal, men nu vil vi hellere have det læst automatisk, når nogen trykker på knappen, så i stedet aktiverer vi ADC'en Autotrigger Aktiver (ADATE) bit i ADCSRA -registret, så udløsningen udføres automatisk.
  10. Vi indstillede også ADPS2..0 -bitene (AD Prescalar -bitene) til 111, så ADC -uret er CPU -uret divideret med en faktor 128.
  11. Vi vælger kilden til ADC -udløseren til at være PD2, som også kaldes INT0 (ekstern afbrydelsesanmodning 0). Vi gør dette ved at skifte de forskellige bits i ADCSRB-registret (se tabel 24-6 på side 251). Vi ser ved tabellen, at vi vil have ADTS0 slukket, ADTS1 tændt og ADTS2 slukket, så ADC'en vil udløse denne pin. Bemærk, at hvis vi løbende ville prøve den analoge port, som hvis vi læste et kontinuerligt analogt signal (som lydsampling eller noget), ville vi indstille dette til Free Running Mode. Den metode, vi bruger til at indstille triggering på PD2, udløser en ADC -aflæsning af den analoge port PC0 uden at forårsage en afbrydelse. Afbrydelsen kommer, når konverteringen er fuldført.
  12. Aktiver ADC Interrupt Enable (ADIE) -bitten i ADCSRA -registret, så når den analoge til digitale konvertering er fuldført, genererer den en afbrydelse, som vi kan skrive en afbrydelseshandler til og sætte på.org 0x002A.
  13. Indstil I -bit i SREG for at aktivere afbrydelser.

Øvelse 1: Sørg for at læse de relevante afsnit i databladet for hver af ovenstående indstillinger, så du forstår, hvad der foregår, og hvad der ville ske, hvis vi ændrede dem til alternative indstillinger.

Trin 7: Skriv Interrupt Handler

I det sidste trin så vi, at vi har konfigureret det, så en stigende kant, der er fundet på PD2, vil udløse en analog til digital konvertering på PC0, og når denne konvertering er fuldført, vil den kaste en ADC -konvertering fuldstændig afbrydelse. Nu vil vi gøre noget med denne afbrydelse. Hvis du undersøger tabel 12-6 på side 65, vil du se en liste over de mulige afbrydelser. Vi har allerede set RESET -afbrydelsen på adressen 0x0000 og Timer/Counter0 Overflow -afbrydelsen på adressen 0x0020 i tidligere vejledninger. Nu vil vi se på ADC -afbrydelsen, som vi ser ved tabellen, er på adressen 0x002A. Så i begyndelsen af vores samlingssprogkode skal vi bruge en linje, der lyder:

.org 0x002Arjmp ADC_int

som springer til vores interrupt -håndterer mærket ADC_int, når ADC'en har gennemført en konvertering. Så hvordan skal vi skrive vores interrupt handler? Den måde, ADC fungerer på, er ved at udføre følgende beregning:

ADC = Vin x 1024 / Vref

Så lad os se, hvad der sker, hvis jeg trykker på knappen "genopkald" på tastaturet. I så fald vil spændingen på PC0 ændre sig til en vis værdi, f.eks. 1,52V, og da Vref er på 5V, har vi:

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

og så ville det vise sig som en 311. Hvis vi ville konvertere dette tilbage til en spænding, ville vi bare vende beregningen. Vi behøver dog ikke at gøre dette, da vi ikke er interesseret i de faktiske spændinger bare for at skelne mellem dem. Når konverteringen er færdig, gemmes resultatet i et 10-bit tal placeret i ADCH og ADCL registre, og vi har fået det til at være "venstrejusteret", hvilket betyder, at 10-bitene starter ved bit 7 i ADCH og går ned til bit 6 i ADCL (der er 16 bits i alt i disse to registre, og vi bruger kun 10 af dem, dvs. 1024 kanaler). Vi kunne få resultatet "til højre justeret", hvis vi ville ved at rydde ADLAR -bit i ADMUX -registret. Grunden til, at vi vælger venstrejusteret, er fordi vores signaler er langt nok fra hinanden, at de to sidste cifre i kanalnummeret ikke er relevante og er sandsynligvis bare støj, så vi vil skelne mellem tasterne ved kun at bruge de øverste 8 cifre, med andre ord, vi behøver kun at se på ADCH for at finde ud af, hvilken knap der blev trykket på. Så vores interrupt -handler skulle simpelthen læse nummeret ud af ADCH registrer, konverter dette tal til et tastaturværdi, og send derefter denne værdi til vores registeranalysatorlysdioder, så vi kan kontrollere, at tryk på et "9" -sig vil få lysdioderne svarende til "00001001" til at lyse. Inden vi går langt selvom vi først skal se, hvad der dukker op i ADCH, når vi trykker på de forskellige knapper. Så lad os bare skrive en simpel interrupt -handler, der bare sender indholdet af ADCH til analysatorens display. Så her er, hvad vi har brug for:

ADC_int: lds analysator, ADCH; indlæse værdien af ADCH i vores analysersbi EIFR, 0; ryd det eksterne afbrydelsesflag, så det er klar til at gå igen

På nuværende tidspunkt skulle du bare kunne kopiere koden fra vores analysator i selvstudie 5 og tilføje denne afbrydelse og skifteindstillingerne og køre den. Opgave 2: Skriv koden og kør den. Se, at du får ADCH vist på din analysator display. Prøv at trykke på det samme tastetryk flere gange. Får du altid den samme værdi i ADCH?

Trin 8: Kortlæg tastaturværdierne

Kortlæg tastaturværdierne
Kortlæg tastaturværdierne

Det, vi skal gøre nu, er at konvertere værdierne i ADCH til tal, der svarer til den tast, der blev trykket på. Vi gør dette ved at skrive indholdet af ADCH for hvert tastetryk og derefter konvertere det til et decimaltal, som jeg gjorde på billedet. I vores afbrydelseshåndteringsrutine vil vi betragte en hel række værdier som svarende til hvert tastetryk, så ADC'en vil kortlægge alt inden for dette område til et givet tastetryk.

Øvelse 3: Gør denne mappng, og skriv derefter din ADC-afbrydelsesrutine igen.

Her er hvad jeg fik til mit (dit vil sandsynligvis være anderledes). Bemærk, at jeg har konfigureret det med en række værdier for hvert tastetryk.

ADC_int:; Ekstern interrupt handlerclr analysator; forberede sig på nye nummerlds -knap H, ADCH; ADC opdateres, når ADCH læses clccpi -knapH, 240brlo PC+3; hvis ADCH er større, så er det en 1ldi analysator, 1; så belastningsanalysator med et 1rjmp -retur; og return clccpi -knapH, 230; hvis ADCH er større end en 2brlo PC+3ldi analysator, 2rjmp return clccpi knapH, 217brlo PC+3ldi analysator, 3rjmp return clccpi buttonH, 203brlo PC+3ldi analysator, 4rjmp return clccpi buttonH, 187brlo PC+3ldi analysator, 5rjmp return clccpi buttonH, 155brlo PC+3ldi analysator, 6rjmp return clccpi buttonH, 127brlo PC+3ldi analysator, 255; vi vil indstille flash som alle onrjmp return clccpi knapH, 115brlo PC+3ldi analysator, 7rjmp return clccpi buttonH, 94brlo PC+3ldi analysator, 8rjmp return clccpi buttonH, 62brlo PC+3ldi analysator, 9rjmp return clccpi buttonH, 37brlo PC+3ldi analysator, 0b11110000; stjerne er øverste halvdel onrjmp return clccpi buttonH, 28brlo PC+3ldi analysator, 0rjmp return clccpi buttonH, 17brlo PC+3ldi analyzer, 0b00001111; hashtegn er nederste halvdel onrjmp return clccpi buttonH, 5brlo PC+3ldi analysator, 0b11000011; genopkald er top 2 bund 2rjmp return ldi analysator, 0b11011011; ellers opstod fejl retur: reti

Trin 9: Kode og video til version 1

Jeg har vedhæftet min kode til denne første version af tastaturdriveren. I denne skal du trykke på tasten og derefter trykke på knappen for at få ADC til at læse input fra tastaturet. Hvad vi hellere vil have, er ingen knap, men signalet om at foretage konverteringen kommer fra selve tastetrykket. Øvelse 3: Saml og upload denne kode, og prøv den. Du skal muligvis ændre de forskellige konverteringstærskler for at svare til dine tastetrykspændinger, da de sandsynligvis adskiller sig fra mine. Hvad sker der, hvis du prøver at bruge et input fra tastaturet både til ADC0 og til den eksterne afbrydelsesstift i stedet for via en knap? Jeg vedhæfter også en video af betjeningen af denne første version af vores tastaturdriver. Du vil bemærke, at i min kode er der et afsnit, der initialiserer Stack Pointer. Der er forskellige registre, som vi måske vil skubbe og poppe fra stakken, når vi manipulerer variabler og hvad-ikke, og der er også registre, som vi måske vil gemme og gendanne senere. For eksempel er SREG et register, der ikke bevares på tværs af afbrydelser, så de forskellige flag, der indstilles og ryddes som følge af operationer, kan ændres, hvis der opstår et afbrydelse midt i noget. Så det er bedst, hvis du skubber SREG videre til stakken i begyndelsen af en afbrydelseshandler og derefter springer den af igen for enden af afbrydelsesbehandleren. Jeg har placeret den i koden for at vise, hvordan den initialiseres og for at forudse, hvordan vi får brug for den senere, men da vi er ligeglade med, hvad der sker med SREG under afbrydelser i vores kode, brugte jeg ikke stakken til dette. at jeg har brugt skiftoperationen til at indstille forskellige bits i registre ved initialisering. For eksempel i linjen:

ldi temp, (1 <> st EICRA, temp

Kommandoen "<<" i den første kodelinje ovenfor er en skiftoperation. Det tager hovedsageligt det binære tal 1, som er 0b00000001 og flytter det tilbage med mængden af tallet ISC01. Dette er placeringen af den bit, der hedder ISC01 i EICRA -registret. Da ISC01 er bit 1, flyttes tallet 1 til venstre 1 -position for at blive 0b00000010. På samme måde er den anden, ISC00, bit 0 i EICRA, og derfor er forskydningen af tallet 1 nulpositioner til venstre. Hvis kig, tag et andet kig på m328Pdef.inc -filen, som du downloadede i den første vejledning og har brugt evrr siden, vil du se, at det bare er en lang liste med ".equ" -udsagn. Du vil opdage, at ISC01 er lig med 1. Assembleren erstatter hver forekomst af den med 1, før han overhovedet begynder at samle noget. De er bare navne på register bits for at hjælpe os mennesker med at læse og skrive kode. Nu er den lodrette linje mellem de to skiftoperationer ovenfor en logisk "eller" operation. Her er ligningen:

0b00000010 | 0b00000001 = 0b00000011

og det er det, vi indlæser (ved hjælp af "ldi") i temp. Grunden til at folk bruger denne metode til at indlæse værdier i et register er, at det giver en mulighed for at bruge bitens navn i stedet for bare et tal, og det gør koden meget lettere at læse. Der er også to andre teknikker, vi har brugt. Vi bruger instruktionerne "ori" og "andi". Disse giver os mulighed for at SET og CLEAR bits henholdsvis uden at ændre nogen af de andre bits i et register. For eksempel da jeg brugte

ori temp, (1

denne "eller" s temp med 0b00000001, som sætter en 1 i nul -bit og lader resten forblive uændret. Også da vi skrev

andi temp, 0b11111110

dette ændrer nulbiten af temp til en 0 og lader resten forblive uændret.

Øvelse 4: Du skal gennemgå koden og sikre dig, at du forstår hver linje. Du finder det måske interessant at finde bedre metoder til at gøre ting og skrive et bedre program. Der er hundrede måder at kode ting på, og jeg er temmelig sikker på, at du kan finde en meget bedre måde end min. Du kan også finde (himmelen forbyde!) Fejl og mangler. I så fald vil jeg helt sikkert høre om dem, så de kan rettes.

Okay, lad os nu se, om vi kan slippe af med den overflødige knap …

Trin 10: Kode til version 2

Den enkleste måde at slippe af med knappen er bare at fjerne den helt, glemme input til PB2 og bare skifte ADC til "Free Running Mode".

Med andre ord skal du blot ændre ADCSRB -registret, så ADTS2, ADTS1 og ADTS0 alle er nul.

Indstil derefter ADSC -bit i ADCSRA til 1, som starter den første konvertering.

Upload den nu til din mikrokontroller, og du vil opdage, at det korrekte nummer kommer frem på displayet, mens du trykker på knappen, og kun mens du trykker på knappen. Dette skyldes, at ADC'en løbende sampler ADC0 -porten og viser værdien. Når du tager fingeren af knappen, vil "knapstoppet" få et par tilfældige værdier til at forekomme meget hurtigt, og derefter vil det slå tilbage til 0V -input. I vores kode har vi denne 0V vist som 0b11011011 (fordi tastetrykket '0' allerede bruger visningsværdien 0b00000000)

Dette er dog ikke den løsning, vi ønsker af to grunde. Først vil vi ikke beholde knappen. Vi vil trykke på det en gang og få nummeret vist (eller brugt i en ny kode i en senere vejledning). For det andet ønsker vi ikke løbende at prøve ADC0. Vi vil have det til at tage en enkelt aflæsning, konvertere det og derefter sove, indtil et nyt tastetryk udløser en ny konvertering. Gratis driftstilstand er bedst, hvis det eneste, du vil have mikrokontrolleren til at gøre, er konstant at læse nogle analoge indgange - som hvis du ville vise temperaturer i realtid eller noget.

Så lad os finde endnu en løsning …

Trin 11: Hvordan slipper vi for knappen? Version 3

Hvordan slipper vi for knappen? Version 3
Hvordan slipper vi for knappen? Version 3

Der er mange måder, vi kan fortsætte på. Først kunne vi tilføje hardware for at slippe af med knappen. For eksempel kan vi prøve at sætte en transistor i kredsløbet ved tastaturets udgangslinje, så det ville tage en lille strøm af strømmen fra udgangen og sende en 5V puls til afbryderstiften PD2.

Det ville dog sandsynligvis være for støjende i det mindste og i værste fald ville det ikke give nok tid til en nøjagtig tastetrykaflæsning, da tastaturets spændingsudgang ikke ville nå at stabilisere sig, før ADC -aflæsningen blev registreret.

Så vi vil hellere komme med en softwareløsning. Det, vi gerne vil gøre, er at tilføje en afbrydelse på PD2 -stiften og skrive en afbrydelseshåndterer til den, som kalder en enkelt aflæsning af tastaturets pin. Med andre ord slipper vi for autotrigger -afbrydelsen fra ADC'en og tilføjer en ekstern afbrydelse, der kalder ADC'en inde i den. På den måde kommer signalet til at læse ADC'en, efter at PD2 -signalet allerede er opstået, og dette kan give tingene nok tid til at stabilisere sig til en nøjagtig spænding, før PC0 -stiften læses og konverteres. Vi ville stadig have en ADC -afslutningsafbrydelse, der sender resultatet til analysatorens display i slutningen.

Giver mening? Jamen lad os gøre det…

Tag et kig på den nye kode vedhæftet.

Du ser følgende ændringer:

  1. Vi tilføjede en rjmp på adressen.org 0x0002 til at håndtere INT0 ekstern afbrydelse
  2. Vi ændrede EIMSK -registeret for at angive, at vi vil afbryde INT0 -stiften
  3. Vi ændrede ADATE -stiften i ADCSRA -registret til at deaktivere autotriggering
  4. Vi slap med ADCSRB -indstillingerne, da de er irrelevante, når ADATE er slukket
  5. Vi behøver ikke længere at nulstille det eksterne triggerflag, da INT0 -afbrydelsesrutinen gør dette automatisk, når den er færdig - tidligere havde vi ikke en afbrydelsesrutine, vi udløste bare ADC'en fra et signal ved den pin, så vi var nødt til at ryd det flag i hånden.

Nu i afbryderhandleren kalder vi simpelthen en enkelt konvertering fra ADC.

Øvelse 5: Kør denne version og se, hvad der sker.

Trin 12: Kode og video til arbejdsversionen

Som vi så ved den sidste version, fungerer knapafbrydelsen ikke særlig godt, fordi afbrydelsen udløses på en stigende kant for at fastgøre PD2, og derefter kalder afbrydelsesbehandleren ADC -konverteringen. ADC'en får imidlertid spændingsaflæsning, før den har stabiliseret sig, og den læser altså nonsens.

Hvad vi har brug for er at indføre en forsinkelse mellem afbrydelsen på PD2 og ADC -læsningen på PC0. Vi vil gøre dette ved at tilføje en timer/tæller, et tælleroverløbsafbrydelse og en forsinkelsesrutine. Heldigvis ved vi allerede, hvordan vi gør dette fra selvstudium 3! Så vi vil bare kopiere og indsætte den relevante kode derfra.

Jeg har givet den resulterende kode og en video, der viser den i drift.

Du vil bemærke, at aflæsningerne ikke er så nøjagtige, som man kunne håbe. Dette skyldes sandsynligvis en række kilder:

  1. vi trykker fra tastaturets spændingsudgang for at udløse på PD2, hvilket påvirker aflæsningen i PC0.
  2. vi ved ikke rigtigt, hvor lang tid vi skal forsinke efter udløseren for at få den bedste læsning.
  3. det tager et par cyklusser, før ADC -konverteringen er gennemført, hvilket betyder, at vi ikke kan skyde hurtigt på tastaturet.
  4. der er sandsynligvis støj i selve tastaturet.
  5. etc…

Så selvom det lykkedes os at få tastaturet til at fungere, og vi nu kunne bruge det i applikationer ved at bruge tastetryksværdierne på en anden måde i stedet for bare at sende dem til analysatorens display, er det ikke særlig præcist, og det er meget irriterende. Derfor tror jeg, at den bedste måde at koble tastaturer til er simpelthen at stikke hvert output fra tastaturet til en anden port og beslutte, hvilken tast der trykkes på, hvilke porte der ser en spænding. Det er let, meget hurtigt og meget præcist.

Faktisk er der kun to grunde til, at man gerne vil køre et tastatur, som vi har gjort her:

  1. Den bruger kun 2 af stifterne på vores mikrokontroller i stedet for 8.
  2. Det er et fantastisk projekt at vise forskellige aspekter af ADC på mikrokontrolleren, som adskiller sig fra de standard ting, du kan finde derude som temperaturmålinger, drejning af potentiometre osv. Jeg ville have et eksempel på udløste enkeltaflæsninger og ekstern automatisk udløsning af pin. snarere end bare frit kørende CPU-gobbling-tilstand.

Anyway, her er et sidste par øvelser til dig:

Øvelse 6: Omskriv ADC-konverteringsafslutningsafbryderhandleren igen for at bruge en opslagstabel. Dvs. Så den tester den analoge værdi med det første element i tabellen, og hvis den er større, vender den tilbage fra afbrydelsen, hvis den ikke er det, øges Z til det næste element i tabellen og grene tilbage til testen igen. Dette vil forkorte koden og rydde op i afbrydelsesrutinen og få den til at se pænere ud. (Jeg vil give en mulig løsning som det næste trin) Øvelse 7: Tilslut dit tastatur til 8 ben på mikrokontrolleren, og skriv den simple driver til det, og oplev, hvor meget pænere det er. Kan du tænke på et par måder at få vores metode til at fungere bedre?

Det er alt for denne vejledning. Jeg har vedhæftet den sidste version med tips. Når vi gør vores vej tættere på vores endelige mål, vil vi bruge tastaturet igen i Tutorial 9 til at vise, hvordan du styrer syv segmentdisplays med det (og bygger noget interessant, der bruger de ekstra taster på telefonens tastatur), og derefter vil vi skift til at kontrollere tingene med knap-tryk i stedet (da denne metode passer bedre med det slutprodukt, vi bygger mod med disse selvstudier), og vi vil bare lægge tastaturet på hylden.

Vi ses næste gang!

Anbefalede: