Hallo
Ich habe ein atmega8 und habe ihn in c mit AVR Studio4 programmiert.
Er soll eine Spannung am ADC0 und ADC1 Port einlesen und in der zweiten
Zeile eines LCD ausgeben. Dies funktioniert auch wenn ich nur einen Wert
anzeigen lasse.
Sobalt ich beide Werte ( einen links einen rechts ) anzeigen lasse,
wechseln sich die Werte im Sekunden Tackt. Also die Anzeige von ADC0
zeigt dann für ca. ne Sekunde den Wert von ADC1 und umgekehrt an.
Woran könnte das liegen?
interne 5V
AREF mit Kondensator mit 100N auf GND
ADC0 Poti 0
ADC1 Poti 1
LCD Ausgabe:
Zeile1: Gestartet
Zeile2: 0000mV 0000mV
Vielen Dank Jens
> while (!(ADCSRA & ( 1<<ADSC)));
Das ADSC wird gelöscht, wenn die Wandlung beendet ist! Da es eine
Zeile weiter oben erst gesetzt wird, wird die Schleife direkt
übersprungen. Warten auf das Wandlungsergebnis geht anders...
Und benutze bitte zum Schreiben der Steuerregister die Bitnamen! Dafür
sind die da. Nicht nur für ADSC...
Zu deinem ADC Problem.
while (!(ADCSRA & ( 1<<ADSC)));
Das ist falsch rum.
Nachdem du den ADC auf einen neuen Kanal stellst, solltest du die erste
Messung verwerfen. Die ist normalerweise Müll. Es empfiehlt sich auch
ein paar mal hintereinander zu messen und den Mittelwwert davon zu
nehmen. Also so wie im Tutorial: Erste Messung verwerfen, dann zb 4 mal
messen und Mittelwert davon.
Warum verwendest du eigentlich nicht die Funktion aus dem Tutorial?
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Aktivieren_des_ADC
1
voidmain()
2
{
3
...
4
Start:
5
6
ADC0();
7
mV();
8
ADC1();
9
mA();
10
_delay_ms(300);
11
gotoStart;
12
13
while(1)
14
{
15
}
16
return0;
17
}
Der goto da drinn ist Nonsense. Die Idee ist es eine Endlosschleife zu
kreieren. Die ist im Prinzip ja auch schon da: while( 1 )
Nur müsstest du sie noch mit Leben füllen.
1
voidmain()
2
{
3
...
4
5
while(1)
6
{
7
ADC0();
8
mV();
9
ADC1();
10
mA();
11
_delay_ms(300);
12
}
13
return0;
14
}
Gewöhn dir goto gleich wieder ab (auch in deinen Umwandlungsfunktionen).
Wenn du zum jetzigen Zeitpunkt einen goto benutzen willst, gibt es immer
eine einfachere strukturierte Möglichkeit dasselbe zu erreichen. Wenn
ich es (ohne grosse Probleme oder darüber Nachzudenken) schaffe eine
Dreiviertel-Million Lines of Code Programm ohne goto zu schreiben, dann
wirst du ja wohl die 80 Zeilen ohne goto machen können.
Karl heinz Buchegger wrote:
> Nachdem du den ADC auf einen neuen Kanal stellst, solltest du die erste> Messung verwerfen. Die ist normalerweise Müll.
Kannst du diese Aussage belegen? Im Datenblatt steht nur, dass man nach
dem Einschalten/Wechseln der Referenz die erste Messung verwerfen soll:
The first ADC conversion result after switching reference voltage source
may be inaccurate, and the user is advised to discard this result.
Bei mir funktioniert der Wechsel des Kanals nämlich auch problemlos.
Benedikt K. wrote:
> Karl heinz Buchegger wrote:>>> Nachdem du den ADC auf einen neuen Kanal stellst, solltest du die erste>> Messung verwerfen. Die ist normalerweise Müll.>> Kannst du diese Aussage belegen? Im Datenblatt steht nur, dass man nach> dem Einschalten/Wechseln der Referenz die erste Messung verwerfen soll:> The first ADC conversion result after switching reference voltage source> may be inaccurate, and the user is advised to discard this result.>> Bei mir funktioniert der Wechsel des Kanals nämlich auch problemlos.
Wenn das so im Datenblatt steht, dann hast hast du da wohl recht und ich
war überereifrig.
>Nachdem du den ADC auf einen neuen Kanal stellst, solltest du die erste>Messung verwerfen. Die ist normalerweise Müll.
Nachdem daß ja immer wieder postuliert wird, und auch im Beispiel-Code
des Tutorials so steht, kann mir mal jemand sagen, wo genau das im
Datenblatt steht? Ich finde das einfach nicht.
Oliver
Das Problem liegt im Ablauf des Umschaltens des Multiplexers. Wenn du
den Befehl gibst, den Kanal zu Wechseln, wird dieser Befehl
logischerweise erst nach Ablauf der letzten Wandlung ausgeführt. Nach
Ablauf der Wandlung wird aber auch, das Flag gesetzt, dass neue Daten
bereitstehen. Somit hast du also nachdem du den Multiplexer umgeschaltet
hast, noch ein Wandlungsergebnis vom vorher ausgewählten Kanal. Deshalb
verwerfen viele Entwickler einfach das erste Wandlungsergebnis nach dem
Kanalwechsel. Wenn man es aber geschickt aufgleist, geht es natürlich
auch ohne verwerfen von Daten. Man kann nämlich auch einfach den Befehl
zum Umschalten des Mux einfach vor der letzten Wandlung des
vorhergehenden Kanals absetzen. Klar soweit?
@Ralf Schwarz
>Klar soweit?
Nö. Ein " ham' wer schon immer so gemacht" ist genauso hilfreich wie
"viel hilft viel", das einmauern toter Katzen in Brückenfundamente, oder
"schad' ja nix".
Etwas genauer: Die Anwendung hier sind einzelne Wandlungen, der ADC wird
jedes mal neu gestartet, VREF wird nicht umgeschaltet. Ein
Standard-Szenario für ADC-Betrieb ohne free-run.
Wo steht im Danteblatt, daß ein Umschalten des Kanals vor dem Start des
ADC's zu einem ungültigem Wandlungsergebnius führt?
Oliver
@Oliver: Sorry für meine unqualifizierte Aussage. Du hast natürlich
Recht, der ADC läuft hier nicht im Free Running mode, somit hat mein
Hinweis natürlich nichts mit dem Problem zu tun. Aber da viele (auch
erfahrene) Leute sich schwer tun mit dem Timing des ADCs, hab ich hier
mal meinen Senf dazugegeben und dümmer ist dabei sicher niemand
geworden.
elomt wrote:
> funktioniert bei mir nicht es wirt auf dem LCD zweimal(> I'schwartzes kästchien schräges X ) ausgegeben.
My fault:
sprintf( Text, "%04u%s", Value, Unit );
****
Mann muss dem sprintf schon auch sagen, wo der Ergebnistext hin soll :-)
Tschuldigung.
So
jetzt funktioniert alles habe :
while (!(ADCSRA & (1<<ADSC))); gegen while (ADCSRA & (1<<ADSC));
und die Ausgabe von Karl Heinz
Vielen Vielen Vielen Dank
zu dem GOTO Befehl
Ich habe hier im Forum schon oft gelesen das der goto oldschool ist und
nicht mehr genutzt werden soll. Andere sagen benutzt ihn ( ist einfach
und funktioniert). Meine Frage ist nun was für Altanatieven gibt es
denn?
elomt wrote:
> Ich habe hier im Forum schon oft gelesen das der goto oldschool ist und> nicht mehr genutzt werden soll. Andere sagen benutzt ihn ( ist einfach> und funktioniert). Meine Frage ist nun was für Altanatieven gibt es> denn?
Nichts dagegen goto zu benutzen, wo es einen Sinn ergibt. Aber wenn man
eine Schleife implementiert, duerfte while() fast immer erste Wahl sein.
Dein Code sieht eher aus wie Markoassembler mit den ganzen "von Hand"
implementierten Schleifen. Im Uebrigen sind sind deine Spruenge in den
mA und mV Funktionen hoechst zweifelhaft...
elomt wrote:
> Ich habe hier im Forum schon oft gelesen das der goto oldschool ist und> nicht mehr genutzt werden soll.
Prinzipiell richtig, da man schnell Fehler damit machen kann und das
Programm unübersichtlich werden kann.
> Andere sagen benutzt ihn ( ist einfach und funktioniert).
Und hat einige Vorteile gegenüber anderen Lösungen. Generell verbieten
ist also keine Lösung.
> Meine Frage ist nun was für Altanatieven gibt es> denn?
In diesem Fall eine beliebige Endlosschleife:
1
Start:
2
3
ADC0();
4
mV();
5
ADC1();
6
mA();
7
_delay_ms(300);
8
gotoStart;
Dies kann man wunderbar durch folgendes ersetzen:
1
while(1)
2
{
3
ADC0();
4
mV();
5
ADC1();
6
mA();
7
_delay_ms(300);
8
}
Die anderen gotos kann man auch durch ein while ersetzen. Dazu muss
lediglich das if durch ein while ersetzt werden, wenn ich das richtig
sehe.
Sorry wenn ich nochmal was schreibe aber ich habe gerade gesehen das
mein adc wert nicht unter 14 geht wenn ich gnd auf den adc port gebe.
Weis einer woran das liegen könnte?
Auch Multimeter messen Mist.
Aber 14 ist schon ein bischen viel.
Welchen Wert kriegst du, wenn du mal direkt GND an den Pin hängst?
Edit: Grade gesehen. Du hast ja schon Masse mal direkt an den Pin
angeschlossen.
Zeig nochmal das Pgm, so wie es jetzt aussieht. Schaltbild wär auch
nicht verkehrt, damit wir nicht aneinander vorbeireden.
Hallo
Ich schreibe erstmal ein neues Programm da mein jetziges mit der ganzen
LCD Menüführung zu umfangreich ist.
Vielen Dank noch mal für die guten tips.