Inhaltsverzeichnis:

AVR-Assembler-Tutorial 7: 12 Schritte
AVR-Assembler-Tutorial 7: 12 Schritte

Video: AVR-Assembler-Tutorial 7: 12 Schritte

Video: AVR-Assembler-Tutorial 7: 12 Schritte
Video: Getting started with AVR and Atmel Studio 7 2024, November
Anonim
AVR-Assembler-Tutorial 7
AVR-Assembler-Tutorial 7

Willkommen bei Lernprogramm 7!

Heute werden wir zuerst zeigen, wie man eine Tastatur aufräumt, und dann zeigen, wie man die analogen Eingangsports verwendet, um mit der Tastatur zu kommunizieren. Wir werden dies mit Interrupts und einem einzelnen Draht als Eingang tun. Wir werden die Tastatur so verdrahten, dass jeder Tastendruck eine eindeutige Spannung an den analogen Eingang sendet, die es uns ermöglicht, anhand der Spannung zu unterscheiden, welche Taste gedrückt wurde. Dann geben wir die gedrückte Zahl an unseren Registeranalysator aus, um zu zeigen, dass alles so läuft, wie es sollte. Es gibt eine Reihe von Fallstricken, auf die Sie bei der Verwendung des Analog-Digital-Wandlers (ADC) im ATmega328p stoßen können Nehmen Sie die Dinge in ein paar Etappen auf dem Weg, um herauszufinden, wie Sie sie vermeiden können. Wir werden auch sehen, warum die Verwendung des Analog-Digital-Wandlers nicht der beste Weg ist, um eine Tastatur zu steuern, obwohl sie weniger Ports auf Ihrem Mikrocontroller verwendet. In diesem Tutorial benötigen Sie:

  1. eine Tastatur. Sie können einen kaufen oder tun, was ich getan habe, und einen plündern.
  2. 2 Buchsenleisten für die Tastatur (wenn Sie eine aufräumen)
  3. Anschlussdrähte
  4. ein Steckbrett
  5. 4 1-Kohm-Widerstände
  6. 1 15 Kohm Widerstand
  7. 1 3,3 Kohm Widerstand
  8. 1 180 Ohm Widerstand
  9. 1 680 Ohm Widerstand
  10. ein digitales Multimeter
  11. Ihr Analysator aus Tutorial 5

Sie können die ersten Schritte überspringen, wenn Sie bereits über eine Tastatur verfügen und keine aufräumen müssen.

Hier ist ein Link zur vollständigen Sammlung meiner AVR-Assembler-Tutorials:

Schritt 1: Aufräumen einer Tastatur 1

Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1
Eine Tastatur durchsuchen 1

Vor langer Zeit, als sogar Ihre Großeltern noch Kinder waren, benutzten die Leute diese seltsam aussehenden Geräte, an denen lange Kabel an der Wand befestigt waren, um miteinander zu kommunizieren. Sie wurden "Telefone" genannt und waren normalerweise billige Plastikdinger, die ein nerviges Geräusch machten, wenn jemand Sie anrief (nicht, dass die "Justin Bieber"-Klingeltöne von heute nicht genauso nervig sind). Auf jeden Fall hatten diese Geräte Tastenfelder, die sehr einfach verkabelt waren und daher leicht zu beseitigen sind, und sie haben 2 zusätzliche Tasten ("Wahlwiederholung" und "Flash") von den Tastenfeldern, die Sie kaufen können, die Sie möglicherweise wiederverwenden möchten B. "Pfeiltasten", "Menütasten" oder etwas anderes. Wir beginnen also damit, eine Tastatur von einem alten Telefon zu säubern. Nehmen Sie zuerst das Telefon (ich verwende ein GE-Gerät, wie in den Bildern gezeigt) und hebeln Sie es auseinander, um die Verkabelung freizulegen. Nehmen Sie dann einen Meißel und brechen Sie die kleinen Plastikknöpfe ab, die die Tastatur halten, und entfernen Sie die Tastatur.

Schritt 2: Aufräumen einer Tastatur 2

Aufräumen einer Tastatur 2
Aufräumen einer Tastatur 2
Aufräumen einer Tastatur 2
Aufräumen einer Tastatur 2
Aufräumen einer Tastatur 2
Aufräumen einer Tastatur 2

Nehmen Sie nun eine PVC-Säge und schneiden Sie den Kunststoff um die Schlüssellöcher herum und schneiden Sie dann um die Kante, um die richtige Tiefe zu erhalten, und hinterlassen Sie eine dünne Tastatur.

Setzen Sie dann die Tastatur mit den kleinen Stiften wieder auf, die übrig bleiben, nachdem Sie im letzten Schritt die Oberseiten davon abgeschnitten haben, und stecken Sie das heiße Eisen einfach mit einem Lötkolben in jedes Stiftloch, das den Kunststoff schmilzt und über die verteilt Unterseite der Tastatur, die neue "Knöpfe" bildet, die die Tastatur wie zuvor an Ort und Stelle halten.

Ich mag es, die drei Lautsprecher aufzuräumen und vielleicht die anderen Dinge wie Schalter und was-nicht, die auf dem Board sind. Diesmal werde ich jedoch nicht die Schalter und so weiter aufräumen, weil wir im Moment andere Ziele haben. Außerdem befindet sich dort ein linearer TA31002-IC, der ein Telefonklingel ist. Das Datenblatt ist leicht zu finden und online herunterzuladen und gibt die Pinbelegung und die Funktionen an. Also werde ich es vorerst auf die Platine gelötet lassen und später damit herumspielen. Ich würde es gerne an ein Oszilloskop anschließen und sehen, welche coolen Signale ich daraus bekomme. Vielleicht sogar eine Türklingel daraus machen. Wer weiß.

Wie auch immer, sobald Sie mit der Zerstörung des Telefons und dem Aufräumen der Teile fertig sind, werden wir unsere Tastatur fertig stellen.

Schritt 3: Aufräumen einer Tastatur 3

Aufräumen einer Tastatur 3
Aufräumen einer Tastatur 3
Aufräumen einer Tastatur 3
Aufräumen einer Tastatur 3
Aufräumen einer Tastatur 3
Aufräumen einer Tastatur 3

Verwenden Sie einen Entlötdocht und entfernen Sie die Flachbandkabel von der Unterseite der Tastatur. Stellen Sie sicher, dass die Löcher in der Platine frei sind, und befestigen Sie dann zwei Buchsenleisten auf der Platine, wo die Löcher sind. Sie müssen wahrscheinlich Ihre Header abschneiden, damit es sich um 4-Pin-Header handelt.

Jetzt, da die Header angebracht sind, können Sie es mit einem Steckbrett verdrahten, ein Multimeter nehmen und die Tasten testen, indem Sie das Multimeter über zufällige Pins kleben und den Widerstand messen. Auf diese Weise können Sie die Schlüssel zuordnen. Es ist schwer zu erkennen, wie die Tasten mit den Ausgängen verdrahtet sind, wenn man sich den Stromkreis ansieht, aber wenn Sie ein Multimeter verwenden, können Sie es an zwei beliebige Pins anschließen und dann die Tasten drücken, bis Sie eine Zahl auf dem Bildschirm anstelle eines offenen Stromkreises sehen. Dies ist die Pinbelegung für diesen Schlüssel.

Ordnen Sie auf diese Weise alle Tasten den Ausgangspins zu.

Schritt 4: Verdrahten Sie die Tastatur

Verdrahten Sie die Tastatur
Verdrahten Sie die Tastatur
Verdrahten Sie die Tastatur
Verdrahten Sie die Tastatur

Folgen Sie nun dem Schaltplan und verdrahten Sie die Tastatur mit Ihrem Steckbrett.

Wie dies funktionieren wird, legen wir 5V auf die linke Seite und die rechte Seite geht auf GND. Der erste Pin rechts im Diagramm geht in den ersten unserer analogen Pins des Atmega328p-Mikrocontrollers. Wenn keine Tasten gedrückt werden, beträgt das Signal 0 V, und wenn jede der verschiedenen Tasten gedrückt wird, liegt der Eingang am analogen Port zwischen 0 V und 5 V mit unterschiedlichen Werten, je nachdem, welche Taste gedrückt wurde. Wir haben die Widerstandswerte so gewählt, dass jeder Pfad einen Widerstand enthält, der sich vom Rest unterscheidet. Der analoge Port des Mikrocontrollers nimmt ein analoges Signal auf und teilt es in 1024 verschiedene Kanäle zwischen 0V und 5V auf. Dies bedeutet, dass jeder Kanal eine Breite von 5V/1024 = 0,005 V/Kanal = 5 mV/Kanal hat. Der analoge Port kann also Eingangsspannungen unterscheiden, solange sie sich um mehr als 5 mV unterscheiden. In unserem Fall haben wir die Widerstandswerte so gewählt, dass zwei beliebige Tastendrücke ein Spannungssignal senden, das sich um mehr als dieses unterscheidet, damit der Mikrocontroller leicht entscheiden kann, welche Taste gedrückt wurde. Das große Problem ist, dass das gesamte System sehr laut ist, so dass wir einen Spannungsbereich auswählen müssen, der jedem Tastendruck zugeordnet werden soll – aber dazu kommen wir etwas später.

Beachten Sie, dass wir eine 14-Tasten-Tastatur mit nur einer einzigen Eingabeleitung zum Controller steuern können. Das ist einer der nützlichen Aspekte von Analogeingängen.

Unser erster Versuch, das Tastenfeld zu steuern, besteht darin, dass ein Tastendruck einen Interrupt auslöst Schlüsselwert in Binär auf unseren 8 LEDs, die wir in Tutorial 5 eingerichtet haben.

Schritt 5: Verdrahten Sie die Tastatur mit Ihrem Analysator

Verdrahten Sie die Tastatur mit Ihrem Analysator
Verdrahten Sie die Tastatur mit Ihrem Analysator
Verdrahten Sie die Tastatur mit Ihrem Analysator
Verdrahten Sie die Tastatur mit Ihrem Analysator

Die Bilder zeigen, wie wir die Tastatur mit dem Mikrocontroller verbinden möchten, damit wir die Ausgabe auf unserem Analysator-Display sehen können. Im Wesentlichen verdrahten wir einfach den Ausgang der Tastatur mit PortC-Pin 0, der beim ATmega328P auch ADC0 genannt wird.

Es gibt jedoch ein paar zusätzliche Dinge. Wir werden auch eine Taste an PD2 anschließen. D.h. Nehmen Sie ein Kabel von Ihrer 5V-Schiene zu einer Taste und von der anderen Seite der Taste zu PD2, und schließlich möchten wir den AREF-Pin von unserer 5V-Schiene trennen und stattdessen getrennt lassen. Wir könnten einen 0,1 Mikrofarad Entkopplungskondensator einfügen, wenn wir wollten. Dies ist ein Keramikkondensator mit einer 104 darauf geschrieben. Die ersten beiden Ziffern sind die Zahl und die letzte Ziffer ist die Potenz von 10, mit der wir sie multiplizieren, um eine Antwort in Picofarad zu erhalten (Pico bedeutet 10^-12), also 104 bedeutet 10 x 10^4 Picofarad, was dasselbe ist wie 100 Nanofarad (Nano bedeutet 10^-9), was 0,1 Mikrofarad entspricht (Mikro bedeutet 10^-6). Wie auch immer, alles, was dies tut, ist den AREF-Pin zu stabilisieren, wenn wir ihn als unseren Referenz-Pin verwenden können.

Wir wollen auch einen 1 MOhm Widerstand zwischen PD2 und Masse. Wir werden PD2 als Ausgangspin auf 0 V setzen und bei einer positiven Flanke an diesem Pin triggern. Wir möchten, dass die Kante sofort verschwindet, wenn wir die Taste loslassen, also fügen wir diesen "Pulldown" -Widerstand ein.

Der Grund, warum wir die Taste wollen, ist, dass wir unseren Analog-Digital-Wandler von Pin INT0 auf dem Chip auslösen möchten, der auch PD2 ist. Schließlich möchten wir, dass der Tastendruck sowohl den ADC auslöst als auch den zu konvertierenden Eingang ohne separate Taste bereitstellt, aber aufgrund der Funktionsweise des Timings werden wir mit einer separaten Taste zum Auslösen des ADC beginnen und sobald wir alles bügeln die Fehler beseitigt haben und zuversichtlich sind, dass alles ordnungsgemäß funktioniert, werden wir die Rausch- und Timing-Probleme angehen, die mit dem Auslösen mit demselben Tastendruck einhergehen, den wir lesen möchten.

Im Moment funktioniert es also so, dass wir eine Taste gedrückt halten, dann die Taste drücken, um den ADC auszulösen, und dann loslassen und hoffentlich wird der Binärwert der Taste, die wir gedrückt haben, auf dem Analysator angezeigt.

Lassen Sie uns also einen Code schreiben, der dies erreicht.

Schritt 6: Welche Kippschalter sollten wir einstellen?

Welche Kippschalter sollten wir einstellen?
Welche Kippschalter sollten wir einstellen?

Lassen Sie uns zuerst darüber nachdenken, wie wir dies codieren werden, damit der Controller die Eingabe von der Tastatur lesen und in einen numerischen Wert umwandeln kann, der der gedrückten Taste entspricht. Wir werden den Analog-Digital-Wandler (ADC) verwenden. das ist in den Atmega328p eingebaut. Wir verwenden AREF als Referenzspannung und unser Tastaturausgang wird an PortC0 oder PC0 angeschlossen. Beachten Sie, dass dieser Pin auch als ADC0 für den Analog-Digital-Wandler 0 bezeichnet wird. Es könnte eine gute Idee sein, Abschnitt 12.4 über Interrupts für den ATmega328P und auch Kapitel 24 über den Analog-Digital-Wandler durchzulesen, bevor wir gestartet oder haben diese Abschnitte zumindest zum Nachlesen bereit zugehörige Registerbits. Diese entsprechen im Wesentlichen den alten Kippschaltern der ersten Computer. Sie legen entweder einen Schalter auf EIN oder AUS, oder noch weiter hinten würden Sie Kabel zwischen einer Steckdose und einer anderen anschließen, damit Elektronen, die diese Weggabelung erreichen, ein Tor geschlossen und ein anderes geöffnet finden, das sie auf einen anderen Weg im Labyrinth von zwingt Schaltung und damit eine andere logische Aufgabe ausführen. Beim Codieren in Assembler haben wir einen engen Zugriff auf diese Funktionen des Mikrocontrollers, was einer der attraktiven Aspekte überhaupt ist. Es ist mehr "hands on" und viel weniger passiert sozusagen "hinter den Kulissen". Betrachten Sie das Einstellen dieser Register also nicht als mühsame Aufgabe. Das macht Assemblersprache interessant! Wir gewinnen eine sehr persönliche Beziehung zum Innenleben und der Logik des Chips und bringen ihn dazu, genau das zu tun, was wir wollen – nicht mehr und nicht weniger. Keine verschwendeten Taktzyklen. Hier ist eine Liste der Schalter, die wir einstellen müssen:

  1. Schalten Sie das ADC-Bit zur Leistungsreduzierung, PRADC, aus, das Bit 0 des PRR-Registers ist, da es den ADC abschaltet, wenn dieses Bit eingeschaltet ist. Das Leistungsreduzierungsregister ist im Wesentlichen eine Möglichkeit, verschiedene Dinge auszuschalten, die Strom verbrauchen, wenn Sie sie nicht benötigen. Da wir den ADC verwenden, möchten wir sicherstellen, dass er nicht auf diese Weise deaktiviert wird. (Siehe PRADC auf Seite 46)
  2. Wählen Sie den analogen Eingangskanal als ADC0 aus, indem Sie MUX3…0 im Register ADC Multiplexer Selection (ADMUX) ausschalten (siehe Tabelle 24-4 Seite 249). Diese sind standardmäßig bereits ausgeschaltet, so dass wir dies nicht wirklich tun müssen. Ich schließe es jedoch ein, da Sie diese Schalter entsprechend umschalten müssen, wenn Sie jemals einen anderen Port als ADC0 verwenden. Verschiedene Kombinationen von MUX3, MUX2, MUX1, MUX0 ermöglichen es Ihnen, jeden der analogen Ports als Eingang zu verwenden und diese auch im Handumdrehen zu ändern, wenn Sie eine Reihe verschiedener analoger Signale gleichzeitig betrachten möchten.
  3. Schalten Sie die Bits REFS0 und REFS1 im ADMUX-Register aus, damit wir AREF als Referenzspannung statt als interne Referenz verwenden (siehe Seite 248).
  4. Schalten Sie das ADLAR-Bit in ADMUX ein, damit das Ergebnis "linksangepasst" ist. Wir werden diese Auswahl im nächsten Schritt besprechen.
  5. Setzen Sie das ADC0D-Bit im Digital Input Disable Register (DIDR0), um den Digitaleingang an PC0 auszuschalten. Wir verwenden diesen Port für den analogen Eingang, also können wir auch den digitalen Eingang dafür deaktivieren.
  6. Setzen Sie ISC0 und ISC1 im External Interrupt Control Register A (EICRA), um anzugeben, dass wir bei der steigenden Flanke eines Spannungssignals an den INT0-Pin (PD2) triggern möchten, siehe Seite 71.
  7. Löschen Sie die Bits INT0 und INT1 im External Interrupt Mask Register (EIMSK), um anzuzeigen, dass wir keine Interrupts an diesem Pin verwenden. Wenn wir Interrupts an diesem Pin aktivieren würden, bräuchten wir einen Interrupt-Handler an der Adresse 0x0002, aber stattdessen richten wir ihn so ein, dass ein Signal an diesem Pin die ADC-Konvertierung auslöst, deren Abschluss durch den ADC-Konvertierungs-Complete-Interrupt bei. gehandhabt wird Adresse 0x002A. Siehe Seite 72.
  8. Setzen Sie das ADC Enable (ADEN) Bit (Bit 7) im ADC Steuer- und Statusregister A (ADCSRA), um den ADC zu aktivieren. Siehe Seite 249.
  9. Wir könnten eine einzelne Konvertierung starten, indem wir das ADC-Start-Konvertierungs-Bit (ADSC) jedes Mal setzen, wenn wir das analoge Signal lesen wollten, aber im Moment möchten wir es lieber automatisch lesen lassen, wenn jemand den Knopf drückt, also aktivieren wir stattdessen den ADC Bit Autotrigger Enable (ADATE) im ADCSRA-Register, damit die Triggerung automatisch erfolgt.
  10. Wir setzen auch die ADPS2..0-Bits (die AD Prescalar-Bits) auf 111, sodass der ADC-Takt der CPU-Takt geteilt durch einen Faktor von 128 ist.
  11. Als Quelle der ADC-Triggerung wählen wir PD2, die auch INT0 (External Interrupt Request 0) genannt wird. Wir tun dies, indem wir die verschiedenen Bits im ADCSRB-Register umschalten (siehe Tabelle 24-6 auf Seite 251). Wir sehen in der Tabelle, dass ADTS0 ausgeschaltet, ADTS1 eingeschaltet und ADTS2 ausgeschaltet sein soll, damit der ADC diesen Pin auslöst. Beachten Sie, wenn wir den analogen Port kontinuierlich abtasten möchten, wie wenn wir ein kontinuierliches analoges Signal lesen (wie Sound-Sampling oder so), würden wir dies auf den Freilaufmodus setzen. Die von uns verwendete Methode zum Einstellen der Triggerung auf PD2 löst ein ADC-Lesen des analogen Ports PC0 aus, ohne einen Interrupt zu verursachen. Der Interrupt kommt, wenn die Konvertierung abgeschlossen ist.
  12. Aktivieren Sie das ADC Interrupt Enable (ADIE)-Bit im ADCSRA-Register, damit nach Abschluss der Analog-Digital-Wandlung ein Interrupt generiert wird, für das wir einen Interrupt-Handler schreiben und auf.org 0x002A setzen können.
  13. Setzen Sie das I-Bit in SREG, um Interrupts zu aktivieren.

Übung 1: Stellen Sie sicher, dass Sie die relevanten Abschnitte im Datenblatt für jede der oben genannten Einstellungen lesen, damit Sie verstehen, was vor sich geht und was passieren würde, wenn wir sie auf alternative Einstellungen ändern.

Schritt 7: Schreiben Sie den Interrupt-Handler

Im letzten Schritt haben wir gesehen, dass wir es so eingerichtet haben, dass eine an PD2 erkannte steigende Flanke eine Analog-Digital-Wandlung an PC0 auslöst und wenn diese Konvertierung abgeschlossen ist, wird ein ADC-Konvertierungs-Vollständig-Interrupt ausgelöst. Jetzt wollen wir etwas mit diesem Interrupt machen. Wenn Sie sich Tabelle 12-6 auf Seite 65 ansehen, sehen Sie eine Liste der möglichen Interrupts. Den RESET-Interrupt bei Adresse 0x0000 und den Timer/Counter0 Overflow-Interrupt bei Adresse 0x0020 haben wir bereits in früheren Tutorials gesehen. Jetzt wollen wir uns den ADC-Interrupt ansehen, den wir in der Tabelle sehen, ist an der Adresse 0x002A. Am Anfang unseres Assembler-Codes benötigen wir also eine Zeile, die lautet:

.org 0x002Arjmp ADC_int

die zu unserem Interrupt-Handler mit der Bezeichnung ADC_int springt, wenn der ADC eine Konvertierung abgeschlossen hat. Wie sollen wir also unseren Interrupt-Handler schreiben? Der ADC funktioniert so, dass er die folgende Berechnung durchführt:

ADC = Vin x 1024 / Vref

Mal sehen, was passiert, wenn ich die Taste "Wahlwiederholung" auf der Tastatur drücke. In diesem Fall ändert sich die Spannung an PC0 auf einen Wert, sagen wir 1,52 V, und da Vref bei 5 V liegt, haben wir:

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

und so würde es als 311 erscheinen. Wenn wir dies wieder in eine Spannung umwandeln wollten, würden wir die Berechnung einfach umkehren. Wir müssen dies jedoch nicht tun, da wir nicht an den tatsächlichen Spannungen interessiert sind, nur um sie zu unterscheiden. Wenn die Konvertierung abgeschlossen ist, wird das Ergebnis in einer 10-Bit-Zahl gespeichert, die in den ADCH- und ADCL-Registern platziert wird, und wir haben es veranlasst, dass es "linksangepasst" wird, was bedeutet, dass die 10-Bits bei Bit 7 von ADCH beginnen und auf. heruntergehen Bit 6 von ADCL (insgesamt gibt es 16 Bits in diesen beiden Registern und wir verwenden nur 10 davon, dh 1024 Kanäle). Wir könnten das Ergebnis "rechtsangepasst" haben, wenn wir wollten, indem wir das ADLAR-Bit im ADMUX-Register löschen. Der Grund, warum wir linksangepasst wählen, ist, dass unsere Signale weit genug voneinander entfernt sind, dass die letzten beiden Stellen der Kanalnummer nicht relevant sind und sind wahrscheinlich nur Rauschen, daher werden wir die Tastendrücke nur anhand der oberen 8 Ziffern unterscheiden, mit anderen Worten, wir müssen uns nur den ADCH ansehen, um herauszufinden, welche Taste gedrückt wurde. Unser Interrupt-Handler sollte also einfach die Nummer aus dem ADCH lesen registrieren, diese Zahl in einen Tastaturwert umwandeln und diesen Wert dann an unsere Registeranalysator-LEDs senden, damit wir überprüfen können, ob das Drücken einer "9" zum Aufleuchten der LEDs entsprechend "00001001" führt Allerdings müssen wir zuerst sehen, was in ADCH angezeigt wird, wenn wir die verschiedenen Tasten drücken. Schreiben wir also einfach einen einfachen Interrupt-Handler, der nur den Inhalt von ADCH an das Display des Analysators sendet. Hier ist also, was wir brauchen:

ADC_int:lds Analyzer, ADCH;Lade den Wert von ADCH in unseren Analyzerbi EIFR, 0; Löschen Sie das externe Interrupt-Flag, damit es wieder einsatzbereit istreti

Inzwischen sollten Sie in der Lage sein, einfach den Code aus unserem Analyzer in Tutorial 5 zu kopieren und diesen Interrupt und die Toggle-Einstellungen hinzuzufügen und auszuführen. Übung 2: Schreiben Sie den Code und führen Sie ihn aus. Achten Sie darauf, dass die ADCH-Anzeige auf Ihrem Analysator-Display angezeigt wird. Versuchen Sie, dieselbe Taste mehrmals zu drücken. Bekommst du in ADCH immer den gleichen Wert?

Schritt 8: Zuordnen der Tastendruckwerte

Ordnen Sie die Tastendruckwerte zu
Ordnen Sie die Tastendruckwerte zu

Was wir jetzt tun müssen, ist die Werte in ADCH in Zahlen umzuwandeln, die der gedrückten Taste entsprechen. Wir tun dies, indem wir den Inhalt von ADCH für jeden Tastendruck ausschreiben und diesen dann in eine Dezimalzahl umwandeln, wie ich es im Bild getan habe. In unserer Interrupt-Behandlungsroutine betrachten wir einen ganzen Bereich von Werten als korrespondierend zu jedem Tastendruck, so dass der ADC alles in diesem Bereich einem gegebenen Tastendruck zuordnet.

Übung 3: Führen Sie diese Zuordnung durch und schreiben Sie dann Ihre ADC-Interrupt-Routine neu.

Hier ist, was ich für meine habe (Ihre wird sehr wahrscheinlich anders sein). Beachten Sie, dass ich es mit einem Wertebereich für jeden Tastendruck eingerichtet habe.

ADC_int:; Externer Interrupt-Handlerclr-Analysator; auf neue Nummern vorbereiten buttonH, ADCH; ADC aktualisiert, wenn ADCH gelesen wird clccpi buttonH, 240brlo PC+3; wenn ADCH größer ist, ist es ein 1ldi-Analysator, 1; also Load Analyzer mit 1rjmp Return; und Zurück-Clccpi-Taste H, 230; wenn ADCH größer ist als ein 2brlo PC+3ldi Analyzer, 2rjmp return clccpi buttonH, 217brlo PC+3ldi Analyzer, 3rjmp return clccpi buttonH, 203brlo PC+3ldi Analyzer, 4rjmp return clccpi buttonH, 187brlo PC+3ldi Analyzer, 5ccrjmp zurück cl 155brlo PC+3ldi-Analysator, 6rjmp return clccpi buttonH, 127brlo PC+3ldi-Analysator, 255; Wir werden Flash als alle einstellen. 0b111100000; Stern ist die obere Hälfte onrjmp return clccpi buttonH, 28brlo PC+3ldi Analyzer, 0rjmp return clccpi buttonH, 17brlo PC+3ldi Analyzer, 0b00001111; Hash-Zeichen ist untere Hälfte onrjmp return clccpi buttonH, 5brlo PC+3ldi Analyzer, 0b11000011; Wahlwiederholung ist oben 2 unten 2rjmp return ldi-Analysator, 0b11011011; andernfalls ist ein Fehler aufgetreten return:reti

Schritt 9: Code und Video für Version 1

Ich habe meinen Code für diese erste Version des Tastaturtreibers angehängt. In diesem müssen Sie die Taste drücken und dann die Taste drücken, damit der ADC die Eingabe von der Tastatur liest. Was wir lieber hätten, ist keine Schaltfläche, sondern das Signal für die Konvertierung kommt vom Tastendruck selbst. Übung 3: Bauen Sie diesen Code zusammen, laden Sie ihn hoch und probieren Sie ihn aus. Möglicherweise müssen Sie die verschiedenen Konvertierungsschwellenwerte ändern, um Ihren Tastendruckspannungen zu entsprechen, da sie sich wahrscheinlich von meinen unterscheiden. Was passiert, wenn Sie versuchen, eine Eingabe über die Tastatur sowohl für den ADC0 als auch für den externen Interrupt-Pin anstelle einer Taste zu verwenden?Ich füge auch ein Video zur Bedienung dieser ersten Version unseres Tastendrucktreibers bei. Sie werden das bemerken in meinem Code gibt es einen Abschnitt, der den Stack Pointer initialisiert. Es gibt verschiedene Register, die wir möglicherweise aus dem Stapel schieben und entfernen möchten, wenn wir Variablen manipulieren und was nicht, und es gibt auch Register, die wir möglicherweise später speichern und wiederherstellen möchten. SREG ist beispielsweise ein Register, das nicht über Interrupts hinweg beibehalten wird, sodass die verschiedenen Flags, die als Ergebnis von Operationen gesetzt und gelöscht werden, geändert werden können, wenn ein Interrupt mitten in etwas auftritt. Es ist also am besten, wenn Sie SREG am Anfang eines Interrupt-Handlers auf den Stack legen und am Ende des Interrupt-Handlers wieder ablegen. Ich habe es in den Code eingefügt, um zu zeigen, wie es initialisiert wird und um vorauszusehen, wie wir es später brauchen werden, aber da es uns egal ist, was mit SREG während Interrupts in unserem Code passiert, habe ich den Stack dafür nicht verwendet dass ich die Schiebeoperation verwendet habe, um beim Initialisieren verschiedene Bits in Registern zu setzen. Zum Beispiel in der Zeile:

ldi-Temp, (1<> M. EICRA, temp

Der Befehl "<<" in der ersten Codezeile oben ist eine Shift-Operation. Es nimmt im Wesentlichen die Binärzahl 1, die 0b00000001 ist, und verschiebt sie um den Betrag der Zahl ISC01 nach links. Dies ist die Position des Bits namens ISC01 im EICRA-Register. Da ISC01 Bit 1 ist, wird die Zahl 1 an die linke 1-Position verschoben, um 0b00000010 zu werden. In ähnlicher Weise ist die zweite, ISC00, das Bit 0 von EICRA, und daher ist die Verschiebung der Zahl 1 Nullstellen nach links. Wenn Sie sich noch einmal die Datei m328Pdef.inc ansehen, die Sie im ersten Tutorial heruntergeladen haben und seitdem evrr verwenden, werden Sie feststellen, dass es sich nur um eine lange Liste von ".equ"-Anweisungen handelt. Sie werden feststellen, dass ISC01 gleich 1 ist. Der Assembler ersetzt jede Instanz davon durch 1 bevor er überhaupt mit dem Assemblieren beginnt. Sie sind nur Namen für Registerbits, die uns Menschen beim Lesen und Schreiben von Code helfen. Nun ist die vertikale Linie zwischen den beiden obigen Verschiebeoperationen eine logische "Oder"-Operation. Hier ist die Gleichung:

0b00000010 | 0b00000001 = 0b00000011

und das laden wir (mit "ldi") in temp. Der Grund, warum Leute diese Methode verwenden, um Werte in ein Register zu laden, besteht darin, dass man den Namen des Bits anstelle einer Zahl verwenden kann und der Code dadurch viel einfacher zu lesen ist. Es gibt auch zwei andere Techniken, die wir verwendet haben. Wir verwenden die Anweisungen "ori" und "andi". Diese ermöglichen es uns, Bits zu setzen bzw. zu löschen, ohne irgendwelche der anderen Bits in einem Register zu ändern. Zum Beispiel, als ich verwendet habe

ori-Temp, (1

diese "oder" temp mit 0b00000001, was eine 1 in das nullte Bit setzt und den Rest unverändert lässt. Auch als wir schrieben

andi temp, 0b11111110

Dies ändert das nullte Bit von temp auf eine 0 und lässt den Rest unverändert.

Übung 4: Sie sollten den Code durchgehen und sicherstellen, dass Sie jede Zeile verstehen. Vielleicht finden Sie es interessant, bessere Methoden zu finden, um Dinge zu tun und ein besseres Programm zu schreiben. Es gibt hundert Möglichkeiten, Dinge zu codieren, und ich bin ziemlich zuversichtlich, dass Sie einen viel besseren Weg als meinen finden können. Sie können auch (Himmel bewahre!) Fehler und Auslassungen finden. In diesem Fall würde ich gerne von ihnen hören, damit sie behoben werden können.

Okay, mal sehen, ob wir diesen überflüssigen Knopf loswerden können…

Schritt 10: Code für Version 2

Der einfachste Weg, die Schaltfläche loszuwerden, besteht darin, sie ganz zu entfernen, die Eingabe in PB2 zu vergessen und den ADC einfach in den "Freilaufmodus" zu schalten.

Mit anderen Worten, ändern Sie einfach das ADCSRB-Register, so dass ADTS2, ADTS1 und ADTS0 alle Nullen sind.

Setzen Sie dann das ADSC-Bit in ADCSRA auf 1, wodurch die erste Konvertierung gestartet wird.

Laden Sie es nun auf Ihren Mikrocontroller hoch und Sie werden feststellen, dass die richtige Zahl auf dem Display angezeigt wird, während Sie die Taste drücken und nur während Sie die Taste drücken. Dies liegt daran, dass der ADC kontinuierlich den ADC0-Port abtastet und den Wert anzeigt. Wenn Sie Ihren Finger von der Taste nehmen, führt das "Tastenprellen" dazu, dass sehr schnell einige zufällige Werte auftreten und sich dann wieder auf den 0-V-Eingang einpendelt. In unserem Code haben wir diese 0V als 0b11011011 (da der Tastendruck '0' bereits den Anzeigewert 0b00000000 verwendet)

Dies ist jedoch aus zwei Gründen nicht die Lösung, die wir wollen. Zuerst wollen wir den Knopf nicht halten müssen. Wir möchten es einmal drücken und die Nummer anzeigen lassen (oder in einem neuen Code in einem späteren Tutorial verwenden). Zweitens wollen wir den ADC0 nicht ständig abtasten. Wir möchten, dass es einen einzelnen Messwert nimmt, konvertiert und dann schläft, bis ein neuer Tastendruck eine neue Konvertierung auslöst. Der Freilaufmodus ist am besten, wenn der Mikrocontroller nur kontinuierlich einen analogen Eingang lesen soll - beispielsweise wenn Sie Echtzeittemperaturen oder ähnliches anzeigen möchten.

Also lasst uns noch eine andere Lösung finden…

Schritt 11: Wie werden wir den Knopf los? Version 3

Wie werden wir den Knopf los? Version 3
Wie werden wir den Knopf los? Version 3

Es gibt zahlreiche Möglichkeiten, wie wir vorgehen könnten. Zuerst könnten wir Hardware hinzufügen, um die Schaltfläche loszuwerden. Zum Beispiel können wir versuchen, einen Transistor in die Schaltung an der Ausgangsleitung des Tastendrucks einzubauen, damit er ein kleines Rinnsal des Stroms vom Ausgang nimmt und einen 5-V-Impuls an den Interrupt-Pin PD2 sendet.

Dies wäre jedoch wahrscheinlich zumindest zu laut und würde im schlimmsten Fall nicht genügend Zeit für eine genaue Tastendruckmessung lassen, da der Spannungsausgang des Tastenfelds keine Zeit hätte, sich zu stabilisieren, bevor der ADC-Wert erfasst wird.

Da würden wir uns lieber eine Softwarelösung einfallen lassen. Was wir gerne tun möchten, ist einen Interrupt auf dem PD2-Pin hinzuzufügen und einen Interrupt-Handler dafür zu schreiben, der ein einzelnes Lesen des Keypad-Pins aufruft. Mit anderen Worten, wir entfernen den Autotrigger-Interrupt vom ADC und fügen einen externen Interrupt hinzu, der den ADC darin aufruft. Auf diese Weise kommt das Signal zum Lesen des ADC, nachdem das PD2-Signal bereits aufgetreten ist, und dies könnte genug Zeit geben, um sich auf eine genaue Spannung zu stabilisieren, bevor der PC0-Pin gelesen und konvertiert wird. Wir hätten immer noch einen ADC-Completion-Interrupt, der das Ergebnis am Ende auf dem Display des Analysators ausgibt.

Sinn ergeben? Nun, lass es uns tun…

Sehen Sie sich den angehängten neuen Code an.

Sie sehen die folgenden Änderungen:

  1. Wir haben einen rjmp unter der Adresse.org 0x0002 hinzugefügt, um den externen INT0-Interrupt zu verarbeiten
  2. Wir haben das EIMSK-Register geändert, um anzuzeigen, dass wir am INT0-Pin unterbrechen möchten
  3. Wir haben den ADATE-Pin im ADCSRA-Register geändert, um das Autotriggering zu deaktivieren
  4. Wir haben die ADCSRB-Einstellungen entfernt, da sie irrelevant sind, wenn ADATE ausgeschaltet ist
  5. Wir müssen das externe Trigger-Flag nicht mehr zurücksetzen, da die INT0-Interrupt-Routine dies automatisch tut, wenn sie abgeschlossen ist Löschen Sie diese Flagge von Hand.

Jetzt rufen wir im Interrupt-Handler einfach eine einzelne Konvertierung vom ADC auf.

Übung 5: Führen Sie diese Version aus und sehen Sie, was passiert.

Schritt 12: Code und Video für die Arbeitsversion

Wie wir in der letzten Version gesehen haben, funktioniert der Button-Interrupt nicht sehr gut, da der Interrupt bei einer steigenden Flanke an Pin PD2 ausgelöst wird und dann der Interrupt-Handler die ADC-Konvertierung aufruft. Der ADC erhält dann jedoch den Spannungswert, bevor er sich stabilisiert hat, und liest daher Unsinn.

Was wir brauchen, ist eine Verzögerung zwischen dem Interrupt auf PD2 und dem ADC-Lesen auf PC0 einzuführen. Wir werden dies tun, indem wir einen Timer/Zähler, einen Zählerüberlauf-Interrupt und eine Verzögerungsroutine hinzufügen. Zum Glück wissen wir bereits aus Tutorial 3, wie das geht! Wir werden also einfach den entsprechenden Code von dort kopieren und einfügen.

Ich habe den resultierenden Code und ein Video gegeben, das ihn in Betrieb zeigt.

Sie werden feststellen, dass die Messwerte nicht so genau sind, wie man es sich erhoffen würde. Dies liegt wahrscheinlich an einer Reihe von Quellen:

  1. Wir klopfen vom Spannungsausgang der Tastatur, um auf PD2 zu triggern, was den Messwert in PC0 beeinflusst.
  2. Wir wissen nicht wirklich, wie lange wir nach dem Trigger verzögern müssen, um den besten Messwert zu erhalten.
  3. Es dauert einige Zyklen, bis die ADC-Wandlung abgeschlossen ist, was bedeutet, dass wir kein Schnellfeuer auf die Tastatur ausführen können.
  4. Es ist wahrscheinlich ein Rauschen in der Tastatur selbst.
  5. etc…

Obwohl wir es also geschafft haben, die Tastatur zum Laufen zu bringen und sie jetzt in Anwendungen verwenden können, indem wir die Tastendruckwerte auf andere Weise verwenden, anstatt sie nur auf dem Display des Analysators auszugeben, ist sie nicht sehr genau und sehr ärgerlich. Deshalb denke ich, dass der beste Weg, Tastaturen zu verdrahten, darin besteht, einfach jeden Ausgang der Tastatur in einen anderen Port zu stecken und zu entscheiden, welche Taste von welchen Ports gedrückt wird, um eine Spannung zu sehen. Das ist einfach, sehr schnell und sehr genau.

Tatsächlich gibt es nur zwei Gründe, warum man eine Tastatur so ansteuern möchte, wie wir es hier getan haben:

  1. Es verwendet nur 2 der Pins auf unserem Mikrocontroller anstelle von 8.
  2. Es ist ein großartiges Projekt, um verschiedene Aspekte des ADC auf dem Mikrocontroller zu zeigen, die sich von den Standarddingen unterscheiden, die Sie dort finden können, wie Temperaturmesswerte, Drehpotentiometer usw. Ich wollte ein Beispiel für getriggerte Einzelmesswerte und externe Pin-Autotriggerung anstatt nur den frei laufenden CPU-Gobbling-Modus.

Wie auch immer, hier sind ein paar letzte Übungen für Sie:

Übung 6: Schreiben Sie den Interrupt-Handler für die vollständige ADC-Umwandlung neu, um eine Nachschlagetabelle zu verwenden. D.h. Damit testet es den Analogwert mit dem ersten Item in der Tabelle und wenn es größer ist kehrt es aus dem Interrupt zurück, wenn nicht, dann inkrementiert es Z zum nächsten Item in der Tabelle und verzweigt wieder zum Test zurück. Dadurch wird der Code gekürzt und die Interrupt-Routine aufgeräumt und sie sieht schöner aus. (Ich werde als nächsten Schritt eine mögliche Lösung nennen) Übung 7: Schließen Sie Ihre Tastatur an 8 Pins des Mikrocontrollers an und schreiben Sie den einfachen Treiber dafür und erleben Sie, wie viel schöner es ist. Können Sie sich ein paar Möglichkeiten vorstellen, wie unsere Methode besser funktioniert?

Das ist alles für dieses Tutorial. Die endgültige Version habe ich mit Hinweisen angehängt. Als wir unserem Endziel näher kommen, werden wir in Tutorial 9 noch einmal die Tastatur verwenden, um zu zeigen, wie man Sieben-Segment-Anzeigen damit steuert (und etwas Interessantes baut, das die zusätzlichen Tasten auf der Telefontastatur verwendet) und dann werden wir Wechseln Sie stattdessen zur Steuerung von Dingen mit Tastendrücken (da diese Methode besser zu dem Endprodukt passt, auf das wir mit diesen Tutorials hinarbeiten) und wir werden die Tastatur einfach auf den Tisch legen.

Bis zum nächsten Mal!

Empfohlen: