Hallo,
ich habe eine Frage zum Initialisieren eines ADC-Kanals.
Im Anhang ist zu sehen, wie ich das angeschlossen habe.
Ich verwende ein ATmega8 und als ADC-Eingang kommt PC0 (ADC0) zum
Einsatz:
1
[...]
2
unsignedcharADCkanal=0;
3
[...]
4
//initialisieren des Analog-Digital-Converters
5
voidadcinit(void)
6
{
7
// AVcc als externe Referenzspannung nutzen, Spannungsmessung an PC0
>>ADMUX = (1<<REFS0) | (0<<REFS1) | ADCkanal;
wenn ich das so sehe solltest du dir erstmal bewusst machen was in
dieser zeile eigentlich geschieht........ weil so is das mehr als nur
absoluter mist
Danke,
ich habe diese Routine in ähnlicher Form in einem anderen Posting
bereits verwendet, da es sich um ein größeres Projekt handelt (ist kein
Cross-Posting -> nur dieses ADC-Thema wollte ich hier getrennt
behandeln).
Da wurde mir gerade auch berichtet, dass das komisch ist.
Es handelt sich nämlich um einen fertigen Code, den ich zum Üben nehmen
wollte. War wohl die falsche Wahl...
Das Tutorial werde ich durchgehen müssen und das gesamte Programm wohl
auch selber schreiben, da der fertige Code voller Fehler zu sein scheint
und es einem Anfänger nicht gerade leicht fällt, alle Fehler zu finden
und zu korrigieren.
Also, jetzt mal der Reihe nach...
Ist überhaupt die Beschaltung richtig?
ADC Prescaler Select bestimmen:
TFmin = 18,432
TFmax = 73,728
Also kommt ein Teilungsfaktor von 32 oder 64 zum Einsatz.
Es soll aber schnell gewandelt werden, deshalb nehme ich einen
Teilungsfaktor von 32.
Ist das dann folgend richtig?
macht nicht, was du möchtest. Zur Messung auf Kanal 0 muß ADMUX 3..0 =
0000 gesetzt werden. PD0 ist eine Konstante zum Zugriff auf den Pin PD0
im PORT-Register, und hat den Wert 1. Das hat mit ADC0 nichts zu tun
(auch wenn es der selbe Pin ist). Mit deiner Zeile würdest du auf Kanal
ADC 1 messen.
entspricht anscheinend dem Tutorial, und sollte daher funktionieren,
auch wenn weder der dummy-ADC-Zyklus noch das anschließemde Auslesen des
Registers erforderlich sind. Ausser, daß da unnütz Zeit verbraten wird,
schadet es aber auch nicht.
Oliver
Danke Oliver,
ich möchte aber 5V als Referenz nehmen und nicht die internen 2,56V, da
ich bis 4,5V messen muss.
Dachte mit
1
ADMUX|=(0<<REFS1)|(1<<REFS0);
verwende ich AVcc als Referenzspannung, also 5V.
Wenn ich die interne 2,56V Spannungsreferenz nehmen möchte, muss ich
doch
1
ADMUX|=(1<<REFS1)|(1<<REFS0);
schreiben, oder ist das ein Denkfehler meinerseits?
Der Rest von der ADC-Routine ist vom Tutorial abgekupfert, ja, richtig
erkannt! Aber ist das auch richtig implementiert?
Achilles schrieb:
> Der Rest von der ADC-Routine ist vom Tutorial abgekupfert, ja, richtig> erkannt! Aber ist das auch richtig implementiert?
Die Tutorial Routine funktioniert.
Und ehe du dich an der vergreifst und sie umänderst, solltest du sie
erst mal so lassen wie sie ist.
Du hast bei deiner Umänderei gleich wieder einen Fehler eingebaut. Damit
der ADC überhaupt arbeitet, muss er enabled sein, sprich das ADEN Bit
muss gesetzt sein. Am Ende deiner messen() Funktion disablest du den ADC
und schaltest ihn nie wieder ein.
Im Allgemeinen sind die Tutorialsfunktionen hier ziemlich gut getestet.
Das hängt auch damit zusammen, dass sie sofort korrigiert werden, sobald
ein Benutzer einen Fehler darin meldet (was mitlerweilse sehr selten
vorkommt). Wenn du also die Code-Schnipsel so übernimmst, wie sie dir im
Tutorial angeboten werden, ist die Wahrscheinlichkeit sehr hoch, dass
das auch funktioniert. Wenns dann nicht funktioniert, dann liegt das
daran, dass
* du entweder den Schnipsel falsch eingebaut hast oder
* du den Schnipsel verändert hast und dabei Fehler eingebaut hast
Man ist daher immer gut beraten, Schnipsel erst mal so zu lassen, wie
sie präsentiert werden. Und erst dann macht man kleine Veränderungen und
beobachtet ob die Funktionalität stribt. Wenn ja, dann hat man beim
Verändern einen Fehler eingebaut.
>Dachte mitADMUX |= (0<<REFS1) | (1<<REFS0);>ADMUX |= (1<<REFS1) | (1<<REFS0);>verwende ich AVcc als Referenzspannung, also 5V.
Ok, tust du auch. Ich nutze (und mag) die Schreibweise (0<<REFS1) nicht,
daher die Verwirrung, aber das ist Ansichtssache.
Oliver
Karl heinz Buchegger schrieb:
> Am Ende deiner messen() Funktion disablest du den ADC> und schaltest ihn nie wieder ein.
Super, danke! Im Tutorial steht das so, weil man damit Strom sparen
kann.
Ich disable erstmal nicht das ADEN-Bit, sondern nehme einfach
1
voidmessen(void)
2
{
3
[...]
4
ADCSRA&=~(1<<ADEN);
5
[...]
6
}
raus. Den Code kann ich hinterher besser schreiben, aber du kennst es
bestimmt selber, dass Anfänger gerne zu quick&dirty greifen und sich
freuen, wenn überhaupt das Programm funktioniert!
Hab bitte Verständnis!
@Oliver:
Wie schreibst du das denn anders?
Gruß,
Achilles
So, ich habe ein neues Problem:
Da ich die Beschaltung wie in meinem ersten Posting benutze und mein
IU-Wandler derzeit 2,5V ausgibt, sollte mein ADC eigentlich einen Wert
von ~511 einlesen?! Macht er aber nicht:
Der Wert fängt bei ~340 an und fällt bis auf ~305 ab, wenn mehrere
Anfragen an die Funktion messung() kurz hintereinander kommen.
Das Beispiel im Tutorial liefert dieselben Werte.
Wer den kompletten Code braucht:
[Beitrag "Re: ATmega8 und UART => Code bringt Einsteiger zum Verzweifeln"]
Was mache ich denn nun wieder falsch?
>> hat es funktioniert!
was auch völlig richtig ist.
(1<<PC0) schiebt eine 1 PC0 mal, also 0 mal, nach links.
Macht dann 0x01 und damit ADC1.
Da hat sich der Oliver in seiner Korrektur vertan. ;-)
Gruß aus Berlin
Michael