ADC AD7924 Probleme...

Hallo zusammen

Ich komme nicht mehr weiter beim auslesen eines ADC AD7924 (link) an einem MEGA2560.
Ich kann zwar die 4 Kanäle auslesen, aber das Resultat im Serialmonitor kann ja kaum stimmen:
Serialmonitor, alle Eingänge 2.5V (max):
Ch.0 = 4094
Ch.1 = 8191
Ch.2 = 12286
Ch.3 = 16383

0V:
Ch.0 = 16
Ch.1 = 4112
Ch.2 = 8206
Ch.3 = 12304

Der Code dazu ist im Anhang. Ebenso ein paar Printscreens vom Logic-Analyzer.

#include <SPI.h>
long result0;
long result1;
long result2;
long result3;
long msb0;
long lsb0;
long msb1;
long lsb1;
long msb2;
long lsb2;
long msb3;
long lsb3;
  
void setup() {
  Serial.begin(115200);
  pinMode(SS,OUTPUT);
  digitalWrite(SS,HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE2));

}
//83 Ch0, 87 Ch1, 8B CH2, 8F CH3

void loop() {

  digitalWrite(SS,LOW);
  SPI.transfer(0x83);
  SPI.transfer(0x30);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  msb0 = SPI.transfer(0x0);
  lsb0 = SPI.transfer(0x0);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  SPI.transfer(0x87);
  SPI.transfer(0x30);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  msb1 = SPI.transfer(0x0);
  lsb1 = SPI.transfer(0x0);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  SPI.transfer(0x8B);
  SPI.transfer(0x30);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  msb2 = SPI.transfer(0x0);
  lsb2 = SPI.transfer(0x0);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  SPI.transfer(0x8F);
  SPI.transfer(0x30);
  digitalWrite(SS,HIGH);

  digitalWrite(SS,LOW);
  msb3 = SPI.transfer(0x0);
  lsb3 = SPI.transfer(0x0);
  digitalWrite(SS,HIGH);

  result0=msb0<<8|lsb0;
  Serial.print("Ch.0 =     ");
  Serial.println(result0);
  result1=msb1<<8|lsb1;
  Serial.print("Ch.1 =     ");
  Serial.println(result1);
  result2=msb2<<8|lsb2;
  Serial.print("Ch.2 =     ");
  Serial.println(result2);
  result3=msb3<<8|lsb3;
  Serial.print("Ch.3 =     ");
  Serial.println(result3);
  Serial.println();
  delay(500);
 
}

Wie man sieht stimmt der Ch.0, aber bei allen anderen wird immer ca. 4095 dazu gezählt.
Die beiden Control-Bytes sind msb = 1000 0011, lsb = 0011 0000
lsb ändert nicht, msb nur die Bits 3 + 4 (Adresse Ch.)
Irgendwo mache ich einen Fehler, aber wo?

Bitte um Hilfe :wink:

Gruss
Franz

AD7924-5_MEGA.ino (1.57 KB)

ad7924.pdf (854 KB)

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Laut Datenblatt (S. 26) müssen die Bits für die Kanalnummer ausgeblendet werden.

Ok, aber werden den die nicht durch das Bitshift "result0=msb0<<8|lsb0" ausgeblendet?
Sorry für die Frage, aber ich stehe noch ein bisschen auf Kriegsfuss mit dem Bitshift;)

Gruss
Franz

So wird nichts ausgeblendet, nur aneinandergehängt. Ausblenden geht mit bitweisem UND: &,

Ok, also etwa so?

result0=msb0<<8|lsb0;
result0=(result0<<4)>>4;

Zuerst 4 nach links um alle 4 Bit auszublenden und dann wieder 4 nach rechts.
Werde das morgen mal probieren.

Das wird nichts, wenn result0 long ist.

result0=(msb0&&B00001111)<<8|lsb0;
result0=(msb0 & B00001111)<<8|lsb0;

Schon besser, aber && ist hier fehl am Platz :frowning:

DrDiettrich:
Das wird nichts, wenn result0 long ist.

Ok, aber bei int würds funktionieren, oder?

Azli:
Ok, aber bei int würds funktionieren, oder?

Ja ist aber viel umständlicher.
msb0 & B00001111 ist ein einziger Maschienenbefehl.
Grüße Uwe

Hallo,

warum überhaupt shiften und warum nur 4 Bits betrachten?
Man bekommt 16 Bit angeliefert. Die ersten sind 2 Nullen. Dann kommen 2 Bits für den aktiven Kanal und dann 12 Bits für den Messwert. Alles MSB first. Die obersten Nullen benötige ich nicht und die Kanalnummer auch nicht wenn ich weiß welchen ich gerade abgefragt habe. Mich interessieren also nur die untersten 12 Bits. Ich würde demzufolge eine 12Bit Maske drüber legen und fertig.

result = data & 0x0FFF

Edit:
ja okay, die SPI.transfer Funktion arbeitet Byteweise. Hatte nur meine Funktion im Kopf. Sorry.

Hallo,

Bitweise Operationen nur ein & Zeichen. :wink:
Logische Operationen mit zwei && Zeichen.

long temp = (msb0 & 0x0F) << 8;
long result0 = temp | lsb0;

oder kombiniert

long result0 = ((msb0 & 0x0F) << 8) | lsb0;

Die untersten 12 Bits bekommt man so:

result = (...) & 0xFFF;

Hallo,

ist ja richtig, nur dann muss man vorher die Bytes richtig verknüpfen und dann die Maske über alles drüber. Ist am Ende Jacke wie Hose. :slight_smile:

Funktioniert :slight_smile:

Vielen Dank für eure Hilfe, ich denke jetzt hab ich das mit dem Bit-Geschiebe (fast) im Griff ;D

Gruss
Franz