Forum: Mikrocontroller und Digitale Elektronik AD-Wandler, Mega48 und STK500


von Sven (Gast)


Lesenswert?

Hallo,

ich würd gern beim Atmega48 auf dem STK500 den AD-Wandler auf die 5V
Betriebsspannung einstellen. Im Moment läuft er mit der "Internal 1.1
Voltage Reference".

Eigentlich müsste ich doch nur im ADMUX-Register die entsprechenden
Ports setzen. Nur irgendwie klappt das nicht. Kann mir einer da wohl
helfen.

Welche Bits muss ich genau setzen?

von johnny.m (Gast)


Lesenswert?

Zum Einstellen der Referenzspannung müssen die Bits REFS1 und REFS0
entsprechend gesetzt werden. Für AVCC als Referenz muss REFS1 0 und
REFS0 1 sein.

von Sven (Gast)


Lesenswert?

Hmm,

klappt irgendwie nicht. Die Spannung am ADC0 variiert zwischen 0,2 -
4,7 V. Es werden aber nur Werte zwischen 240 und 250 vom AD-Wandler
ausgegeben.

von johnny.m (Gast)


Lesenswert?

Wenn Du mal so freundlich sein könntest, den Code zu posten, mit dem Du
diese Ergebnisse erzielst, dann kann man Dir vielleicht auch
weiterhelfen. Wenn der ADC0 im ADMUX ausgewählt ist (MUX3..0 = 0000b)
und die Referenzspannung korrekt eingestellt ist (REFS1..0 = 01b) und
an dem Eingangspin alles in Ordnung ist (als Eingang ohne Pull-Up
programmiert), dann sollte es eigentlich funktionieren.

von Sven (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist mal der Code.

Dabei hab ich noch ein Problem. Will bei einem bestimmten Wert vom
AD-Wandler die LED PB2 einschalten. Leider klappt das auch nicht.

Vielleicht kann mal einer schauen woran das liegt.....

Danke!

von johnny.m (Gast)


Lesenswert?

Hast Du mal überlegt, wie wahrscheinlich es ist, dass der ADC-Wert exakt
einen bestimmten Wert annimmt? Dass das mit der LED nicht klappt, ist
also wenig verwunderlich. Bei 5V Referenzspannung ist die Auflösung
<5mV. So präzise kann man die Spannung i.d.R. nicht einstellen.

von Sven (Gast)


Lesenswert?

Gut, hast schon Recht.

Exakt war auch eigentlich nicht geplant. Hatte so an +/- 5 Werte
gedacht. Hatte mir vorher den Wert des AD-Wandlers über die serielle
Schnittstelle an den PC geschickt und dort den Wert auf einem Terminal
dargestellt. Mit diesem Wert wollte ich dann die LED einschalten.

Werd es aber geich mal mit einer größeren Wertespanne versuchen.

von johnny.m (Gast)


Lesenswert?

Ein paar Dinge, die mir auf den ersten Blick auffallen:

1.: Die Variable a wird sowohl in der ISR als auch in einer Funktion
verwendet und sollte (oder besser: muss) daher volatile deklariert
werden.

2.: Du liest den 10-Bit ADC-Wert in eine Character-Variable ein, in die
er gar nicht hineinpasst. Deshalb bekommst Du nie Werte über 255.
Entweder a als unsigned int deklarieren, oder das ADLAR-Bit im
ADMUX-Register setzen und nur das High-Byte (ADCH) des Ergebnisses
auslesen. Dann hast Du allerdings nur 8 Bit Auflösung.

von Sven (Gast)


Lesenswert?

Habs mal mit dem ADLAR-Bit und der 8-Bit Auflösung probiert. Klappt aber
auch nicht.

Was komisch an der ganzen Sache ist, das ich bei 0V am ADC0 Pin schon
einen Wert von 240 bekomme. Das kann doch schon eigenlich nicht
sein.....

von johnny.m (Gast)


Lesenswert?

> ADMUX = (0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3);
So was macht man einfach nicht. Nullen rumschieben bringt nix. Schreib
lieber
ADMUX &= ~((1<<MUX0)|(1<<MUX1)|(1<<MUX2)|(1<<MUX3));
Da weißt Du wenigstens genau, was Du da machst...

von johnny.m (Gast)


Lesenswert?

Deaktivier mal zur Sicherheit explizit den Pull-Up am ADC0 (PortC.0)

von Profi (Gast)


Lesenswert?

Das mit pause==50000 ist mir nicht ganz klar:
Es müssen erst 50000 Interrupts (d.h. 50000 Receiver Empty) ausgeführt
werden, damit ein neues Zeichen geschickt wird.
Ungewöhnliche Art einer Warteschleife...

When the Data Register empty Interrupt Enable (UDRIE) bit in UCSRB is
written to one, the USART Data Register Empty Interrupt will be
executed as long as UDRE is set (provided that global interrupts are
enabled). UDRE is cleared by writing UDR.

When interrupt-driven data transmission is used, the Data Register
empty Interrupt routine must either write new data to UDR in order to
clear UDRE or disable the Data Register empty Interrupt, otherwise a
new interrupt will occur once the interrupt routine terminates.


Wie johnny bereits schrieb: 10 bits passen nicht in 8. Deshalb
alternativ
UDR0 = ADCW >>2;

von Sven (Gast)


Lesenswert?

Hey, hat hingehauen. Ganz blöder Fehler.

Die Taktfrequenz war falsch eingestellt. Hatte die Tage mal den Quarz
gewechselt.

Nunklappt das auch mit der LED. Leider nur das einschalten.

Hab das zum Testen mal so gemacht:

void spannung()
{

  if(a == 32)
  {
  if(PORTB |= (1 << PB0))
  PORTB &= ~(1 << PB0);

  else
  PORTB |= (1 << PB0);
  }
}

Einschalten klappt, nur dass Ausschalten nicht....

von johnny.m (Gast)


Lesenswert?

Du hast in der zweiten if-Abfrage eine Zuweisung drin (PORTB |= (1 <<
PB0)). Das muss wenn überhaupt "if(PORTB & (1 << PB0))" heißen.
Außerdem ergibt die Zuweisung immer "wahr" als logischen Wert, so
dass das "else" vermutlich nie angesprungen wird.

von Sven (Gast)


Lesenswert?

Jup, jetzt klappts.

Nun brauch ich noch eine kleine entprellung für die Taster.

Gibt es die entprellung von peter auch in ner einfachen Form?

von Sven (Gast)


Lesenswert?

Wie kann ich den eine Bedingung setzen, dass ein Port eine bestimmte
Zeit auf High sein muss um etwas auszuführen?

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.