Aus RN-Wissen.de
Wechseln zu: Navigation, Suche


(Referenzspannung)
(ADCSRA)
Zeile 164: Zeile 164:
 
*'''ADEN (ADC Enable)'''<br/>Wird dieses Bit gesetzt (also 1), dann wird der ADC aktiviert. Schreibt man eine 0 wird der ADC deaktiert. Wird der ADC während einer Wandlung deaktiviert, wird die Wandlung abgebrochen.
 
*'''ADEN (ADC Enable)'''<br/>Wird dieses Bit gesetzt (also 1), dann wird der ADC aktiviert. Schreibt man eine 0 wird der ADC deaktiert. Wird der ADC während einer Wandlung deaktiviert, wird die Wandlung abgebrochen.
 
*'''ADSC (ADC Start Conversion)'''<br/>Dieses Bit startet den Messvorgang, je nachdem in welchem Betriebsmodi der ADC läuft. Wird dieses Bit nach der Aktivierung des ADC über '''ADEN''' zum ersten Mal gesetzt, wird der ADC erst eine Initialisierungswandlung durchführen und danach erst die eigentliche Wandlung. Das Schreiben einer 0 auf das Bit hat keinen Effekt.
 
*'''ADSC (ADC Start Conversion)'''<br/>Dieses Bit startet den Messvorgang, je nachdem in welchem Betriebsmodi der ADC läuft. Wird dieses Bit nach der Aktivierung des ADC über '''ADEN''' zum ersten Mal gesetzt, wird der ADC erst eine Initialisierungswandlung durchführen und danach erst die eigentliche Wandlung. Das Schreiben einer 0 auf das Bit hat keinen Effekt.
*'''ADATE (ADC Auto Trigger Enable)'''<br/>Wird dieses Bit gesetzt, wird das Auto Triggering des ADC aktiviert.
+
*'''ADATE (ADC Auto Trigger Enable)'''<br/>Wird dieses Bit gesetzt, wird das Auto Triggering des ADC aktiviert. Die genaue Triggerquelle wir im Register '''SFIOR''' eingestellt. Default ist das der Free-runnng mode.
 
*'''ADIF (ADC Interrupt Flag)'''<br/>Dieses Bit wird auf 1 gesetzt, wenn eine Wandlung erfolgte und das Ergebnis nun verfügbar ist. Der ADC Complete Interrupt wird ausgelöst, wenn das '''ADIE'''-Bit gesetzt ist und die Interrupts global aktiviert sind. Das Bit wird gelöscht, wenn die entsprechende [[ISR]] abgearbeitet wird. Alternativ kann man es löschen, indem man eine 1 auf das Bit schreibt.
 
*'''ADIF (ADC Interrupt Flag)'''<br/>Dieses Bit wird auf 1 gesetzt, wenn eine Wandlung erfolgte und das Ergebnis nun verfügbar ist. Der ADC Complete Interrupt wird ausgelöst, wenn das '''ADIE'''-Bit gesetzt ist und die Interrupts global aktiviert sind. Das Bit wird gelöscht, wenn die entsprechende [[ISR]] abgearbeitet wird. Alternativ kann man es löschen, indem man eine 1 auf das Bit schreibt.
 
*'''ADIE (ADC Interrupt Enable)'''<br/>Wird dieses Bit gesetzt und die globalen Interrupts sind aktiviert, wird der ADC Complete Interrupt aktiviert, auf den man dann in der entsprechenden [[ISR]] reagieren kann.
 
*'''ADIE (ADC Interrupt Enable)'''<br/>Wird dieses Bit gesetzt und die globalen Interrupts sind aktiviert, wird der ADC Complete Interrupt aktiviert, auf den man dann in der entsprechenden [[ISR]] reagieren kann.
Zeile 193: Zeile 193:
 
*'''ADPS1 (ADC Prescaler Select Bit 1)'''<br/>Siehe '''ADPS2''' für eine Beschreibung.
 
*'''ADPS1 (ADC Prescaler Select Bit 1)'''<br/>Siehe '''ADPS2''' für eine Beschreibung.
 
*'''ADPS0 (ADC Prescaler Select Bit 0)'''<br/>Siehe '''ADPS2''' für eine Beschreibung.
 
*'''ADPS0 (ADC Prescaler Select Bit 0)'''<br/>Siehe '''ADPS2''' für eine Beschreibung.
 
  
 
=== ADMUX ===
 
=== ADMUX ===

Version vom 26. Dezember 2008, 13:18 Uhr

Für allgemeine Informationen zum Analog-Digital-Wandler siehe Artikel ADC.

Mit einem Analog-Digital-Wandler (ADC, für Analog Digital Converter) ist es mit den AVRs möglich, auf einfache Art und Weise analoge Größen in digitale Werte umzuwandeln. Dies bietet sich z.B. an, wenn man die Batteriespannung eines Roboters bestimmen möchte.

Kanäle

Ein AVR hat normalerweise nur einen ADC integriert. Öfters muss man aber mehrere analoge Größen von verschiedenen Quellen wandeln, deswegen besitzen die AVRs Kanäle (ein ATmega32 z.B. besitzt acht Kanäle auf Port A). Diese Kanäle werden dann mithilfe eines Multiplexer auf den ADC geschaltet, der dann die anliegende analoge Spannung in einen digitalten Wert wandelt.

Betriebsmodi

Der ADC bietet verschiedene Betriebsmodi. Diese wären:

  • Single Conversion: Der ADC wandelt eine analoge Größe um und gibt diese zurück.
  • Free Running: Der ADC wandelt wie in einer Endlosschleife ständig die anliegende analoge Größe in digitale Werte um und gibt diese zurück.
  • Autotrigger: Bei neueren AVRs (z.B. Mega48,Mega88,Mega32,..) kann der ADC auch direkt vom Timer oder getriggert über den analogen Komperator gestartett werden.

Teilungsfaktor

Zum Wandeln benötigt der ADC einen eigenen Takt, der auf der Taktfrequenz des Mikrocontrollers basiert. Eine Wandlung braucht normalerweise 13 Zyklen des ADC-Taktes. Allerdings ist die Taktfrequenz des Mikrocontrollers zu schnell und deswegen wird diese durch den Vorteiler verkleinert. Der resultierende Takt sollte beim AVR zwischen 50kHz und 200kHz liegen. Mit reduzierter Genauigkeit ist bis 1000 kHz möglich. Folgende Teilungsfaktoren sind verfügbar:

Teilungsfaktoren  2  4  8 16 32 64 128

Um zu bestimmen welcher Teilungsfaktor geeignet ist, kann man folgende Formel verwenden.
[math]Taktfrequenz = 8 MHz[/math]

[math]Teilungsfaktor_{min} = {Taktfrequenz \over {200 kHz}} = {{8000000 Hz} \over {200000 Hz}} = 40[/math]

[math]Teilungsfaktor_{max} = {Taktfrequenz \over {50 kHz}} = {{8000000 Hz} \over {50000 Hz}} = 160[/math]

Deswegen kann man nun zwischen einem der folgenden Teilungsfaktor wählen: 64 und 128. Im Interesse der Geschwindigkeit sollte 64 gewählt werden.

Siehe bitte die Registerübersicht weiter unten. Dort wird gezeigt, welches Register entsprechend eingestellt werden muss, damit man einen der oben aufgelisteten Teilungsfaktoren auswählen kann.

Referenzspannung

Das Ergebnis der Wandlung des ADC bezieht sich auf eine bestimmte Referenzspannung. Die Referenzspannung ist also gleich der maximal zu messenden Spannung. Wenn die Spannung höher ist (kleiner als Vcc+0.3V, um den Port nicht zu beschädigen) gibt der AD Wandler das maximale Ergebnis. Um einzustellen welche Referenzspannung verwendet werden soll, gibt es das Register ADMUX. Je nach verwendetem AVR sind verschiedene Möglichkeiten als Referenzspannung vorhanden:

Referenz- spannungsquelle Bedeutung
AREF es wird die externe Spannung als Referenz verwendet die an Pin AREF anliegt
AVCC besitzt der AVR eine eigene Spannungsversorgung für den ADC
wird der Pin AVCC als Referenz gewählt,
ansonsten wird Vcc verwendet,
mit externen Kondensator am AREF Pin
Intern Spannung 1,1V und/oder 2,56V, je nach AVR einer der beiden Spannungen, oder beide zur Auswahl, wie zB. beim ATmega644, mit oder ohne (zB. beim Tiny15L) externem Kondensator am AREF Pin

Verwendet man Bascom als Programmiersprache, gibt es, je nach verwendetem AVR, folgende Möglichkeiten zur Angabe als Referenz :

Config Adc = Single , Prescaler = Auto , Reference = 
 OFF             ' AREF 
 AVCC            ' AVCC oder VCC 
 INTERNAL        ' Wenn nur eine interne Spannung möglich ist 
 INTERNAL_1.1    ' Wenn mehr interne Spannungen auswählbar sind 
 INTERNAL_2.56   ' Wenn mehr interne Spannungen auswählbar sind 
 INTERNALEXTCAP  ' Wenn, zB. beim Tiny15L, ein Kondensator an AREF angeschlossen ist 

Siehe bitte die Registerübersicht. Dort steht genauer wie man das Register einzustellen hat.

Man benötigt die Referenzspannung auch (oder besser deren analoge Größe) um den Wert den der ADC zurückgibt in V umzurechnen. Um den zurückgegebenen Wert des ADC umzuwandel geht man so vor:

  1. Bestimmen der Auflösung des ADC. Bei den ATMegas normalerweise 10 Bit. 10 Bit entsprechen einer Stufung von 1024.
  2. Ermitteln des digitalen Wertes der analogen Größe. In der Beispielrechnung verwende ich den Wert 592.
  3. Größe der Referenzspannung. In der Beispielrechnung wird 5V verwendet.

Mit diesen Werten kann folgende Berechnung ausführen.

[math]V = 592 * 5V[/math]

[math]V = 2960 / 2 ^{Bit} = 2960 / 2 ^{10} = \underline {\underline { 2{,}9V }}[/math]

Programmbeispiele

C/C++

Dieses Beispiel ist für die Atmel Controller Mega16 und Mega32 gedacht, die mit einer Taktfrequenz von 8 MHz laufen. Je nach Einsatzart muss man das Beispielprogramm entsprechend abändern (also diese Zeile mit ADMUX |= (1<<REFS1) | (1<<REFS0);).

#include <avr/io.h>
#include <inttypes.h>

uint16_t readADC(uint8_t channel) {
	uint8_t i;
	uint16_t result = 0;
	
	// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
	ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

	// Kanal des Multiplexers waehlen
	ADMUX = channel;
	// Interne Referenzspannung verwenden (also 2,56 V)
	ADMUX |= (1<<REFS1) | (1<<REFS0);
	
	// Den ADC initialisieren und einen sog. Dummyreadout machen
	ADCSRA |= (1<<ADSC);
	while(ADCSRA & (1<<ADSC));
	
	// Jetzt 3x die analoge Spannung and Kanal channel auslesen
	// und dann Durchschnittswert ausrechnen.
	for(i=0; i<3; i++) {
		// Eine Wandlung
		ADCSRA |= (1<<ADSC);
		// Auf Ergebnis warten...
		while(ADCSRA & (1<<ADSC));
		
		result += ADCW;
	}
	
	// ADC wieder deaktivieren
	ADCSRA &= ~(1<<ADEN);
	
	result /= 3;
	
	return result;
}

int main(void) {
	uint16_t result = readADC(0);	//Auslesen der analogen Spannungen an Pin 0,
					// also ADC0. In result steht das Ergebnis.
	return 0;
}

Bascom

Dieses Programmbeispiel ist für den Atmel Controller Mega32 gedacht. Es gibt nacheinander die Spannungen der einzelnen Kanäle (ADC0..7) aus. Dazwischen macht es immer 800 ms pause.

' Die gemessene Spannung wird in der Variablen W gespeichert.
' Channel ist der Pin, an dem die Spannung gemessen werden soll.

$baud = 9600
$crystal = 1000000
$regfile "m32def.dat"
Config Adc = Single , Prescaler = Auto
Start Adc
Dim W As Word , Channel As Byte
Channel = 0
Do
  W = Getadc(channel)
  Print "ADC-Pin " ; Channel ; ": Wert " ; W
  Incr Channel
  If Channel > 7 Then Channel = 0
  Waitms 800
Loop
End

Registerübersicht

Hinweis: Diese Registertabellen wurden für den aktuellen Atmel Controller Mega16 und Mega32 erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.


ADCSRA

ADC Control and Status Register A

Dieser Register dient dazu den ADC zu kontrollieren.

Bit: 7 6 5 4 3 2 1 0
Name: ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
  • ADEN (ADC Enable)
    Wird dieses Bit gesetzt (also 1), dann wird der ADC aktiviert. Schreibt man eine 0 wird der ADC deaktiert. Wird der ADC während einer Wandlung deaktiviert, wird die Wandlung abgebrochen.
  • ADSC (ADC Start Conversion)
    Dieses Bit startet den Messvorgang, je nachdem in welchem Betriebsmodi der ADC läuft. Wird dieses Bit nach der Aktivierung des ADC über ADEN zum ersten Mal gesetzt, wird der ADC erst eine Initialisierungswandlung durchführen und danach erst die eigentliche Wandlung. Das Schreiben einer 0 auf das Bit hat keinen Effekt.
  • ADATE (ADC Auto Trigger Enable)
    Wird dieses Bit gesetzt, wird das Auto Triggering des ADC aktiviert. Die genaue Triggerquelle wir im Register SFIOR eingestellt. Default ist das der Free-runnng mode.
  • ADIF (ADC Interrupt Flag)
    Dieses Bit wird auf 1 gesetzt, wenn eine Wandlung erfolgte und das Ergebnis nun verfügbar ist. Der ADC Complete Interrupt wird ausgelöst, wenn das ADIE-Bit gesetzt ist und die Interrupts global aktiviert sind. Das Bit wird gelöscht, wenn die entsprechende ISR abgearbeitet wird. Alternativ kann man es löschen, indem man eine 1 auf das Bit schreibt.
  • ADIE (ADC Interrupt Enable)
    Wird dieses Bit gesetzt und die globalen Interrupts sind aktiviert, wird der ADC Complete Interrupt aktiviert, auf den man dann in der entsprechenden ISR reagieren kann.
  • ADPS2 (ADC Prescaler Select Bit 2)
    Diese Bits bestimmen den Teilungsfaktor zwischen der CPU-Frequenz und dem Eingangstakt des ADC. Zum Wandeln benötigt der ADC einen eigenen Takt, der auf der Taktfrequenz des Mikrocontrollers basiert. Allerdings ist die Taktfrequenz zu schnell und deswegen wird diese durch den Vorteiler verkleinert. Der resultierende Takt sollte zwischen 50kHz und 200kHz liegen. Siehe Teilungsfaktor. Folgende Teilungsfaktoren sind verfügbar:
ADPS2 ADPS1 ADPS0 Teilungsfaktor
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128
  • ADPS1 (ADC Prescaler Select Bit 1)
    Siehe ADPS2 für eine Beschreibung.
  • ADPS0 (ADC Prescaler Select Bit 0)
    Siehe ADPS2 für eine Beschreibung.

ADMUX

ADC Multiplexer Selection Register

Mit diesem Register wird u.a. der Multiplexer gesteuert.

Bit: 7 6 5 4 3 2 1 0
Name: REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
  • REFS1 (Reference Selection Bit 1)

Mit diesem Bit kann steuern, welche Referenzspannung der ADC verwenden soll. Die möglichen Quellen sind unten aufgelistet. Wird während einer Wandlung die Quelle für die Referenzspannung geändert, wird die aktuelle Wandlung mit der "alten" Quellen zuerste beendet, bevor die neue Einstellung übernommen wird.

REFS1 REFS0 Referenzspannungsquelle
0 0 AREF, internes Vref deaktiviert
0 1 AVCC mit externen Kondensator am AREF Pin
1 0 Keine Funktion, reserviert
1 1 Interne 2,56V Spannungsreferenz mit externen Kondensator am AREF Pin
  • REFS0 (ADC Start Conversion)
    Siehe REFS1.
  • ADLAR (ADC Left Adjust Result)
    Dieses Bit beeinflusst, wie der ermittelte Messwert im ADC Data Register abgelegt wird.
  • MUX4 (Analog Channel and Gain Selection Bit 4)
    Dieses Bit wird auf 1 gesetzt, wenn eine Wandlung erfolgte und das Ergebnis nun verfügbar ist. Der ADC Complete Interrupt wird ausgelöst, wenn das ADIE-Bit gesetzt ist und die Interrupts global aktiviert sind. Das Bit wird gelöscht, wenn die entsprechende ISR abgearbeitet wird. Alternativ kann man es löschen, indem man eine 1 auf das Bit schreibt.
  • MUX3 (Analog Channel and Gain Selection Bit 3)
    Mit diesen Bits (MUX3 bis MUX0) wird der Kanal des Multiplexers eingestellt, der mit dem ADC verbunden ist.
MUX4..0 Pin
00000 ADC0
00001 ADC1
00010 ADC2
00011 ADC3
00100 ADC4
00101 ADC5
00110 ADC6
00111 ADC7

Es reicht also einfach die Pinnummer in ADMUX zu schreiben.

  • MUX2 (Analog Channel and Gain Selection Bit 2)
    Siehe MUX3 für eine Beschreibung.
  • MUX1 (Analog Channel and Gain Selection Bit 1)
    Siehe MUX3 für eine Beschreibung.
  • MUX0 (Analog Channel and Gain Selection Bit 0)
    Siehe MUX3 für eine Beschreibung.

ADCL / ADCH

Desweiteren gibt es noch die Register ADCL/ADCH hier steht das Ergebnis einer Wandlung. Wie bei den meisten auf 2 Register verteilten Werten, bewirkt das lesen des Low-Bytes ein puffern des High-bytes. Man liest den Wert folgendermaßen aus:


uint16_t x = ADCL;
x += (ADCH<<8);
// oder besser
x = ADCW;

Siehe auch


Weblinks