Hallo
Ich habe folgendes Problem. Ich versuche mich an einer
Analog/Digitalwandnlung. Hierbei habe ich das Problem das mir der
Mikrocontroller(Atmega644) bei z.B. 2 V am Eingang auch 2000 mV angibt
aber wenn ich den Eingang low lasse (gemessen 0.3 V ) er mir trotzdem
angibt zB. 1500 mV. Ich benutze einen Externen 14,7456 MHZ. Als Kanal
übergebe ich zB. 0 (für PortA Pin0). Die Referenzspannung beträgt 3,3 V.
long ReadAnalog(uint8_t mux)
{
if((mux > -1) | (mux < 8)){
uint8_t i;
uint16_t result;
ADMUX = mux; // Kanal waehlen
ADMUX |= (1<<REFS0); // AVCC als Referenz (3,3 V)
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); //
ADCSRA |= (1<<ADSC);
while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result = ADCW;
result = 0;
char zwischenspeicher[10];
for( i=0; i<4; i++ )
{
ADCSRA |= (1<<ADSC);
while ( ADCSRA & (1<<ADSC) ) {
;
}
result += ADCW;
ltoa(result,zwischenspeicher,10);
ausgabe(zwischenspeicher);
ausgabe(" ");
}
ADCSRA &= ~(1<<ADEN);
result /= 4;
return ((result * 3.30 /1024.00)*1000);
} // Ende if((mux>-1) | (mux < 8))
}
Bei "ausgabe(zwischenspeicher);" gibt mir der Mikrocontroller schon
300,600,900,1200 an. Wobei mich hierbei stört das 300 von 1024=3,3V
schon um die 1 V sind .(Die anderen sind aufaddierungen von 300 was auch
so sein sollte
Jemand ne idee?
Vielen dank im Vorraus
Alex
Alex wrote:
> aber wenn ich den Eingang low lasse (gemessen 0.3 V ) er mir trotzdem
Heißt das, der Eingang ist unbeschaltet? In dem Fall kann der Eingang
jeden Spannungspegel annehmen. Solche Messungen können höchstens
sinnvoll sein, wenn man gerne Zufallszahlen erzeugen möchte.
Gast wrote:
> Bist du sicher dass die Zeile wirklich macht was du dir vorgestellt> hast?> -> if((mux > -1) | (mux < 8)){>> z.B. wenn du jetzt 100 als mux übergibst.
Zufällig funktioniert das, aber nur, weil mux vom Typ uint8_t ist (also
unsigned) und deshalb (mux > -1) immer false ergibt.
Sinnvoller wäre es auf jeden Fall, einfach
if (mux < 8)
zu schreiben.
Gast wrote:
> Es ist wohl eher immer true, da jeder Wert den mux annehmen kann größer> als -1 ist.
Ne, eben nicht. mux ist 1 byte lang, folglich wird der Compiler für den
Vergleich die -1 als Bytewert verwenden. In Hexadezimalschreibweise ist
das 0xff. Zufällig ist dies genau gleich dem größten Wert, den eine
Variable vom Typ uint8_t - wie mux - annehmen kann.
Deshalb kann mux niemals größer als -1 sein. Klingt verrückt, ist aber
so.
Andreas Vogt wrote:
> Gast wrote:>> Es ist wohl eher immer true, da jeder Wert den mux annehmen kann größer>> als -1 ist.>> Ne, eben nicht. mux ist 1 byte lang, folglich wird der Compiler für den> Vergleich die -1 als Bytewert verwenden. In Hexadezimalschreibweise ist> das 0xff. Zufällig ist dies genau gleich dem größten Wert, den eine> Variable vom Typ uint8_t - wie mux - annehmen kann.> Deshalb kann mux niemals größer als -1 sein. Klingt verrückt, ist aber> so.
Die Conclusio ist zwar richtig, aber die Begründung ist falsch.
Es geht nicht um bytewert oder wordwert.
Es geht um Signedness.
mux > -1
ist ein Ausdruck, in dem 2 Datentypen gemischt werden.
mux ist ein uint8_t, also wohl ein unsigned char
-1 ist ein int. Genauer: ein signed int
Die C Regeln schreiben jetzt vor, dass alles auf die Länge des größten
gemeinsamen Datentyps gebracht werden muss. Das wäre jetzt erst mal 16
Bit, für den int. Aus dem uint8_t wird also ein uint16_t.
Jetzt steht da ein unsigned Typ einem signed Typ gegenüber und in dem
Fall sagen die C-Regeln, dass alles auf unsigned gebracht wird.
mux bleibt so wie es war, während -1 zu einem unsigned wird. Bei
Benutzung von 2-er Komplementregeln (was wir mal vorraussetzen können),
ist der zu -1 gehörende unsigned Wert 65535
Und jetzt hast du Recht.
mux wird wohl nie größer als 65535 sein. Vor allen Dingen gibt es keinen
unsigned 16 Bit Wert der größer als 65535 sein kann.
(Der Optimizer des Compilers könnte die Erweiterung von 8 auf 16 Bit
spritzen, allerdings bleibt das Problem nach wie vor, dass in ein und
derselben Expression ein unsigned mit einem signed Datentyp gemischt
wird. Und in dem Fall gewinnt immer unsigned)
Karl heinz Buchegger wrote:
> -1 ist ein int. Genauer: ein signed int
Ist das irgendwo festgelegt? Könnte der Compiler nicht auch ein signed
char daraus machen?
Karl heinz Buchegger wrote:
> Jetzt steht da ein unsigned Typ einem signed Typ gegenüber und in dem> Fall sagen die C-Regeln, dass alles auf unsigned gebracht wird.
Ich habe arbeite gerade einem C++ Projekt für einen ATmega mit der
Winavr Toolchain. Da habe ich mal gehässigerweise folgendes Kompilieren
lassen:
1
uint8_tmcucsr=MCUCSR;
2
if(mcucsr>-2)
3
__asm__volatile("nop");
Im resultierenden .lss-File sieht man, dass die if-Abfrage komplett
wegomptimiert wird, und dass das nop bedingungslos ausgeführt wird.
Offenbar ist der gcc - jedenfalls bei der Verarbeitung von cpp-Dateien -
der Ansicht, dass ein unsigned immer größer ist, als ein negativer
Wert. Eine Umwandlung von signed auf unsigned scheint hier gar nicht
stattzufinden.
Karl heinz Buchegger wrote:
> (Der Optimizer des Compilers könnte die Erweiterung von 8 auf 16 Bit> spritzen, allerdings bleibt das Problem nach wie vor, dass in ein und> derselben Expression ein unsigned mit einem signed Datentyp gemischt> wird. Und in dem Fall gewinnt immer unsigned)
Was genau meinst Du damit? Dass der Compiler den signed Wert einfach als
unsigned betrachtet? Das tut gcc in meinem Beispiel offensichtlich
nicht.
edit
Alles Quark, Du hast Recht. In meinem Beispiel wird die if-Abfrage
deshalb wegoptimiert, weil ein Wert mit der Länge von einem Byte nie
größer sein kann als eine zwei Byte lange -2, die als unsigned
betrachtet wird.
wieso sollte mux auf unsigned int erweitert werden? Im Gegenteil wird
aus mux ein signed int, womit der Vergleich immer true ist.
Erwähnenswert wäre noch
if((mux > -1) | (mux < 8))
Die bitweise Veroderung der beiden Vergleiche, was ebenfalls
funktioniert, aber tunlichst nicht zu Gewohnheit werden sollte. Kann
üble Fehler ergeben, die man nicht mehr sieht.