Forum: Mikrocontroller und Digitale Elektronik Analog/Digitalwandnlung Atmega644


von Alex (Gast)


Lesenswert?

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

von Andreas V. (tico)


Lesenswert?

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.

von Alex (Gast)


Lesenswert?

Jup habe den Fehler. Liegt nicht an der Software sondern an der 
Hardware.. Benutze keine Pull Up/Down Widerstände. Danke für die 
schnelle Hilfe

von Gast (Gast)


Lesenswert?

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.

von Andreas V. (tico)


Lesenswert?

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.

von Gast (Gast)


Lesenswert?

Es ist wohl eher immer true, da jeder Wert den mux annehmen kann größer 
als -1 ist.

von Andreas V. (tico)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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)

von Andreas V. (tico)


Lesenswert?

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_t mcucsr = 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.

von Eddy C. (chrisi)


Lesenswert?

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.

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.