Forum: Mikrocontroller und Digitale Elektronik Probleme ADC-Werte vom AT89C51CC01


von lars (Gast)


Lesenswert?

Hallo,

ich versuche analoge werte vom AT89C51CC01 zu lesen. Jeder zweite Wert 
scheint falsch zu sein.

272
448
272
438
272
438
272
440
272
437
272
436
273
436
273
434
273
434
273
434

Der C-Code sieht so aus.

ADCF = 0x80;     // kanal P1.7 für ADC
ADCON = 0x20;   // Anfang ADC
ADCON  &= 0xF8; // Clear the field SCH[2:0]
ADCON |= 0x07;  // Select kanal
ADCON |= 0x08;  // Fangt Umrechnung im Stadard Mode an
while((ADCON & 0x10)!= 0x10)
{}// Warte flag
ADCON &= 0xC7; // Clear the End of conversion flag
ADC_Wert = (ADDH << 2)+(ADDL);
printf("%i\n",ADC_Wert);
ADC_Wert = 0x00;

ich würde mich freuen wenn mir jemand helfen könnte.

ich hoffe ich habe alle relevanten Angaben gemacht.

Vielen Dank !!!!

von Carlos (Gast)


Lesenswert?

Hallo Lars,
setze in das Klammerpaar bei der while-Schleife ein Semikolon !
Also:

while (.....) {;}

oder

while {....};

Carlos

von Carlos (Gast)


Lesenswert?

Tschuldigung: Falsche Klammern beim 2. Beispiel:

while (....);

Carlos

von Karl H. (kbuchegg)


Lesenswert?

> ADC_Wert = (ADDH << 2)+(ADDL);

Die Berechnung ist erst mal grundsätzlich falsch. Du musst ADDH um 8 Bit 
verschieben, damit die 2 Bit, die in ADDH gelten an die richtige 
Position kommen.

Zum anderen hast du mit dieser Anweisung keine Kontrolle darüber, in 
welcher Reihenfolge ADDH und ADDL tatsächlich ausgelesen werden. Der 
Compiler darf hier jede beliebige Reihenfolge benutzen.

Ich weiß jetzt nicht, wie das bei deinem µC ist, aber bei den Megas ist 
es so, dass zwingend zuerst L und erst dann H ausgelesen werden muss. 
Diese Reihenfolge ist aber nur durch

  ADC_Wert = ADDL;
  ADC_Wert += ADDH << 8;

garantiert.

von Carlos (Gast)


Lesenswert?

Hallo Karl Heinz,
da muss ich Dir leider widersprechen: die Berechnung ist genau richtig 
und läuft bei uns so schon seit einiger Zeit.
Man muss nur darauf achten, daß ´ADC_Wert´ auch eine unsigned 
int-Variable ist, sonst klappts nicht und das Semikolon in der 
while-Klammer darf nicht fehlen.

Carlos

von Karl H. (kbuchegg)


Lesenswert?

Carlos schrieb:
> Hallo Karl Heinz,
> da muss ich Dir leider widersprechen: die Berechnung ist genau richtig

In ADDH steht der Wert so, dass er um 2 Bit verschoben werden muss?`
Das glaub ich dir nicht. Es sei denn es handelt sich um einen 4 Bit ADC, 
wobei sich dann aber die Frage stellt: wozu H und L Register.

> Man muss nur darauf achten, daß ´ADC_Wert´ auch eine unsigned
> int-Variable ist, sonst klappts nicht und das Semikolon in der
> while-Klammer darf nicht fehlen.

Das ist doch großer Unsinn. Der Semikolon in der Klammer hat nichts 
damit zu tun. Der leere Block ist eine leere Anweisung, die vom while 
abhängt. Das ist alles korrekt, du läufst da einem Phantom nach.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Carlos schrieb:
>> Hallo Karl Heinz,
>> da muss ich Dir leider widersprechen: die Berechnung ist genau richtig
>
> In ADDH steht der Wert so, dass er um 2 Bit verschoben werden muss?`
> Das glaub ich dir nicht. Es sei denn es handelt sich um einen 4 Bit ADC,
> wobei sich dann aber die Frage stellt: wozu H und L Register.

Edit:

Es gibt eine Möglichkeit, wann diese Berechnung richtig sein kann.
Dann, wenn die Bits in den Registern so angeordnet sind

      ADDH                          ADDL

  D9 D8 D7 D6 D5 D4 D3 D2       0 0 0 0 0 0 D1 D0

Ob das so ist, weiß ich nicht. Ungewöhnlich wäre es allemal.

von Carlos (Gast)


Lesenswert?

Hallo Karl Heinz,
es ist leider ganz genau so, wie ich gesagt habe:
der A/D-Wandler beim CC01er ist ein 10 Bit Wandler und die Ergebnis-Bits 
ADAT2 bis ADAT9 stehen im SFR ADDH und die Bits ADAT1 und ADAT0 stehen 
im SFR ADDL ganz rechts.
Wenn Du also das 10 Bit-Ergebnis in einer unsigned int-Variablen 
zusammen bauen willst, schiebst Du ADDH um zwei Stellen nach links und 
addierst dazu ADDH.
Und nichts anderes !

Und meines Wissens nach ist die Leer-Anweisung (=´NICHTS-Tun´, also 
warten) in ´C´ immer noch das reine Semikolon und kein leeres 
Klammern-Paar.

Carlos.

von Karl H. (kbuchegg)


Lesenswert?

Carlos schrieb:

> der A/D-Wandler beim CC01er ist ein 10 Bit Wandler und die Ergebnis-Bits
> ADAT2 bis ADAT9 stehen im SFR ADDH und die Bits ADAT1 und ADAT0 stehen
> im SFR ADDL ganz rechts.
> Wenn Du also das 10 Bit-Ergebnis in einer unsigned int-Variablen
> zusammen bauen willst, schiebst Du ADDH um zwei Stellen nach links und
> addierst dazu ADDH.
> Und nichts anderes !

Ok.
Diese Möglichkeit hab ich mir jetzt selbst auch schon zusammengereimt.
Dann ist es das eben nicht.
Was ist mit der Auslesereihenfolge der Register? Ist die wichtig?

> Und meines Wissens nach ist die Leer-Anweisung (=´NICHTS-Tun´, also
> warten) in ´C´ immer noch das reine Semikolon und kein leeres
> Klammern-Paar.

In diesem Punkt ist dein Wissen falsch. Ein leeres Klammernpaar ist eine 
perfekte leere Anweisung. Wenn dein Compiler das nicht mitmacht, dann 
ist der Compiler fehlerhaft.

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.