Hintergrundinformationen zum Analog Digital Konverter:
Der hat natürlich auch 'n eigenes Kapitel im Datenblatt (in der aktuellen Version ab Seite 189), und da am Anfang auch ein Blockschema.
Wie alle Peripheriemodule kann Dein Programm nur über I/O-Register (über den Datenbus) auf den ADC zugreifen - der ADC besitzt drei Register (eines davon als Doppelregister bzw 16bit-Register)
Das ADC Multiplexer Select Register (ADMUX), das ADC Control and Status Register (ADCSRA) und das ADC Data Register (ADC).
Links siehst Du zwei Multiplexer, einen kleinen für die Wahl der Referenzspannung, und einen größeren für die Wahl des zu messenden Kanals.
Gemessen werden können die Spannungen an den Beinen C0..C5 (ADC0..ADC5), an den Beinen ADC6 und ADC7 (gibt's nur in SMD-Packages, nicht beim PDIP), die interne 1,1V-Bandgap-Referenz und Gnd (die letzten beiden eher zu Kalibrationszwecken).
In ADMUX wird also gewählt, welchen Kanal der Multiplexer durchlegen soll.
Bei der Referenzspannung hast Du die Wahl, ob die interne 2,56V-Referenz verwendet werden soll, oder die (interne) analoge Versorgungsspannung (AVcc) - beide liegen dann auch am Aref-Bein an, und sollten dort mit einem Kerko gestützt werden. Alternativ kann man den Multiplexer dort auch abkoppeln (REFS0), und dann (nur dann) eine externe Vergleichsspannung an Aref einspeisen.
Auch diese Wahl wird im ADMUX festgelegt.
Wir haben also den zu messenden Kanal und die Referenz festgelegt, was nun?
Das Arbeitsprinzip des ADC ist schrittweise Approximation - er leitet aus der Referenz Spannungen ab, die er an die zu messende Spannung angleicht.
Dazu steht ihm ein 10-Bit-Analog-Digital-Konverter und ein Komperator zur Verfügung.
Wenn eine Messung angestoßen wird, beginnt die Kontrolllogik mit dem höchsten Bit, es wird vereinfacht gesagt das höchste Bit gesetzt, der DAC liefert die halbe Referenzspannung, diese wird mit der zu bestimmenden Spannung "verglichen" (der Komparator liefert 'ne 0 wenn der DAC-Ausgang größer ist, und 'ne 1 wenn er kleiner ist). Der Ausgang des Komparators hat damit das erste Ergebnisbit festgelegt, Schrittweise geht's mit den restlichen Bits weiter (dieses Bit bleibt also auch im DAC stehen, weiter geht's mit dem 2ten...3ten... … 10ten Bit)
Wenn so alle 10 Bits bestimmt sind, werden diese in das Ergebnisregister übertragen - da zehn Bit nicht in ein Byte passen, besteht das Ergebnisregister aus zwei Byte Registern. Dem ADCH und dem ADCL. Außerdem wird im ADCSRA gemeldet, daß der ADC fertig ist; mit dem Flag ADIF (ADC Interrupt Flag). An ADIF könnte(!!) auch ein Interrupt gekoppelt werden.
"Schrittweise" bedeutet, daß das ganze irgendwie getaktet werden muß, empfohlen sind (bei voller 10bit-Auflösung) höchstens 200kHz. Da der Takt aus dem Systemtakt abgeleitet wird, muß der Takt (im allgemeinen) über einen Vorteiler reduziert werden. Dieser wird konsequenterweise im ADCSRA gewählt. Eine normale Konversion benötigt etwa 13 Takte dieser Takte.
Und in Bascom?
natürlich kannst Du auch hier selbst in ADMUX die Multiplexer einstellen, in ADCSRA den Prescaler festlegen, den ADC überhaupt erst aktivieren, und 'ne Messung starten - aber natürlich bietet Bascom Dir auch 'nen komfortablen Konfigurationsbefehl an (wie wir ja auch schon beim Timer1 verwendet haben.
Für den ADC ist das (nicht sonderlich überraschend):
Config ADC
Als erster Parameter ist der Running Mode anzugeben. Wir wollen jede Messung einzeln anstoßen (single), hier könnte man den ADC auch im Dauerlauf betreiben.
Parameter zwei legt den Prescaler fest, man kann hier einen festen Vorteiler festlegen, oder Bascom den kleinsten (schnellsten) Vorteiler unter Beachtung der maximalen 200kHz selbst bestimmen lassen (Auto).
Parameter drei legt die zu verwendende Referenz fest. In der Tabelle fehlt der Mega8 - es gilt trotzdem die letzte Zeile: ADC-Referenzmodel-8.
Erlaubt sind hier
AREF
bzw
OFF
(also interne Referenzen abgekoppelt, eine extern an Aref angeschlossene Spannung liefert die Referenz), oder
AVcc
(die analoge Spannungsversorgung vom AVcc-Bein wird
intern über den Multiplexer als Referenz verwendet, liegt dabei aber zusätzlich am Aref-Bein an und sollte dort gestützt werden), oder
INTERNAL
bzw
INTERNAL_2.56
(hier wird die interne 2.56V-Referenz über den Multiplexer geschaltet. auch sie liegt dann am Aref-Bein an und ist dort zu stützen).
Obacht: bei einigen Experimentierplatinen ('n Klassiker mit diesem Fauxpas war meiner Erinnerung nach irgendein Pollin-Board) liegen am Aref-Bein immer extern Vcc (5V) an. Schaltet man da auf 'ne interne Referenz auf, ist diese gegen Vcc geschlossen...
(bei AVcc vs. Vcc passiert sicher nicht viel, bei 1,1V vs. 5V siehts sicher anders aus...)
So, wir Initialisieren den ADC also im Single-Mode, lassen Bascom den Prescaler automatisch festlegen, und wählen als Referenz die interne analoge Versorgungsspannung (da unser Poti ja irgendwas zwischen Gnd und (A)Vcc liefert:
CodeBox BascomAVR
Config ADC = Single , Prescaler = Auto , Reference = Avcc
Die Zeile würde ich direkt vor dem "Config Timer1" platzieren, also in Zeile 17.
Der ADC liefert als Ergebnis wie gesagt 'ne 10-Bit-Ganzzahl - wir benötigen also eine Wordvariable. In Zeile 10 wird also eine weitere Variable dimensioniert:
CodeBox BascomAVR
Dim Poti As Word 'ADC-Messergebnis
Für eine single-Messung bietet Bascom die Funktion
getadc()
an. Sie erwartet als Parameter den zu messenden Kanal, startet die Messung, wartet(!!) das Ergebnis ab, und liefert das Ergebnis als Word zurück. Wir wollen ADC0=C0 messen (Kanal 0 ) und das Ergebnis in "Poti haben, also:
CodeBox BascomAVR
Poti = Getadc(0)
Für einen ersten Test platzieren wir diese Zeile im zweiten Teilprogramm direkt nach dem toggeln von "grün". Dadurch wird jede Sekunde 'ne Messung durchgeführt (und der Variable zugewiesen). Anschließend soll das Ergebnis einfach mal seriell ausgegeben werden:
CodeBox BascomAVR
Print "Poti: ", Poti