Forum: Mikrocontroller und Digitale Elektronik A/D-Wandler ADS7841 über SPI mit ATmega16 auslesen ->Probleme


von Rainer (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

im Moment versuche ich mit einem ATmega16 über SPI den A/D-Wandler 
ADS7841 auszulesen.

A/D-Wandler:
http://focus.ti.com/lit/ds/sbas084b/sbas084b.pdf
Controller:
http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf

Die SPI-Schnittstelle des ATmega16 funktioniert, nur antwortet der 
A/D-Wandler nicht wie erwartet.
Im Moment sind drei der Kanäle offen und am Vierten liegen ca. 2,5 V an, 
trotzdem liefert der A/D-Wandler den Wert 0xFFF, also das Maximum 
zurück. Die Eingangsspannung kann ich variieren wie ich will, an der 
Ausgabe ändert sich nichts.
Gestern habe ich noch einen interessanten Effekt bemerkt. Wenn ich 
meinen Finger auf die Eingangspins lege, dann ändert sich auch die 
Antwort des A/D-Wandlers, die ich auf dem Oszilloskop beobachte.
Die Referenzspanung liefert eine 4,096 V-Referenzspannungsquelle. Die 
restliche Schaltung siehe Anhang.

Könnte es sein, dass der A/D-Wandler defekt ist und kann ich das 
irgendwie testen?

Nachfolgend noch der relevante Quellcode.
Alle möglichen Kombinationen aus CPOL, CPHA und DORD habe ich schon 
durchprobiert. Vernünftige Ergebnisse erhalte ich in keinem der Fälle.

Bin über jede Hilfe dankbar.
Gruß
Rainer
1
while(1)
2
{
3
    if ( timer500ms_flag == 1) // wird von Timer gesetzt
4
    {
5
      timer500ms_flag = 0;
6
7
      SS_ADC_LOW;
8
9
      // Aufbau des Befehlsbytes: |Startbit|A2|A1|A0|MODE|SGL/DIF|PD1|PD0|
10
      // Startbit: muss immer 1 sein
11
      // A2..A0: Wahl des Kanals
12
      // MODE: 12bit oder 8bit
13
      // SGL/DIF: Single-Ended Channels wenn high
14
      // PD1..PD0: Engergiesparmodus
15
16
      //Kanal 0
17
      spi_send_byte(0x94); // Befehlsbyte an den ADC senden -> 0b10010100
18
      spi_send_byte(0x00); // Dummydaten an ADC senden
19
      spi_send_byte(0x00); // Dummydaten an ADC senden
20
21
      //Kanal 1
22
      spi_send_byte(0xD4); // Befehle an ADC senden
23
      spi_send_byte(0x00); // Dummydaten an ADC senden
24
      spi_send_byte(0x00); // Dummydaten an ADC senden
25
26
      //Kanal 2
27
      spi_send_byte(0xA4); // Befehle an ADC senden
28
      spi_send_byte(0x00); // Dummydaten an ADC senden
29
      spi_send_byte(0x00); // Dummydaten an ADC senden
30
31
      //Kanal 3
32
      spi_send_byte(0xE4); // Befehle an ADC senden
33
      spi_send_byte(0x00); // Dummydaten an ADC senden
34
      spi_send_byte(0x00); // Dummydaten an ADC senden
35
36
      SS_ADC_HIGH;
37
    }
38
}
39
40
41
void spi_init (void)
42
{
43
    
44
  DDRB |= (1<<PB5);   //MOSI als Ausgang
45
  DDRB |= (1<<PB7);  //SCK als Ausgang
46
  DDRB |= (1<<PB4);  //SS als Ausgang
47
  
48
  SPCR = 0xD3; // SPI Interrupt enable, SPI enable, Master, f_osc/128 = 28,8 kHz
49
}
50
51
52
void spi_send_byte (unsigned char spi_byte)
53
{
54
    SPDR = spi_byte;
55
56
    while(!(SPSR & (1<<SPIF)))
57
    {
58
      // warten bis Übertragung fertig ist
59
    }
60
}

von Avr N. (balze)


Lesenswert?

Hallo Rainer,

ich kann in Deinem Sourcecodeschnippsel nirgendwo eine Stelle erkennen, 
wo Du den ADC per SPI einliest.

Hast Du den Teil einfach nicht eingestellt oder gibt's den Teil noch gar 
nicht ? ;-)

MfG,

Balze aka AVR Noob

P.S.: Einen tollen Vornamen haben Deine Eltern Dir ausgesucht! :)

von Rainer (Gast)


Lesenswert?

Hallo Balze,

danke für Deine Antwort und das...ehm...Kompliment. Ich leite das so an 
meine Eltern weiter. ;)

Die Daten des A/D-Wandlers werden im Interrupt des SPI-Moduls empfangen. 
Wie geschrieben schaue ich mir die Antwort aber direkt mit dem 
Oszilloskop an.

Der A/D-Wandler erwartet drei Bytes. Das erste ist ein Befehlsbyte und 
gibt unter anderem an von welchem Kanal gelesen werden soll. Die anderen 
beiden Bytes sind nur dazu da, um den Wandlungstakt zu generieren. 
Während dieser beiden Bytes shiftet der A/D-Wandler sein Ergebnis raus.
Und genau dieses Ergebnis ist nicht so wie erwartet. Alle Bits sind 
nämlich high, egal welche Spannung anliegt. Das macht mich ratlos.

Gruß
Rainer

von Avr N. (balze)


Lesenswert?

Hallo Rainer,

ich vermute mal, dass Du mit dem SPI Timing etwas nicht so machst wie es 
TI sich vorstellt.
Ich habe mal ein ganz aehnliches Problem gehabt:
Beitrag "Re: Problem mit TI ADS 1234 -> bit24-17 immer 0x00 oder 0xFF HILFE! :)"

Was siehst Du Dir denn auf dem Oszi an? die MISO Leitung?
Und da ist es richtig oder auch falsch ?

MfG,

Balze aka AVR Noob aka Rainer :D

von Avr N. (balze)


Lesenswert?

Nochmal Hallo,

das die Daten verschoben sind ist Dir klar, oder?

Wenn Du 2 Byte als Conversion Clock uebertraegst, liest Du das Ergebnis 
der vorherigen DA-Wandlung ein.

MfG,

Balze aka AVR Noob

von Rainer (Gast)


Lesenswert?

Hallo Balze,

aah jetzt ergibt das mit dem Namen einen Sinn. ;)

Der Hinweis mit dem Timing ist gut. Das werde ich mir mal genauer 
anschauen.
Mit dem Oszi triggere ich auf SCLK und schaue mir zusätzlich MISO an. 
Die Daten kommen schon falsch aus dem ADC raus. Wenn ich sie in den 
Mikrocontroller einlese, stimmen die Daten mit dem Osziplot überein.

Das Datenblatt gibt keinen Hinweis darauf, dass nicht die Daten der 
aktuellen Wandlung übertragen werden. Ist das allgemein bei ADCs so die 
über SPI angesprochen werden ?
Gut, ich starte sowieso alle 500ms eine Umwandlung. Da hätte ich auf 
jeden Fall gesehen, dass sich was ändert, auch wenn es nicht der neueste 
Wert wäre.

Dann werde ich mir das mit dem Timing nochmal GANZ genau anschauen. 
Leider komme ich vor morgen Abend nicht dazu. Bis dahin sag ich mal 
danke. :)

Gruß
Rainer

von Avr N. (balze)


Lesenswert?

Hallo Rainer,

Rainer schrieb:
> ...
> Das Datenblatt gibt keinen Hinweis darauf, dass nicht die Daten der
> aktuellen Wandlung übertragen werden.

Du hast Recht! Ich habe mir das Datenblatt nochmal angesehen.
Du ließt tatsächlich den momentan gesampelten Wert.

Beim ADS1256, den ich zuletzt eingesetzt habe, ist daß eine Art Pipeline 
Betrieb.
Um nicht erst einzulesen, dann den Multiplexer umschaltet und dann auf 
das Umschalten des Multiplexers zu warten, schaltet man erst den 
Multiplexer um und liest dann den im Schieberegister stehenden “alten“ 
Wert (der vorherigen Multiplexereinstellung).

Mfg,

Balze aka AVR Noob

von Rainer (Gast)


Lesenswert?

So. Das Problem ist gelöst. Wie immer war etwas sehr simples der Grund.
Eine kalte Lötstelle am V_ref-Pin. :D Fast schon peinlich, aber ich 
hatte die Referenzspannung immer am Messpunkt auf meiner Platine 
gemessen. Auf die Idee mal direkt am Pin zu messen bin ich nicht 
gekommen. Dazu passt auch, dass sich die Werte verändert haben, sobald 
ich den Finger auf die eine Seite des ICs gelegt habe. Auf dieser Seite 
war auch der V_ref-Pin.

Nun gut ich habe was gelernt, kann jetzt weiterbasteln und vielleicht 
hilft das ja jemandem mit dem gleichen Problem. ;)

Gruß
Rainer

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.