Allgemeines
Die wichtigsten Eigenschaften des ADC:
- 10 Bit Auflösung
- Bis zu 15 Tausend Wandlungen pro Sekunde
- 8 gemultiplexte Eingänge (in Kombination zu 7 differentiellen Messungen und 2 mit Verstärkung von 10 oder 200)
- Messungen bis \(V_{CC}\)
- Integrierte 2.56 V Referenzspannung
Aufbau
Eingänge
Im linken unteren Segment sind die Eingänge, die über Multiplexer zum eigentlichen ADC geführt werden. Der Multiplexer "Pos. Input Mux" kann zwischen den 8 Pins ADC0 bis ADC7 sowie Masse und einer Bandgap-Referenz (typ. 1.23 V) wählen.
Für differentielle Messungen wird jeweils ein zweiter Kanal benötigt, der über den Multiplexer "Neg. Input Mux" ausgewählt wird. Der positive und negative Kanal wird durch eine einstellbare Verstärkung (Gain Amplifier) zu einem Multiplexer geführt, der auswählt, ob eine sog. Single Ended oder eine differentielle Messung durchgeführt wird.
AD Wandlung
Der ADC arbeitet mittels einer 10 Bit sukzessiven Approximation. Dazu wird ein 10 Bit DAC schrittweise auf die zu messende Spannung eingestellt. Mit jedem Bit mehr Auflösung wird über einen Komperator (Sample & Hold Comperator) entschieden, ob das nächste Bit 0 oder 1 sein soll. Als Konsequenz dieses Ablaufs benötigt diese Art von ADC mehrere Takte für die Umwandlung.
Referenz
Als Referenz stehen drei Quellen zur Verfügung:
- Die analoge Betriebsspannung AVCC
- Die interne 2.56 Volt Referenzspannung
- Eine externe Referenzspannung am Pin AREF
Register
Register ADMUX
Das Register ADMUX
steuert die Auswahl der Referenzspannung, der Anordnung der Datenbits und die Auswahl des zu messenden Kanals.
Wird als Referenzspannung die interne 2.56 Volt Referenz oder die Betriebsspannung AVCC gewählt empfiehlt es sich, an den Pin AREF einen Kondensator zu schalten, um Rauschen zu minimieren und die Referenzspannung möglichst stabil zu halten. In diesen zwei Fällen sollte auf keinen Fall eine externe Spannung am Pin AREF anliegen!
Die Anordnung der Datenbits mittels ADLAR kann je nach Anwendung eingestellt werden. Wird der 10 Bit Wert verwendet, kann beim avr-gcc Compiler mittels ADC auf die Kombination von ADCH und ADCL zugegriffen werden. Wenn einzeln auf die Register zugegriffen wird muss ADCL vor ADCH ausgelsen werden.
Register ADCSRA
ADEN - ADC Enable
Schaltet den ADC ein.
ADSC - ADC Start Conversion
Um eine Wandlung zu starten wird dieses Bit mit 1
beschrieben. Beim Lesen liefert dieses Bit eine 1
solange eine Wandlung läuft.
ADATE - ADC Auto Trigger Enable
Es gibt zahlreiche Möglichkeiten, eine Wandlung durch Trigger starten zu lassen. Weitere Infos dazu finden sich im Datenblatt. Hier wird ausschließlich das Starten einer Wandlung durch die Firmware selbst beziehungsweise ein erneutes Starten nach einer Wandlung beschrieben.
ADIF - ADC Interrupt Flag
Wenn eine Wandlung beendet wurde wird dieses Bit auf 1
gesetzt. Eine eventuell aktivierte Interruptroutine des ADCs setzt dieses Bit wieder auf 0
, sobald die entsprechende Interruptroutine aufgerufen wurde. Wird ohne Interrupts gearbeitet kann mittels schreiben einer 1
auf dieses Bit das Bit zurückgesetzt werden.
ADIE -ADC Interrupt Enable
Aktiviert den ADC Interrupt (siehe Beispiele)
ADPS2:0 - ADC Prescaler Select Bits
Wählt den Teiler für die Wandlung des ADCs. Der ADC arbeitet mit einer Frequenz zwischen 50kHz und 200kHz. Diese Frequenz wird aus dem Prozessortakt und diesem Teiler erzeugt.
$$f_{ADC}=\frac{f_{CLK}}{Teiler}$$
Umrechnung
Bei der Umrechnung einer Spannung am Eingang des ADC hin zum Wert als Zahl wird die Eingangsspannung im Verhältnis zur Referenzspannung betrachtet und entsprechend der Auflösung (in Bits} des ADC umgewandelt:
$$Wert_{ADC}=\frac{U_{Eingang}}{U_{Referenz}} \cdot 2^{Bits}$$
Der Umgekehrte Fall ist dann die Umrechnung von einem Wert in die anliegende Spannung:
$$U_{Eingang}=\frac{Wert_{ADC}}{2^{Bits}} \cdot U_{Referenz}$$
Beim ATMega16 ist die Auflösung 10 Bit, d.h. es können \(2^{10}=1024\) verschiedene Spannungen unterschieden werden.
Beispiele
Im folgenden Beispiel wird an Kanal 5 (Port A5) die Spannung gemessen. Als Referenz dient die Spannung am Pin AREF. Vom 10 Bit Ergebnis werden die oberen 8 Bit auf dem Port C ausgegeben.
Ohne Interrupt
#include <avr/io.h> int main (void) { DDRC = 0xFF; // Port C.0-7 = Ausgang PORTC = 0x00; // LEDs loeschen ADMUX = 0x05; // Eingang 5 festlegen ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1); // ADC enable, Teiler auf 64 while (1) { ADCSRA |= (1<<ADSC); // ADC Wandlung starten while(!(ADCSRA & (1<<ADIF))); // Auf Abschluss der Konvertierung warten (ADIF-bit) PORTC = ADC>>2; // Ausgabe der oberen 8 Bit auf PORTC } return 0; }
Mit Interrupt
Bei jedem Aufruf der Interruptservice Routine ADC_vect
wird das Ergebnis der AD Wandlung ausgewertet (mittels ADC
) und eine neue Wandlung gestartet.
#include <avr/io.h> #include <avr/interrupt.h> ISR(ADC_vect) { PORTC = ADC>>2; // Ausgabe der oberen 8 Bit auf PORTC ADCSRA |= (1<<ADSC); // ADC Wandlung starten } int main (void) { DDRC = 0xFF; // Port C.0-7 = Ausgang PORTC = 0x00; // LEDs loeschen ADMUX = 0x05; // Eingang 5 festlegen ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // ADC enable, //Wandlung starten, Interrupt enable, Teiler auf 64 sei(); while (1) { // main loop } return 0; }