Innehållsförteckning:

AVR Assembler Tutorial 7: 12 Steg
AVR Assembler Tutorial 7: 12 Steg

Video: AVR Assembler Tutorial 7: 12 Steg

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

Välkommen till självstudie 7!

Idag ska vi först visa hur man rensar en knappsats och sedan visa hur man använder de analoga ingångsportarna för att kommunicera med knappsatsen. Vi kommer att göra detta med avbrott och en enda tråd som ingång. Vi kommer att ansluta knappsatsen så att varje knapptryckning skickar en unik spänning till den analoga ingången som gör att vi kan skilja med den spänning som tangenten trycktes in. Sedan skickar vi ut det nummer som trycks till vår registeranalysator för att visa att allt händer som det ska. Det finns ett antal fallgropar som du kan springa in på när du använder Analog to Digital Converter (ADC) i ATmega328p och så kommer vi att ta saker i några steg på vägen för att försöka lista ut hur man undviker dem. Vi kommer också att se varför att använda den analoga till digitala omvandlaren inte är det bästa sättet att styra en knappsats även om den använder färre portar på din mikrokontroller. I den här självstudien behöver du:

  1. en knappsats. Du kan köpa en eller så kan du göra vad jag gjorde och ta bort en.
  2. 2 kvinnliga rubriker för knappsatsen (om du tar bort en)
  3. anslutningskablar
  4. en brödbräda
  5. 4 1 Kohm -motstånd
  6. 1 15 Kohm motstånd
  7. 1 3.3 Kohm -motstånd
  8. 1 180 ohm motstånd
  9. 1680 ohm motstånd
  10. en digital multimeter
  11. din analysator från självstudie 5

Du kanske vill hoppa över de första stegen om du redan har en knappsats och inte behöver rensa en.

Här är en länk till den kompletta samlingen av mina AVR-monteringsstudier:

Steg 1: Rensa en knappsats 1

Ta bort en knappsats 1
Ta bort en knappsats 1
Ta bort en knappsats 1
Ta bort en knappsats 1
Ta bort en knappsats 1
Ta bort en knappsats 1
Ta bort en knappsats 1
Ta bort en knappsats 1

För länge sedan, när ens dina morföräldrar bara var barn, brukade folk använda dessa konstiga apparater som hade långa kablar anslutna till väggen för att kommunicera med varandra. De kallades "telefoner" och var vanligtvis billiga plastsaker som gav ett irriterande ljud när någon ringde dig (inte att dagens "Justin Bieber" ringsignaler inte är lika irriterande). I vilket fall som helst hade dessa enheter knappsatser på dem som var mycket enkelt anslutna och så är lätta att rensa och de har 2 extra nycklar på dem ("återuppringning" och "blixt") från knappsatserna du kan köpa som du kanske vill återanvända som "piltangenter", "menyknappar" eller något annat. Så vi ska börja med att ta bort en knappsats från en gammal telefon. Ta först telefonen (jag använder en GE som visas på bilderna) och bänd den isär för att avslöja kablarna. Ta sedan en mejsel och knäpp av de små plastknapparna som håller knappsatsen på och ta bort knappsatsen.

Steg 2: Rensa en knappsats 2

Ta bort en knappsats 2
Ta bort en knappsats 2
Ta bort en knappsats 2
Ta bort en knappsats 2
Ta bort en knappsats 2
Ta bort en knappsats 2

Ta nu en PVC -såg och skär plasten runt nyckelhålen och skär sedan runt kanten för att få djupet rätt och lämna en tunn knappsats.

Sätt sedan tillbaka knappsatsen med de små pinnarna som finns kvar efter att du klippt av topparna i det sista steget och använd ett lödkolv för att helt enkelt peta in det heta järnet i varje peghål som kommer att smälta plasten och sprida ut det över botten på knappsatsen som bildar nya "rattar" som håller knappsatsen på plats som tidigare.

Jag gillar att rensa de tre högtalarna och kanske andra saker som switchar och vad som inte finns på tavlan. Men den här gången tänker jag inte ta bort växlarna och sånt eftersom vi har andra mål för tillfället. Det finns också en TA31002 linjär IC där inne som är en ringsignal. Databladet är lätt att hitta och ladda ner online vilket ger pinout och funktioner. Så jag ska låta det lödas till brädet för nu och sedan leka med det senare. Jag skulle vilja ansluta den till ett oscilloskop och se vilka coola signaler jag kan få ut av den. Kanske till och med göra en dörrklocka av det. Vem vet.

Hur som helst när du är klar med att förstöra telefonen och rensa delarna kommer vi att göra klart vårt knappsats.

Steg 3: Rensa en knappsats 3

Ta bort en knappsats 3
Ta bort en knappsats 3
Ta bort en knappsats 3
Ta bort en knappsats 3
Ta bort en knappsats 3
Ta bort en knappsats 3

Använd en avlödningsveke och ta bort bandkablarna från knappsatsens undersida och se till att hålen i kretskortet är klara och fäst sedan två honhuvuden på brädet där hålen är. Du kommer förmodligen att behöva klippa ner dina rubriker så att de är 4-stifts rubriker.

Nu när rubrikerna är fästa kan du koppla den till ett brödbräda, ta en multimeter och testa nycklarna genom att sticka multimetern över slumpmässiga stift och mäta motståndet. Detta gör att du kan kartlägga nycklarna. Det är svårt att se hur nycklarna är anslutna till utgångarna genom att titta på kretsen men om du använder en multimeter kan du ansluta den till två stift och sedan trycka på knapparna tills du ser ett nummer på skärmen istället för en öppen krets. Detta kommer att vara pinout för den nyckeln.

Kartlägg alla nycklar till utgångsstiften på detta sätt.

Steg 4: Anslut knappsatsen

Anslut knappsatsen
Anslut knappsatsen
Anslut knappsatsen
Anslut knappsatsen

Följ nu kopplingsschemat och anslut knappsatsen till din bräda.

Hur detta kommer att fungera är att vi lägger 5V till vänster och höger sida går till GND. Den första stiftet till höger i diagrammet går in i den första av våra analoga stift på Atmega328p mikrokontroller. När det inte trycks på några knappar kommer signalen att vara 0V, och när var och en av de olika knapparna trycks in kommer ingången till den analoga porten att ligga mellan 0V och 5V med en annan mängd beroende på vilken knapp som trycktes. Vi valde motståndsvärdena så att varje väg skulle innehålla ett motstånd som var annorlunda än resten. Den analoga porten på mikrokontrollern tar en analog signal och delar den i 1024 olika kanaler mellan 0V och 5V. Detta innebär att varje kanal har en bredd 5V/1024 = 0,005 V/kanal = 5 mV/kanal. Så den analoga porten kan skilja ingångsspänningar så länge de skiljer sig med mer än 5 mV. I vårt fall har vi valt motståndsvärden så att två knapptryckningar skickar en spänningssignal som skiljer sig mer än så att mikrokontrollern enkelt ska kunna bestämma vilken tangent som trycktes. Det stora problemet är att hela systemet är mycket bullrigt så vi måste välja ett spänningsintervall för att mappa till varje knapptryckning - men vi kommer in på det lite senare.

Lägg märke till att vi kan styra en knappsats med 14 knappar med endast en enda ingångsrad till styrenheten. Det är en av de användbara aspekterna av analoga ingångar.

Nu är vårt första försök att styra knappsatsen att få en knapptryckning att orsaka ett avbrott, avbrottsrutan kommer att läsa den analoga ingångsporten och bestämma vilken tangent som trycktes in, och sedan kommer det numret att matas ut till vår registeranalysatorns underprogram som visar nyckelvärde i binärt på våra 8 lysdioder som vi satte upp i självstudie 5.

Steg 5: Anslut knappsatsen till din analysator

Anslut knappsatsen till din analysator
Anslut knappsatsen till din analysator
Anslut knappsatsen till din analysator
Anslut knappsatsen till din analysator

Bilderna visar hur vi vill koppla knappsatsen till mikrokontrollern så att vi kan se utgången på analysatorens display. I huvudsak kopplar vi helt enkelt utmatningen från knappsatsen till PortC pin 0, som också kallas ADC0 på ATmega328P.

Det finns dock ytterligare ett par saker. Vi kommer också att koppla en knapp till PD2. D.v.s. ta en kabel från din 5V -skena till en knapp och från andra sidan av knappen till PD2, och slutligen vill vi koppla bort AREF -stiftet från vår 5V -skena och istället låta den vara bortkopplad. Vi kunde sätta in en 0,1 mikrofarad avkopplingskondensator om vi ville. Detta är en keramisk kondensator med en 104 skriven på den. De två första siffrorna är siffran och den sista siffran är kraften på 10 vi multiplicerar det med för att få ett svar i picofarads (pico betyder 10^-12), så 104 betyder 10 x 10^4 picofarads, vilket är samma som 100 nanofarader (nano betyder 10^-9), vilket är samma som 0,1 mikrofarader (mikro betyder 10^-6). Hur som helst, allt detta gör är att stabilisera AREF -stiftet när vi kan använda det som vår referensnål.

Vi vill också ha ett 1 Mohm motstånd mellan PD2 och jord. Vi kommer att ställa in PD2 som en utgångsstift vid 0V och vi kommer att trigga på en positiv kant vid den stiftet. Vi vill att kanten ska försvinna omedelbart när vi släpper knappen så vi sätter in detta "pull down" -motstånd.

Anledningen till att vi vill ha knappen är för att vi vill utlösa vår Analog-to-Digital-omvandlare från pin INT0 på chipet, som också är PD2. Så småningom skulle vi vilja att knapptryckningen både skulle utlösa ADC och även tillhandahålla ingången som ska konverteras utan att ha en separat knapp, men på grund av hur timingen fungerar börjar vi med att ha en separat knapp för att utlösa ADC och när vi stryker alla buggarna ut och är övertygade om att allt fungerar som det ska, då kommer vi att ta itu med buller- och timingproblemen som kommer med utlösningen från samma knapptryckning som vi vill läsa.

Så, för närvarande, så fungerar det att vi kommer att hålla en tangent intryckt, sedan trycka på knappen för att utlösa ADC, och sedan släppa och förhoppningsvis kommer det binära värdet på knappen som vi tryckte att dyka upp på analysatorn.

Så låt oss skriva en kod som kommer att åstadkomma det.

Steg 6: Vilka vippomkopplare ska vi ställa in?

Vilka vippomkopplare ska vi ställa in?
Vilka vippomkopplare ska vi ställa in?

Låt oss först tänka på hur vi ska koda detta så att styrenheten kan läsa ingången från knappsatsen och förvandla den till ett numeriskt värde som motsvarar den knapp som trycktes in. Vi ska använda Analog to Digital Converter (ADC) som är inbyggd i Atmega328p. Vi kommer att använda AREF som vår referensspänning och vår knappsatsutgång kommer att anslutas till PortC0 eller PC0. Observera att denna pin också kallas ADC0 för Analog-to-Digital Converter 0. Det kan vara en bra idé för dig att läsa igenom avsnitt 12.4 om avbrott för ATmega328P och även kapitel 24 om Analog-to-Digital Converter innan vi får startat eller åtminstone ha de sektionerna redo för referens. För att konfigurera mikrokontrollern så att den vet vad han ska göra med en analog insignal och hur man interagerar med vårt program måste vi först ställa in några av de olika ADC relaterade registerbitar. Dessa motsvarar i huvudsak de gamla omkopplarna på de första datorerna. Antingen slår du en strömbrytare PÅ eller AV, eller ännu längre bakåt kopplar du in kablar mellan ett uttag och ett annat så att elektroner som når den gaffeln på vägen skulle hitta en grind stängd och en annan öppen och tvinga den ner en annan väg i labyrinten av kretsar och därmed utföra en annan logisk uppgift. När vi kodar på monteringsspråk har vi nära tillgång till dessa funktioner hos mikrokontrollern, vilket är en av de attraktiva sakerna med att göra det i första hand. Det är mer "hands on" och det händer mycket mindre "behind the scenes" liksom. Så tänk inte på att ställa in dessa register som en tråkig uppgift. Det är det som gör monteringsspråk intressant! Vi får en mycket personlig relation till chipets inre funktion och logik och får det att göra precis vad vi vill - inte mer och inte mindre. Inga bortkastade klockcykler. Så här är en lista över de omkopplare vi behöver ställa in:

  1. Stäng av Power Reduction ADC -bit, PRADC, som är bit 0 i PRR -registret, eftersom om denna bit är på kommer den att stänga av ADC. Effektreduktionsregistret är i huvudsak ett sätt att stänga av olika saker som använder ström när du inte behöver dem. Eftersom vi använder ADC vill vi se till att den inte är inaktiverad på detta sätt. (Se PRADC på sidan 46)
  2. Välj den analoga ingångskanalen som ska vara ADC0 genom att stänga av MUX3… 0 i ADC Multiplexer Selection (ADMUX) -registret (se tabell 24-4 sidan 249) dessa är redan avstängda som standard så vi behöver inte göra det. Men jag inkluderar det eftersom om du någonsin använder en annan port än ADC0 måste du växla dessa växlar i enlighet därmed. Olika kombinationer av MUX3, MUX2, MUX1, MUX0 låter dig använda vilken som helst av de analoga portarna som din ingång och du kan också ändra dessa direkt om du vill titta på en massa olika analoga signaler samtidigt.
  3. Stäng av bitarna REFS0 och REFS1 i ADMUX -registret så att vi använder AREF som vår referensspänning snarare än en intern referens (se sidan 248).
  4. Slå på ADLAR -biten i ADMUX så att resultatet är "vänsterjusterat", vi kommer att diskutera detta val i nästa steg.
  5. Ställ in ADC0D -biten i Digital Input Disable Register (DIDR0) för att stänga av digital ingång till PC0. Vi använder den porten för analog ingång så vi kan lika gärna inaktivera den digitala ingången för den.
  6. Ställ in ISC0 och ISC1 i External Interrupt Control Register A (EICRA) för att indikera att vi vill trigga på den stigande kanten av en spänningssignal till INT0 -stiftet (PD2), se sidan 71.
  7. Rensa bitarna INT0 och INT1 i External Interrupt Mask Register (EIMSK) för att indikera att vi inte använder avbrott på denna pin. Om vi skulle aktivera avbrott på denna pin skulle vi behöva en avbrottshanterare på adressen 0x0002 men istället ställer vi in den så att en signal på denna pin utlöser ADC -konverteringen, vars slutförande hanteras av ADC -konverteringen fullständigt avbrott kl. adress 0x002A. Se sidan 72.
  8. Ställ in ADC Enable (ADEN) bit (bit 7) i ADC -kontrollen och statusregistret A (ADCSRA) för att aktivera ADC. Se sidan 249.
  9. Vi kan starta en enda konvertering genom att ställa in ADC -startkonverteringsbiten (ADSC) varje gång vi ville läsa den analoga signalen, men för närvarande vill vi hellre att den läses automatiskt när någon trycker på knappen, så istället aktiverar vi ADC Autotrigger Aktivera (ADATE) bit i ADCSRA -registret så att utlösningen sker automatiskt.
  10. Vi ställde också in ADPS2..0 -bitarna (AD Prescalar -bitarna) till 111 så att ADC -klockan är CPU -klockan dividerad med en faktor 128.
  11. Vi väljer källan för ADC -utlösningen till PD2 som också kallas INT0 (External Interrupt Request 0). Vi gör detta genom att växla mellan de olika bitarna i ADCSRB-registret (se tabell 24-6 på sidan 251). Vi ser i tabellen att vi vill ha ADTS0 av, ADTS1 på och ADTS2 av så att ADC kommer att utlösa den stiftet. Observera att om vi kontinuerligt ville sampla den analoga porten som om vi läste någon kontinuerlig analog signal (som ljudsampling eller något) skulle vi ställa in detta till Free Running Mode. Metoden vi använder för att ställa in triggning på PD2 utlöser en ADC -avläsning av den analoga porten PC0 utan att orsaka ett avbrott. Avbrottet kommer när konverteringen är klar.
  12. Aktivera ADC Interrupt Enable (ADIE) -biten i ADCSRA -registret så att när den analoga till digitala omvandlingen är klar kommer det att generera ett avbrott som vi kan skriva en avbrottshanterare för och sätta på.org 0x002A.
  13. Ställ in I -biten i SREG för att aktivera avbrott.

Övning 1: Se till att du läser relevanta avsnitt i databladet för var och en av ovanstående inställningar så att du förstår vad som händer och vad som skulle hända om vi ändrade dem till alternativa inställningar.

Steg 7: Skriv Interrupt Handler

I det sista steget såg vi att vi har ställt in det så att en stigande kant upptäckt på PD2 kommer att utlösa en analog till digital konvertering på PC0 och när denna konvertering är klar kommer den att kasta ett ADC Conversion Complete -avbrott. Nu vill vi göra något med detta avbrott. Om du undersöker tabell 12-6 på sidan 65 ser du en lista över möjliga avbrott. Vi har redan sett RESET -avbrottet på adressen 0x0000 och Timer/Counter0 Overflow -avbrottet på adressen 0x0020 i tidigare självstudier. Nu vill vi titta på ADC -avbrottet som vi ser vid tabellen på adressen 0x002A. Så i början av vår monteringsspråkkod behöver vi en rad som lyder:

.org 0x002Arjmp ADC_int

som hoppar till vår avbrottshanterare märkt ADC_int när ADC har slutfört en konvertering. Så hur ska vi skriva vår avbrottshanterare? ADC: s sätt fungerar genom att utföra följande beräkning:

ADC = Vin x 1024 / Vref

Så låt oss se vad som händer om jag trycker på knappen "återuppringning" på knappsatsen. I så fall kommer spänningen på PC0 att ändras till något värde, säg 1.52V, och eftersom Vref är vid 5V kommer vi att ha:

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

och så skulle det visa sig som en 311. Om vi ville konvertera detta tillbaka till en spänning skulle vi bara vända beräkningen. Vi behöver dock inte göra detta eftersom vi inte är intresserade av de faktiska spänningarna bara för att skilja dem. När konverteringen är klar lagras resultatet i ett 10-bitars tal placerat i ADCH- och ADCL-registren och vi har fått det att "vänsterjusteras" vilket innebär att 10-bitarna börjar vid bit 7 i ADCH och går ner till bit 6 i ADCL (det finns totalt 16 bitar i dessa två register och vi använder bara 10 av dem, dvs 1024 kanaler). Vi kan ha resultatet "högerjusterat" om vi vill genom att rensa ADLAR -biten i ADMUX -registret. Anledningen till att vi väljer vänsterjusterad är att våra signaler är tillräckligt långt ifrån varandra för att de två sista siffrorna i kanalnumret inte är relevanta och är förmodligen bara brus så vi kommer att skilja knapptryckningarna med endast de 8 övre siffrorna, med andra ord, vi behöver bara titta på ADCH för att ta reda på vilken knapp som trycktes. Så vår avbrottshanterare borde helt enkelt läsa numret ur ADCH registrera, konvertera det numret till ett knappsatsvärde och skicka sedan det värdet till våra registeranalysatorns lysdioder så att vi kan verifiera att genom att trycka på ett "9" -signal kommer lysdioderna som motsvarar "00001001" att tändas. Innan vi går det långt men vi måste först se vad som dyker upp i ADCH när vi trycker på de olika knapparna. Så låt oss bara skriva en enkel avbrottshanterare som bara skickar innehållet i ADCH till analysatorns display. Så här är vad vi behöver:

ADC_int: lds analysator, ADCH; ladda värdet på ADCH i vår analysatorbi EIFR, 0; rensa den externa avbrottsflaggan så att den är redo att gå igen

Nu ska du kunna kopiera koden från vår analysator i självstudie 5 och lägga till detta avbrott och växlingsinställningarna och köra det. Övning 2: Skriv koden och kör den. Se till att ADCH visas på analysatorns display. Prova att trycka på samma knapptryckning flera gånger. Får du alltid samma värde i ADCH?

Steg 8: Kartlägg ut knapptrycksvärdena

Kartlägg ut knapptrycksvärdena
Kartlägg ut knapptrycksvärdena

Vad vi behöver göra nu är att konvertera värdena i ADCH till siffror som motsvarar knappen som trycktes in. Vi gör detta genom att skriva ut innehållet i ADCH för varje knapptryckning och sedan konvertera det till ett decimaltal som jag gjorde på bilden. I vår avbrottshanteringsrutin kommer vi att betrakta ett helt intervall av värden som motsvarar varje knapptryckning så att ADC kommer att kartlägga allt inom det området till ett givet knapptryck.

Övning 3: Gör den här mappningen och skriv sedan om din ADC-avbrottsrutin.

Här är vad jag fick för min (din kommer sannolikt att vara annorlunda). Lägg märke till att jag har ställt in det med en rad värden för varje knapptryckning.

ADC_int:; Extern interrupt handlerclr analysator; förbered dig för nya nummerlds -knappen H, ADCH; ADC uppdateras när ADCH läses clccpi -knapp H, 240brlo PC+3; om ADCH är större är det en 1ldi -analysator, 1; så ladda analysator med en 1rjmp retur; och retur clccpi -knapp H, 230; om ADCH är större än en 2brlo PC+3ldi analysator, 2rjmp retur clccpi knapp H, 217brlo PC+3ldi analysator, 3rjmp retur clccpi knapp H, 203brlo PC+3ldi analysator, 4rjmp retur clccpi knapp H, 187brlo PC+3ldi analysator, 5rjmp retur clccpi knapp, 155brlo PC+3ldi analysator, 6rjmp retur clccpi knapp H, 127brlo PC+3ldi analysator, 255; vi kommer att ställa in flash som alla onrjmp retur clccpi knapp H, 115brlo PC+3ldi analysator, 7rjmp retur clccpi knapp H, 94brlo PC+3ldi analysator, 8rjmp retur clccpi knapp H, 62brlo PC+3ldi analysator, 9rjmp retur clccpi knapp H, 37brlo PC+3ldi analysator, 0b11110000; asterisk är övre halvan onrjmp retur clccpi knapp H, 28brlo PC+3ldi analysator, 0rjmp retur clccpi knapp H, 17brlo PC+3ldi analysator, 0b00001111; hashtecken är nedre halvan onrjmp return clccpi buttonH, 5brlo PC+3ldi analysator, 0b11000011; återuppringning är topp 2 botten 2rjmp return ldi analysator, 0b11011011; annars uppstod fel retur: reti

Steg 9: Kod och video för version 1

Jag har bifogat min kod för den här första versionen av knappsatsdrivrutinen. I den här måste du trycka på knappen och sedan trycka på knappen för att få ADC att läsa ingången från knappsatsen. Vad vi hellre vill ha är ingen knapp utan istället kommer signalen att göra konverteringen från själva knapptrycket. Övning 3: Sätt ihop och ladda upp den här koden och prova den. Du kan behöva ändra de olika konverteringströsklarna för att motsvara dina knapptrycksspänningar eftersom de sannolikt skiljer sig från mina. Vad händer om du försöker använda en ingång från knappsatsen både för ADC0 och för den externa avbrottsstiftet istället för via en knapp? Jag kommer också att bifoga en video av hur den första versionen av vår knapptrycksdrivrutin fungerar. Du kommer att märka att i min kod finns ett avsnitt som initierar Stack Pointer. Det finns olika register som vi kanske vill skjuta och poppa från stapeln när vi manipulerar variabler och vad som inte är och det finns också register som vi kanske vill spara och återställa senare. Till exempel är SREG ett register som inte bevaras över avbrott, så de olika flaggorna som ställs in och rensas som ett resultat av operationer kan ändras om ett avbrott inträffar mitt i något. Så det är bäst om du trycker på SREG till stacken i början av en avbrottshanterare och sedan slår av den igen i slutet av avbrottshanteraren. Jag har placerat den i koden för att visa hur den initieras och för att förutse hur vi kommer att behöva den senare men eftersom vi inte bryr oss om vad som händer med SREG under avbrott i vår kod använde jag inte stacken för detta. att jag har använt skiftoperationen för att ställa in olika bitar i register vid initialisering. Till exempel i raden:

ldi temp, (1 <> st EICRA, temp

Kommandot "<<" i den första kodraden ovan är en skiftoperation. Det tar i huvudsak det binära talet 1, vilket är 0b00000001 och flyttar det till vänster med mängden av talet ISC01. Detta är positionen för den bit som heter ISC01 i EICRA -registret. Eftersom ISC01 är bit 1, flyttas talet 1 till vänster 1 -läge för att bli 0b00000010. På samma sätt är den andra, ISC00, bit 0 i EICRA och därför är skiftet för siffran 1 nollägen till vänster. Om du tittar, ta en titt på filen m328Pdef.inc som du laddade ner i den första självstudien och har använt evrr sedan, kommer du att se att det bara är en lång lista med ".equ" -uttalanden. Du kommer att upptäcka att ISC01 är lika med 1. Monteraren ersätter varje instans av den med 1 innan han ens börjar montera något. De är bara namn på registerbitar för att hjälpa oss människor att läsa och skriva kod. Nu är den vertikala linjen mellan de två skiftoperationerna ovan en logisk "eller" operation. Här är ekvationen:

0b00000010 | 0b00000001 = 0b00000011

och det här är vad vi laddar (med "ldi") till temp. Anledningen till att människor använder den här metoden för att ladda in värden i ett register är att den tillåter en att använda namnet på biten istället för bara ett tal och detta gör koden mycket lättare att läsa. Det finns också två andra tekniker som vi har använt. Vi använder instruktionerna "ori" och "andi". Dessa tillåter oss att SET- respektive CLEAR -bitar utan att ändra någon av de andra bitarna i ett register. Till exempel när jag använde

ori temp, (1

denna "eller" s temp med 0b00000001 som sätter en 1 i nollbiten och lämnar resten oförändrat. Även när vi skrev

andi temp, 0b11111110

detta ändrar nollpunkten till 0 och lämnar resten oförändrat.

Övning 4: Du bör gå igenom koden och se till att du förstår varje rad. Du kanske tycker att det är intressant att hitta bättre metoder för att göra saker och skriva ett bättre program. Det finns hundra sätt att koda saker och jag är ganska säker på att du kan hitta ett mycket bättre sätt än mitt. Du kan också hitta (himmelriket!) Fel och utelämnanden. I så fall skulle jag säkert vilja höra om dem så att de kan åtgärdas.

Okej, låt oss nu se om vi kan bli av med den överflödiga knappen …

Steg 10: Kod för version 2

Det enklaste sättet att bli av med knappen är bara att ta bort den helt, glömma ingången till PB2 och bara byta ADC till "Free Running Mode".

Med andra ord ändrar du bara ADCSRB -registret så att ADTS2, ADTS1 och ADTS0 alla är noll.

Ställ sedan in ADSC -biten i ADCSRA till 1 som startar den första konverteringen.

Ladda nu upp den till din mikrokontroller och du kommer att upptäcka att rätt nummer visas på displayen medan du trycker på knappen och bara medan du trycker på knappen. Detta beror på att ADC kontinuerligt samplar ADC0 -porten och visar värdet. När du tar bort fingret från knappen kommer "knappstoppet" att få några slumpmässiga värden att inträffa mycket snabbt och sedan återställa till 0V -ingång. I vår kod har vi denna 0V som 0b11011011 (eftersom knapptrycket '0' redan använder visningsvärdet 0b00000000)

Detta är dock inte den lösning vi vill ha av två skäl. Först vill vi inte behöva hålla knappen. Vi vill trycka på den en gång och få numret att visas (eller användas i någon ny kod i en senare handledning). För det andra vill vi inte kontinuerligt prova ADC0. Vi vill att den ska ta en enda avläsning, konvertera den och sedan sova tills en ny knapptryckning utlöser en ny konvertering. Free running mode är bäst om det enda du vill att mikrokontrollern ska göra är att kontinuerligt läsa några analoga ingångar - som om du ville visa realtidstemperaturer eller något.

Så låt oss hitta ännu en lösning …

Steg 11: Hur blir vi av med knappen? Version 3

Hur blir vi av med knappen? Version 3
Hur blir vi av med knappen? Version 3

Det finns många sätt vi kan gå vidare. Först kunde vi lägga till hårdvara för att bli av med knappen. Till exempel kan vi försöka sätta en transistor i kretsen vid knapptryckningens utgångsledning så att den skulle ta en liten ström av strömmen från utgången och skicka en 5V puls till avbrottsstiftet PD2.

Det skulle dock förmodligen vara för bullrigt åtminstone och i värsta fall skulle det inte ge tillräckligt med tid för en exakt knapptrycksavläsning eftersom knappsatsens spänningsutgång inte skulle hinna stabiliseras innan ADC -avläsningen fångas.

Så vi skulle hellre komma med en mjukvarulösning. Vad vi skulle vilja göra är att lägga till ett avbrott på PD2 -stiftet och skriva en avbrottshanterare för det som kräver en enda avläsning av knappsatsen. Med andra ord, vi blir av med autotrigger -avbrottet från ADC och lägger till ett externt avbrott som kallar ADC inuti det. På så sätt kommer signalen för att läsa ADC efter att PD2 -signalen redan har inträffat och detta kan ge saker tillräckligt med tid att stabilisera till en exakt spänning innan PC0 -stiftet läses och konverteras. Vi skulle fortfarande ha ett ADC -slutförandeavbrott som matar ut resultatet till analysatorns display i slutet.

Vettigt? Tja, låt oss göra det …

Ta en titt på den nya koden som bifogas.

Du ser följande ändringar:

  1. Vi lade till en rjmp på adressen.org 0x0002 för att hantera INT0 externt avbrott
  2. Vi ändrade EIMSK -registret för att indikera att vi vill avbryta INT0 -stiftet
  3. Vi ändrade ADATE -stiftet i ADCSRA -registret för att inaktivera autotriggering
  4. Vi blev av med ADCSRB -inställningarna eftersom de är irrelevanta när ADATE är avstängd
  5. Vi behöver inte längre återställa den externa triggerflaggan eftersom INT0 -avbrottsrutinen gör detta automatiskt när den är klar - tidigare hade vi inte en avbrottsrutin, vi utlöste bara ADC: n från en signal vid den stiftet, så vi var tvungna att rensa den flaggan för hand.

Nu i avbrottshanteraren kallar vi helt enkelt en enda konvertering från ADC.

Övning 5: Kör den här versionen och se vad som händer.

Steg 12: Kod och video för arbetsversionen

Som vi såg i den senaste versionen fungerar knappavbrottet inte särskilt bra eftersom avbrottet utlöses på en stigande kant för att fästa PD2 och sedan ringer avbrottshanteraren ADC -konverteringen. ADC får dock sedan spänningsavläsningen innan den har stabiliserats och så läser den nonsens.

Vad vi behöver är att införa en fördröjning mellan avbrottet på PD2 och ADC -avläsningen på PC0. Vi kommer att göra detta genom att lägga till en timer/räknare, ett överflödesavbrott och en fördröjningsrutin. Lyckligtvis vet vi redan hur man gör detta från självstudie 3! Så vi kommer bara att kopiera och klistra in den relevanta koden därifrån.

Jag har gett den resulterande koden och en video som visar den i drift.

Du kommer att märka att avläsningarna inte är så exakta som man skulle hoppas. Detta beror troligen på ett antal källor:

  1. vi knackar från knappsatsens spänningsutgång för att utlösa på PD2 vilket påverkar avläsningen i PC0.
  2. vi vet inte riktigt hur lång tid vi ska fördröja efter utlösaren för att få bästa läsning.
  3. det tar några cykler för ADC -konverteringen att slutföras, vilket innebär att vi inte snabbt kan skjuta på knappsatsen.
  4. det är förmodligen brus i själva knappsatsen.
  5. etc…

Så även om vi lyckades få tangentbordet att fungera, och vi nu kan använda det i applikationer genom att använda knapptrycksvärdena på något annat sätt istället för att bara mata ut dem på analysatorns display, är det inte särskilt exakt och det är väldigt irriterande. Det är därför jag tror att det bästa sättet att koppla knappsatser är helt enkelt att fästa varje utmatning från knappsatsen till en annan port och bestämma vilken tangent som trycks av vilka portar som ser en spänning. Det är lätt, mycket snabbt och mycket exakt.

Faktum är att det bara finns två anledningar till varför man skulle vilja köra ett knappsats så som vi har gjort här:

  1. Den använder bara 2 av stiften på vår mikrokontroller istället för 8.
  2. Det är ett fantastiskt projekt att visa olika aspekter av ADC på mikrokontrollen som skiljer sig från de vanliga sakerna du kan hitta där ute som temperaturavläsningar, vridpotentiometrar, etc. Jag ville ha ett exempel på utlösta enstaka avläsningar och extern stift automatisk utlösning snarare än bara fritt körande CPU-gobbling-läge.

Hur som helst, här är ett par sista övningar för dig:

Övning 6: Skriv om avbrottshanteraren för ADC-konverteringen igen för att använda en uppslagstabell. D.v.s. Så att det testar det analoga värdet med det första objektet i tabellen och om det är större återgår det från avbrottet, om det inte är det så ökar det Z till nästa objekt i tabellen och förgrenar sig till testet igen. Detta kommer att förkorta koden och städa upp avbrottsrutinen och få den att se snyggare ut. (Jag kommer att ge en möjlig lösning som nästa steg) Övning 7: Anslut din knappsats till 8 stift på mikrokontrollen och skriv den enkla drivrutinen för den och upplev hur mycket trevligare den är. Kan du tänka dig några sätt att få vår metod att fungera bättre?

Det är allt för denna handledning. Jag har bifogat den slutliga versionen med tips. När vi tar oss närmare vårt slutmål, kommer vi att använda tangentbordet en gång till i Tutorial 9 för att visa hur du styr sju segmentdisplayer med det (och bygga något intressant som använder de extra knapparna på telefonens knappsats) och sedan kommer vi att byt till att styra saker med knapptryck istället (eftersom den metoden passar bättre med slutprodukten vi bygger mot med dessa självstudier) och vi kommer bara att hylla knappsatsen.

Vi ses nästa gång!

Rekommenderad: