Forum: Mikrocontroller und Digitale Elektronik ADC auslesen


von Markus S. (knutschkuh)


Lesenswert?

Hallo zusammen,

ich habe mir die ADC Ansteuerung im Wiki angeschaut und dies auch so 
Programmiert.
Nun msus ich ja nach dem Starten einer Messung warten bis diese 
durchgeführt wurde.
1
 ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
2
  while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
3
  }
4
  return ADCW;                    // ADC auslesen und zurückgeben

Jedoch bleibt er dann bei mir immer im Programm hängen. Ändere ich es ab 
in
1
 ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
2
  while (!(ADCSRA & (1<<ADSC) )) {   // auf Abschluss der Konvertierung warten
3
  }
4
  return ADCW;                    // ADC auslesen und zurückgeben
funktioniert es wunderbar. Ist hier ein Fehler meinerseits oder ein 
Fehler im Wiki?? Ich steh da gerade im Wald...

Gruß Markus

von Thomas E. (thomase)


Lesenswert?

Markus S. schrieb:
> Ich steh da gerade im Wald...
Genauso wie dein ADC. Der läuft gar nicht.
Wie wird der denn initialisiert?

mfg.

von Cyblord -. (cyblord)


Lesenswert?

Welcher Controller? Bei mir sind die beiden ADC Result Bytes im Makro 
"ADC" zu finden und nicht "ADCW".

von Thomas E. (thomase)


Lesenswert?

cyblord ---- schrieb:
> "ADC" zu finden und nicht "ADCW".
Doch. Das passt schon, das ist beides definiert.

mfg.

von Markus S. (knutschkuh)


Lesenswert?

Also mein Programm sieht so aus:
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/version.h>
4
5
6
int main(void)
7
{
8
  DDRB = 0xff;                    //Definiere Port B als Ausgang
9
  DDRA = 0x00;                    //Definiere Port A als Eingang
10
  PORTB = 0xff;                    //Setze Port B auf 0xff (Alle Ausgänge High = LED´s aus)
11
  uint8_t ad_channel=0,ad_wert=0,ad_ausgabe=0;    //Variablen definieren
12
  ADMUX = (1<<ADLAR);                  //Ausgabe des ADC-Wertes Linksbündig!!
13
  ADCSRA = (1<<ADPS2);                //Teilungsfaktor 32
14
  ADCSRA |= (1<<ADEN);                //ADC Aktivieren
15
  ADCSRA |= (ADMUX & ~(0x1f)) | (ad_channel & 0x1f);  //Setze ADC Kanal (Auswahl durch die Variable "ad_channel")
16
  
17
  ADCSRA |= (1<<ADSC);                //Eine Messung starten
18
  while (!(ADCSRA & (1<<ADSC)))            //Endlosschleife bis ADC Messung fertig
19
    {
20
    }
21
  uint8_t temp = ADCH;                //Lesen des ADC Wertes und verwerfen desselben.
22
  
23
    while(1)
24
    {
25
    ADCSRA |= (ADMUX & ~(0x1f)) | (ad_channel & 0x1f);  //Kanalauswahl
26
    ADCSRA|=(1<<ADSC);                //Messung starten
27
    while(!(ADCSRA & (1<<ADSC))){}          //Endlosschleife bis ADC Messung fertig
28
  //  uint8_t temp3 = ADCL;              //Schreiben der niedristen Bits in Temporäre Variable (Wird verworfen)
29
    ad_wert = ADCH;                  //Schreiben der höchsten 8 Bits in die Variable "ad_wert" zur weiterverarbeitung
30
    
31
    //Hier wird geprüft wie Hoch der ADC Wert ist und dazu passend die Ausgabe für Port B vorbereitet.
32
    if(0 <= ad_wert && ad_wert < 2){ad_ausgabe=0;}
33
    if(2 <= ad_wert && ad_wert < 40){ad_ausgabe=1;}
34
    if(40 <= ad_wert && ad_wert < 70){ad_ausgabe=3;}
35
    if(70 <= ad_wert && ad_wert < 100){ad_ausgabe=7;}
36
    if(100 <= ad_wert && ad_wert < 130){ad_ausgabe=15;}
37
    if(118 <= ad_wert && ad_wert < 160){ad_ausgabe=31;}
38
    if(160 <= ad_wert && ad_wert < 193){ad_ausgabe=63;}
39
    if(193 <= ad_wert && ad_wert < 223){ad_ausgabe=127;}
40
    if(223 <= ad_wert && ad_wert <= 255){ad_ausgabe=255;}
41
    PORTB = ad_ausgabe;              //Hier erfolgt die negierte (da active LOW) ausgabe für die Balkenanzeige.
42
        }
43
}

Ich lese nur ADCH in meinem Programm aus da ich Linksbündig ausgebe auf 
8 bit.  Ich nutze einen ATmega16, laut Datenblatt reicht es ADCH 
auszulesen wenn ich nur 8 bit nutze. Oder ist hier mein Denkfehler?

von Cyblord -. (cyblord)


Lesenswert?

Thomas Eckmann schrieb:
> cyblord ---- schrieb:
>> "ADC" zu finden und nicht "ADCW".
> Doch. Das passt schon, das ist beides definiert.
>
> mfg.

Ahso sieh an. Man lernt nie aus. Danke.

von Thomas E. (thomase)


Lesenswert?

Markus S. schrieb:
> ADCSRA |= (ADMUX & ~(0x1f)) | (ad_channel & 0x1f);
Welchen Sinn hat das, daß du das ADCSRA-Register mit ADMUX verknüpfst?
Damit sorgst du zufällig dafür, daß du den ADC auf Free Running stellst 
und er ständig wandelt und das ADSC-Bit immer gesetzt ist.
Wo ist deine Referenzspannung?

mfg.

von Markus S. (knutschkuh)


Lesenswert?

Ähm ok da soll natürlich ADMUX stehen. Referenzspannung ist AREF daher 
sind die Bits dafür 0.
Danke!!

von Thomas E. (thomase)


Lesenswert?

Markus S. schrieb:
> Ähm ok da soll natürlich ADMUX stehen.
Dann sollte das auch laufen.

> ADCSRA |= (ADMUX & ~(0x1f)) | (ad_channel & 0x1f);
Und schreib das nicht so kompliziert. Da muß man ja mindestens dreimal 
hingucken, bis man sieht, was das soll.
ADMUX &= ~0x1F;
ADMUX |= ad_channel;
Nur weil es jetzt 2 Zeilen sind, wird das im Code nicht länger. Der 
Compiler kriegt das schon richtig hin.

mfg.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.