Forum: Compiler & IDEs ADC geht nicht ?


von Sascha Biedermann (Gast)


Lesenswert?

Hallo Leute!

Ich versuche den ADC meines Mega32 zum laufen zu bringen. Dazu habe ich
folgenden Code geschrieben:

while (1)
{
// links ausrichten & Aktivieren
sbi(ADMUX,ADLAR);
sbi(ADCSRA,ADEN);

unsigned char res;

cbi(ADMUX,MUX0);
sbi(ADMUX,MUX1);
sbi(ADMUX,MUX2);
sbi(ADMUX,MUX3);
sbi(ADMUX,MUX4);

// Los geht's
sbi(ADCSRA,ADSC);
loop_until_bit_is_clear(ADCSRA,ADSC);
res = ADCH;
lcd_gotoxy(0,3);
sprintf(str,"%u",res);
lcd_puts(str);
}

Bei dem ausgewählten Channel (Im Datenblatt steht 1,22V) müßte ja alles
andere außer 255 raus kommen. Auch wenn ich einen ADC-Pin auswähle, das
Ergebniss bleibt immer 255. Ist mein ADC kaputt, oder liegt's am Code
?

AREF und AVCC sind mit VCC (5V) und AGND mit GND verbunden.

MfG
Sascha

von Jörg Wunsch (Gast)


Lesenswert?

Hmm:

cbi(ADMUX,MUX0);


sbi(ADMUX,MUX1);


sbi(ADMUX,MUX2);


sbi(ADMUX,MUX3);


sbi(ADMUX,MUX4);



Ein typisches Beispiel, warum cbi/sbi wirklich `deprecated' sein
sollten...

ADMUX = _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);

wäre deutlich effektiver.  Aber das nur nebenbei.

Dein ADSRA hat alle Teilerbits auf 0, d. h. einen Vorteiler von 2.
Sofern Dein Systemtakt nicht gerade im Bereich 100...400 kHz liegt,
bist Du damit außerhalb der Specs.

Normalerweise sollte der ADC allerdings auch mit höherem Takt noch
laufen, nur nicht mehr so genau.  Wenn Dein Systemtakt allerdings bei
14...16 MHz liegt, kann es gut sein, daß der ADC mit der Hälfte davon
auch schon ganz außer Funktion ist.

von Sascha Biedermann (Gast)


Lesenswert?

ah!

die sbi's sind nach und nach dazu gekommen, beim debuggen g

naja ich habe ihn auf 16MHz laufen g gut, habe den prescaler auf 128
gestellt, jetzt geht's...

Hab' vielen Dank!

...soviel zum Thema: Wenn ich das Datenblatt mal schnell überfliege,
dann bekomme ich schon raus wie das geht g

von Martial (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

ich habe das selbe Problem. Der prescale wurde auch verändert, doch es
funktioniert immer noch nicht. Mein Code ist im File A_D angehängt.

Die Ausgabe an die LED ist immer 0xFF.

Gruss Martial

von Lutz Müller (Gast)


Lesenswert?

Hallo,

bin zwar auch leider erst noch ganz am Anfang, aber folgendes glaube
ich als Fehler zu erkennen (ohne mir den Rest angeschaut zu haben:)

void AD_in (unsigned char mux)
{
  ADMUX = (0<<REFS1)|(0<<REFS0)|(0<<ADLAR)|(mux<<MUX0);
  ADCSRA =
(1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);

  while ((ADCSRA & 0x10));

  return ADCW;
}

Eine void-Funktion (ohne Rückgabe) liefert "return ADCW"? => Dann
keine void-Funktion.

Gruß

Lutz

von Lutz Müller (Gast)


Lesenswert?

Hallo,

mit dem Nullen-schieben ist übrigens auch quatsch bzw. bringt
wahrscheinlich nicht das, was Du vorhast. Die Idee hatte ich ganz am
Anfang auch, ist ja auch so schön einfach: Bitshift mit 1 = Bit setzen,
Bitshift mit 0 = Bit löschen. Schade, geht aber nicht. Wurde mir zigmal
erklärt, hab´s trotzdem nicht verstanden warum´s nicht geht. Einer
hat´s dann geschafft mir zu erklären: Mach doch einfach mal die Shifts
und Verknüpfungen zu Fuß (mit dem Prinzip fahre ich jetzt allgemein
sehr gut):
x = (1<<2) | (0<<3) mit 4 Bit entspricht
x = 0100 ODER     ("1" = 0001 zwei Stellen Bitshift nach links)
    0000          ("0" = 0000 drei Stellen Bitshift nach links)
--------------
  = 0100
Also keine Änderung; eine ODER-Verknüpfung nur mit Nullen kann man sich
sparen => einfach weglassen. Da es eine Zuweisung ist (x = ..) wird das
Ergebnis der ODER-Verknüpfung x zugewiesen; der Wert von x vor der
Zuweisung ist dabei egal.

Wenn Du aber beabsichtigt hattest, ein ungesetztes Bit zu setzen (also
nur  ein spezielles Bit im Register, alle anderen Bits sollen bleiben
wie sie waren), wäre
x = x | (1<<3) richtig. Kürzer wäre x |= (1<<3). Mit dem Wert von Oben

x = 0100 ODER
    1000           ("1" = 0001 drei Stellen Bitshift nach links)
----------------
  = 1100
die richtige Lösung.

Um nun ein einzelnes Bit zu setzen, muß eine UND-Verknüpfung her.
Um das Dritte Bit von rechts zu löschen, wäre
x = x & ~(1<<3) richtig. Kürzer wäre x &= ~(1<<3). Die Tilde heißt
negieren. Ergibt mit dem letzten Ergebnis
x = 1100 UND
    1011            (Negiertes 0100)
----------------
  = 1000.

So hab´ zumindest ich das verstanden. Es gibt natürlich ein Makro dafür
im GCC, weil diese Shiften eben oft gebraucht wird. Nennt sich _BV().
Näheres in den FAQ der avr-libc. Zumindest ich brauche aber dieses
"Step by Step für Dumme" weiter oben, um die Dinge zu verstehen. Dann
weiß ich wenigstens, was das Makro macht.

Gruß
Lutz

P.S.: Da dieses Problem hier nicht viel mit dem Ursprungs-thread zu tun
hat, lieber einen neuen aufmachen bei ähnlichen Fragen. Ist dann
übersichtlicher.

von Lutz Müller (Gast)


Lesenswert?

Oh Sch.., 2 mal vergrüßt. Hier ist richtiger:

Hallo,

mit dem Nullen-schieben ist übrigens auch quatsch bzw. bringt
wahrscheinlich nicht das, was Du vorhast. Die Idee hatte ich ganz am
Anfang auch, ist ja auch so schön einfach: Bitshift mit 1 = Bit
setzen,
Bitshift mit 0 = Bit löschen. Schade, geht aber nicht. Wurde mir
zigmal
erklärt, hab´s trotzdem nicht verstanden warum´s nicht geht. Einer
hat´s dann geschafft mir zu erklären: Mach doch einfach mal die Shifts
und Verknüpfungen zu Fuß (mit dem Prinzip fahre ich jetzt allgemein
sehr gut):
x = (1<<2) | (0<<3) mit 4 Bit entspricht
x = 0100 ODER     ("1" = 0001 zwei Stellen Bitshift nach links)
    0000          ("0" = 0000 drei Stellen Bitshift nach links)
--------------
  = 0100
Also keine Änderung; eine ODER-Verknüpfung nur mit Nullen kann man
sich
sparen => einfach weglassen. Da es eine Zuweisung ist (x = ..) wird
das
Ergebnis der ODER-Verknüpfung x zugewiesen; der Wert von x vor der
Zuweisung ist dabei egal.

Wenn Du aber beabsichtigt hattest, ein ungesetztes Bit zu setzen (also
nur  ein spezielles Bit im Register, alle anderen Bits sollen bleiben
wie sie waren), wäre
x = x | (1<<3) richtig. Kürzer wäre x |= (1<<3). Mit dem Wert von Oben

x = 0100 ODER
    1000           ("1" = 0001 drei Stellen Bitshift nach links)
----------------
  = 1100
die richtige Lösung.

Um nun ein einzelnes Bit zu LÖSCHEN, muß eine UND-Verknüpfung her.
Um das Dritte Bit von rechts zu löschen, wäre
x = x & ~(1<<2) richtig. Kürzer wäre x &= ~(1<<2). Die Tilde heißt
negieren. Ergibt mit dem letzten Ergebnis
x = 1100 UND
    1011            (Negiertes 0100 aus: 1<<2 = 0100)
----------------
  = 1000.

So hab´ zumindest ich das verstanden. Es gibt natürlich ein Makro
dafür
im GCC, weil diese Shiften eben oft gebraucht wird. Nennt sich _BV().
Näheres in den FAQ der avr-libc. Zumindest ich brauche aber dieses
"Step by Step für Dumme" weiter oben, um die Dinge zu verstehen.
Dann
weiß ich wenigstens, was das Makro macht.

Gruß
Lutz

P.S.: Da dieses Problem hier nicht viel mit dem Ursprungs-thread zu
tun
hat, lieber einen neuen aufmachen bei ähnlichen Fragen. Ist dann
übersichtlicher.

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.