mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 10-bit vom A/D-Wandler nutzen


Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe bisher beim Atmega88 den A/D-Wandler mit einer Aufösung von 
8-bit verwendet und habe somit Werte zwischen 0 und 255 bekommen.

Wenn ich jetzt die 10-bit Auflösung benutze, müsste ich doch Werte 
zwischen 0 und 1024 bekommen. Schreibe ich mir den erzeugten 10-bit Wert 
vom AD-Wandler nun in eine Integer Variable, bekomme ich aber Werte bis 
65535.

Warum ist das so? Stehen die 10-bit vom A/D-Wandler dann an den 
höchstwerigsten Stellen der 16-bit Variablen und die anderen werden mit 
Nullen aufgefüllt?

Wie kann ich nur die 10-bit benutzen, also Werte zwischen 0 und 1024 
bekommen?


Gruß  Björn

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>zwischen 0 und 1024 bekommen
Nö, nur zwischen 0 und 1023

>Warum ist das so? Stehen die 10-bit vom A/D-Wandler dann an den
>höchstwerigsten Stellen der 16-bit Variablen und die anderen werden mit
>Nullen aufgefüllt?

Hast du vielleicht noch ADLAR gesetzt? Sollte man dann nicht tun...

>Wie kann ich nur die 10-bit benutzen, also Werte zwischen 0 und 1024
>bekommen?
Gar nicht (siehe oben).
Du kannst Werte zwischen 0 und 1023 bekommen, wenn du das ADLAR-Bit 
nicht setzt.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt ein Steuerbit mit dem Namen ADLAR (ADC Left Adjust Result). Wenn 
dieses Bit gesetzt ist, wird das Ergebnis der Wandlung "links" 
ausgerichtet (was v.a. dann Sinn macht, wenn man nur 8 Bit Auflösung 
braucht, man muss dann nämlich nur das High-Byte auslesen), andernfalls 
rechts. Wenn Du höhere Werte als 1023 bekommst, ist dieses Bit 
vermutlich gesetzt. Lösche es und Du wirst zufrieden sein...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und welches Byte muss ich dann auslesen? High- oder Low-Byte?

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Johnny: und wieder zu langsam! ;-)

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Und welches Byte muss ich dann auslesen? High- oder Low-Byte?
Grundlagen: Ein Byte kann keine 10bit breiten Informationen einhalten 
(geht einfach nicht, oder hat schon jemand eine Byte-Kompression 
erfunden?)
Du musst ein unsigned integer Variable (uint_16?) benutzen:

unsigned int wert;

.
.
.
.

wert = ADC;
.
.
.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und welches Byte muss ich dann auslesen? High- oder Low-Byte?
Beide natürlich. Aber der Oskar ist eh wieder schneller...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wusste ich doch...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bekomme jetzt aber wieder nur Werte zwischen 0 und 255.

Auslesen so:

AD_Wert = ADCL;

AD_Wert = AD_Wert + ADCH;

Oder mach ich das falsch? Im Datenblatt steht, zuerst das Low_Byte und 
dann das High.

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>AD_Wert = AD_Wert + ADCH;

Wenn du im Datenblatt weiter unten guckst, steht da auch, wie man beide 
Bytes "gleichzeitig" ausliest.
Das habe ich oben zwar schon geschrieben, scheint dich aber nicht zu 
interessieren...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das habe ich oben zwar schon geschrieben, scheint dich aber nicht zu
 >interessieren...

Doch, hab ich gesehen und auch ausprobiert: Klappt aber nicht. Im meiner 
Variablen steht ein Wert von 61568.

unsigned int AD_Wert;

void ADC_wandlung()    //PORTC, Bit2
{
  ADMUX &= ~((1<<MUX0)|(1<<MUX2)|(1<<MUX3));  //ADC2 eingestellt
  ADMUX |= (1<<MUX1);
  ADCSRA = (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
  ADMUX |= (1<<REFS0);

  ADCSRA |= (1<<ADSC);    //Eine AD-Wandlung zur Initialisierung
  while (ADCSRA & (1<<ADSC))
  {
   ;
  }

  ADCSRA |= (1<<ADSC);    //AD Wandlung
  while (ADCSRA & (1<<ADSC))
  {
  ;
  }

  ADCSRA &= ~(1<<ADSC);    //AD Wandlung deaktivieren

  AD_Wert; = ADC;
}

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  AD_Wert; = ADC;

Das ist ein Semikolon zu viel.

>  ADCSRA |= (1<<ADSC);    //Eine AD-Wandlung zur Initialisierung
>  while (ADCSRA & (1<<ADSC))
>  {
>   ;
>  }
>
>  ADCSRA |= (1<<ADSC);    //AD Wandlung
>  while (ADCSRA & (1<<ADSC))
>  {
>  ;
>  }
>
>  ADCSRA &= ~(1<<ADSC);    //AD Wandlung deaktivieren

Du machst 2 Messungen nacheinander, ohne das erste Ergebnis auszulesen. 
Warum?
Und die Wandlung brauchst du nicht deaktivieren.
Guck dir am besten mal das gcc-Tutorium zu dem Thema an.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du machst 2 Messungen nacheinander, ohne das erste Ergebnis auszulesen.
> Warum?

Weil laut Datenblatt ein paar µs von der Initialisierung bis zur ersten 
Wandlung vergehen müssen.

Das GCC-Tutorial hab ich mir schon angeschaut. Egal wie ich es mache:

AD_Wert = ADCL;
AD_Wert += (ADCH << 8);

oder so

AD_Wert = ADCW;

oder so

AD_Wert = ADC;


ich krieg immer Werte bis 6500 raus.....

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um welchen Controller handelt es sich?
Kannst du dein komplettes Programm bitte posten?!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ADCSRA &= ~(1<<ADSC);    //AD Wandlung deaktivieren
Den ADC schaltet man durch löschen des ADEN-Bits aus. Das ADSC wird 
automatisch nach dem Ende der Wandlung gelöscht. Du fragst es ja auch 
schließlich daraufhin ab.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rahul-Oskar:
ATMega88 (siehe gaaaaanz oben) ;-)

Aber das mit dem kompletten Programm wäre echt ne feine Sache... Hab 
keine Lust zum  Hellsehen heute...

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>(siehe gaaaaanz oben) ;-)

Zwischen den beiden Threads steht soviel Zeug - da überliest man das 
gerne mal...
Das wäre auch noch was gutes fürs Forum: ein kleiner Kasten am Rand, in 
dem noch mal eine Art Zusammenfassung (z.B. Controller, Problem, 
Entwicklungsumgebung etc) steht...

Autor: fieser Rahul (auch Oskar genannt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>(siehe gaaaaanz oben) ;-)

>Zwischen den beiden Threads steht soviel Zeug - da überliest man das
>gerne mal...

Aber totzdem "Danke"!

Wieso übernimmt man eigentlich nie irgendwelche Beispiele direkt?
(Bin gestern mal wieder über das UBSEL-Bit gefallen...[Nein, ich hab mir 
nicht das Bein am Bit, sondern den Kopf - gewollt - am Tisch danach 
gestossen...])

Bei mir gibt es immer eine ADC-Init-Routine und eine ADC-lese-Routine.

void init_ADC(void)
{
   ADMUX = (1<<REFS0); // REF = AVCC
   ADCSRA = (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2); // ADC 
freigeben, Prescaler = 128 (Wandelfrequenz = ...)
}

unsigned int read_adc(unsinged char kanal)
{
  ADMUX |= (kanal & 0x0F);
  ADCSR |= (1<<ADSC);
  while(ADCSR & (1<<ADSC));
  return ADC;
}

Ausm Kopf...(kann also noch Fehler enthalten; Gewähr wird nicht 
gegeben.)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.