Forum: FPGA, VHDL & Co. Xilinx Spartan6 SPI ADC


von Alex (Gast)


Lesenswert?

Hey,

Ich habe einen ADC per SPI an einen Spartan6 angeschlossen.
ADC: LTC2308IUF  12bit 8Channel 500ksps ADC
Datenblatt: 
http://pdf1.alldatasheet.com/datasheet-pdf/view/253910/LINER/LTC2308IUF-PBF.html

Ich habe das SPI IP Core in EDK hinzugefügt ohne interrupt da ich die 
polling Methode benutzen will.
SPI IP Core Daten:
Ratio of PLB Clock Frequency To SCK Frequency:  32
Number of SPI transfer bits: 16

Und folgendes Programm benutze ich in SDK:
1
//SPI Device Id aus XParameter.h
2
#define SPI_DEVICE_ID    XPAR_SPI_0_DEVICE_ID
3
4
5
#define BUFFER_SIZE    12  //Buffergröße
6
#define DAC_Anzahl    2000000 //Anzahl Lese/Schreib Vorgänge
7
8
9
typedef u8 DataBuffer[BUFFER_SIZE];  //Bufferdefenition
10
11
12
//SPI
13
static XSpi  DAC_SPI;   /* The instance of the SPI device */
14
15
16
//Lese/Schreib-Buffer
17
u8 ReadBuffer[BUFFER_SIZE];
18
u8 WriteBuffer[BUFFER_SIZE];
19
20
21
//SPI Test
22
int DAC_SPI_test(void)
23
{
24
  int Status;
25
  u32 Count;
26
  u32 Count1;
27
  u32 Count2;
28
  u32 Delay;
29
30
    XStatus status = XST_SUCCESS;
31
    status = XSpi_Initialize(&DAC_SPI, SPI_DEVICE_ID);
32
33
    switch(status)
34
    {
35
            case XST_SUCCESS: print("Status: Erfolgreich initialisiert\n\r"); break;
36
            case XST_DEVICE_IS_STARTED: print("Status: Device is started\n\r"); break;
37
            case XST_DEVICE_NOT_FOUND: print("Status: Device not found\n\r"); break;
38
    }
39
40
    Xuint32 options = XSP_MASTER_OPTION;
41
    status = XSpi_SetOptions(&DAC_SPI, options);
42
43
    switch(status)
44
    {
45
            case XST_SUCCESS: print("Status: Erfolgreich option gesetzt\n\r"); break;
46
            case XST_DEVICE_BUSY: print("Status: Device busy\n\r"); break;
47
            case XST_SPI_SLAVE_ONLY: print("Status: Slave only\n\r"); break;
48
    }
49
50
    XSpi_SetSlaveSelect(&DAC_SPI, 1);
51
    XSpi_Start(&DAC_SPI);
52
53
54
  //Interrupts disable
55
  XSpi_IntrGlobalDisable(&DAC_SPI);
56
57
  //Anzahl der Datenübertragung
58
  for(Count=0;Count<DAC_Anzahl;Count++){
59
60
  //Ausgaberegister beschreiben
61
  WriteBuffer[0] = 1;      //Single Ended=1, diff. Ended=0    S/D
62
  WriteBuffer[1] = 0;      //ODD = 1 , SIGN = 0          O/S
63
  WriteBuffer[2] = 0;      //Adress selecet bit1        S1
64
  WriteBuffer[3] = 0;      //Adress selecet bit0        S0
65
  WriteBuffer[4] = 1;      //Unipolar=1, Bipolar=0
66
  WriteBuffer[5] = 0;      //SleepMode=1, NapMode=0
67
68
69
  /*
70
   * O/S=0
71
   * S1=0
72
   * S0=0
73
   * => CH0 selected => TUNE_INDICATOR //Signal an Channel 0
74
   */
75
76
77
  //Daten Übertragen
78
  Status=XSpi_Transfer(&DAC_SPI, WriteBuffer, ReadBuffer, BUFFER_SIZE);
79
  switch(Status)
80
  {
81
    case XST_SUCCESS: print("Status: Erfolgreich gesendet.\n\r"); break;
82
    case XST_DEVICE_IS_STOPPED: print("Status: Device stopped\n\r"); break;
83
    case XST_DEVICE_BUSY: print("Status: Device busy\n\r"); break;
84
    case XST_SPI_NO_SLAVE: print("Status: Device no slave\n\r"); break;
85
  }
86
87
88
  //Recive Daten Ausgeben
89
  for (Count1 = 0; Count1 < BUFFER_SIZE; Count1++) {
90
    xil_printf("ADC Wert %x: %d\n\r",Count1,ReadBuffer[Count1]);
91
  }
92
    for (Delay = 0; Delay < 500; Delay++);
93
  }
94
95
  return XST_SUCCESS;
96
}

Das Problem ist das ich bloß Fehlerhafte Daten zurück bekomme.
Die Ausgabe sieht z.b. folgender Maßen aus ohne das ich eine Spannung 
angelegt habe:

Status: Erfolgreich gesendet.
ADC Wert 0: 18
ADC Wert 1: 64
ADC Wert 2: 226
ADC Wert 3: 72
ADC Wert 4: 226
ADC Wert 5: 72
ADC Wert 6: 226
ADC Wert 7: 70
ADC Wert 8: 226
ADC Wert 9: 74
ADC Wert A: 226
ADC Wert B: 74

Schonmal danke im vorraus für das aufgebrachte interesse meines 
Problems.
Über evtl. Lösungen würde ich mich freuen.
Alex

von PittyJ (Gast)


Lesenswert?

Eine sinnvolle Methode ist, dass man auch den Readbuffer vorher löscht 
(z.B. mit 0), um zu sehen, was wirklich gelesen wird.

Danach sollte man mit dem Oszi messen, was der ADC wirklich sendet.
Und das dann mit den Werten vergleichen, die im Programm vorliegen.

Achja, Variablen Count und Count1 zu nennen, das macht Probleme, wenn 
man es einen Monat später wieder verstehen will. Geht das nicht 
sinnvoller?
Und es gibt nur einen "Count of Count".

von Alex (Gast)


Lesenswert?

Danke für die Antwort PittyJ

das mit dem readbuffer hab ich bei dem kopierten Code hier gerade nur 
rausgenommen das hatte ich sonst drin. Also das machte keine 
Veränderung.

Mit dem Count gebe ich dir auch Recht. Macht jedoch auch kein 
Unterschied an der Ausgabe.

Bei der Messung mit dem Oszilloskop sind mir bei dem SDI und Convst 
Signal Spikes aufgefallen die bei beiden Signalen gleich sind. Er sendet 
auf dem SDI Signal auch nicht meine Angelegte Bitreihenfolge. Es könnte 
sein das diese Spikes den Vorgang quasi immer wieder reseten und er mir 
deshalb so komische Werte zurück gibt. Das würde mich darauf zurück 
führen das ich in dem Programm schon ein Fehler haben müsste, jedoch 
weiß ich nicht wo.
Also hat wer evtl. noch Ideen für Fehler im Programm?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alex schrieb:
> Bei der Messung mit dem Oszilloskop sind mir bei dem SDI und Convst
> Signal Spikes aufgefallen die bei beiden Signalen gleich sind.
Was für Spikes? Wie oft treten die auf? Sieht dein Timing der 4 
Interfacesignale so aus, wie im Datenblatt auf Seite 17?

Alex schrieb:
> Das Problem ist das ich bloß Fehlerhafte Daten zurück bekomme.
> Die Ausgabe sieht z.b. folgender Maßen aus ohne das ich eine Spannung
> angelegt habe:
Irgendwie ist da schon ein Muster drin...
Und was würdest du erwarten?

> u8 ReadBuffer[BUFFER_SIZE];
Wie soll ein 12Bit AD-Wert in ein u8 passen?

von Alex (Gast)


Lesenswert?

Danke für die schnelle Antwort!

> u8 ReadBuffer[BUFFER_SIZE];
Wie soll ein 12Bit AD-Wert in ein u8 passen?

Also es könnte sein das ich da nun Grundliegend falsch bin aber sollte 
nicht theoretisch in jedem ReadBuffer immer nur eine 0 oder 1 stehen. 
Ich hätte jetzt gedacht das er wie im Datenblatt auf Seite 17 mir die 
Einzelnen Bits jeweils in ReadBuffer[X] zurückgiebt und ich diese danach 
zusammensetzten muss zu dem Wert.
Deshalb gebe ich doch auch am anfang Die Werte in den WriteBuffer 
einzelnd ein.

Ich habe es jetzt auf u16 geändert dabei sagt der Compiler mir acuh eine 
Warnung aus für den Transfer Befehl wegen der u16.
warning: passing argument 2 of 'XSpi_Transfer' from incompatible pointer 
type

Und das bekomme ich dann als Ausgabe
Status: Erfolgreich gesendet.
ADC Wert 0: 128
ADC Wert 1: 57360
ADC Wert 2: 57360
ADC Wert 3: 57360
ADC Wert 4: 57360
ADC Wert 5: 57360
ADC Wert 6: 0
ADC Wert 7: 0
ADC Wert 8: 0
ADC Wert 9: 0
ADC Wert A: 0
ADC Wert B: 0

Wenn ich eine Spannung anlege steigt der ADC Wert 0: jedoch stieg er auf 
z.B. 23569 ein Wert der bei einer 12bit auflösung ja eigentlich garnicht 
möglich ist. Auch komisch ist das dieser Wert nachdem ich die Spannung 
entferne nur ganz langsam abfällt.

Oszi Bilder versuche ich gleich nachzureichen.

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

So die Bilder leider nur mit Handy Camera.
Und immer nur die einzelnen Signale da ich nicht mehr als 2 Hände habe 
und die Pins so klein sind das ich das Oszi nicht festklemmen kann.

Bei den Bildern habe ich den WriteBuffer[0]=0x880 nun gesetzt ich war 
wohl falsch davor mit den 0 und 1 bits.

von PittyJ (Gast)


Lesenswert?

So wie ich das Datenblatt lesen kommen nur 12 Bit zurück??
Wenn die 12 Bit MSB-mäßig oben in einem uint16 stehen, dann müßte mann 
doch nur durch 16 teilen??

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alex schrieb:
> immer nur die einzelnen Signale da ich nicht mehr als 2 Hände habe
Der zeitliche Ablauf miteinander ist aber eigentlich 
interessant...

Denn wenn du das Timing vom Datenblatt nicht einhältst, dann kannst du 
alles mögliche bekommen. also musst du zuerst das mal überprüfen.

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Das Timing stimmt mit dem Datenblatt überein. Jedoch ist das Signal was 
ich reingebe 6*16bit lang. Also ich kann die ersten 6 WriteBuffer[1-6] 
mit verschiedenen 16bit Werten beschreiben.
Obwohl ich die Buffer größe ja auf 12 definiert habe. Nun stellt sich 
mir die Frage kann das damit zusammen hängen das ich in EDK bei dem IP 
Core Number of SPI bits: 16bit eingestellt habe? Jedoch kann man da ja 
nur 8/16/32 auswählen, also muss ich ja die 16 nehmen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alex schrieb:
> Also es könnte sein das ich da nun Grundliegend falsch bin aber sollte
> nicht theoretisch in jedem ReadBuffer immer nur eine 0 oder 1 stehen.
Nein, das ist falsch.
Du hast ein sehr grundlegendes Missverstindnis von Bit und Wort...
Oder du hast di falsch Vorstellung von "SPI". Sieh dir das mal an:
http://www.lothar-miller.de/s9y/archives/15-SPI.html

> Obwohl ich die Buffer größe ja auf 12 definiert habe.
Ein einzelnes Wort deines ADC hat 12 Bit. Um eine einzige Wandlung 
durchzuführen reicht es also aus, einen einzigen SPI-Transfer zu 
machen. Weil dein SPI nicht auf 12 Bit eingestellt werden kann, musst 
du aber 16 Bit übertragen. Wenn du Glück hast, geht das mit dem ADC und 
er ignoriert die ersten oder die letzten 4 Bits der Übertragung.

Für deinen 8-Kanal-ADC brauchst du insgesamt also bestenfalls 8 Puffer 
für die Kommandoregister und die Ergebnisse dieser 8 Kanäle. Diese 
Puffer sollten sinnvollerweise 16 Bit breit sein (das ist der nächste 
Schritt nach 12).

Weil du aber derzeit nur einen Kanal ansprechen willst, reicht das hier 
aus:
1
//Lese/Schreib-Buffer
2
u16 ReadBuffer;
3
u16 WriteBuffer;
4
:
5
:
6
7
  // Anzahl der Datenübertragung
8
  for(Count=0;Count<DAC_Anzahl;Count++){
9
10
  // Ausgaberegister beschreiben
11
  WriteBuffer = 0x880;      // Kommandowort
12
13
  // Daten Übertragen --> 1 einzige Übertragung reicht da aus.
14
  Status=XSpi_Transfer(&DAC_SPI, WriteBuffer, ReadBuffer, 1);
15
:

von Alex (Gast)


Lesenswert?

Vielen Dank für die erklärung! Ich war falsch davor mit den bit/byte im 
bezug auf den Buffer.
Wobei ich aber auch erwähnen muss das die Beschreibung von Xilinx 
verwirrend ist da sie dort schreiben:

* @param  ByteCount contains the number of bytes to send/receive. The
*    number of bytes received always equals the number of bytes sent.

Ich habe die entsprechenden Änderungen nun vorgenommen.
Es funktioniert jetzt bis auf ein paar Feinheiten die noch angepasst 
werden müssen. Jedoch muss ich den Wert des Buffers auf 2 stellen und 
nicht auf 1.
1
Status=XSpi_Transfer(&DAC_SPI, WriteBuffer, ReadBuffer, 2);

um in meinem Fall einmal 16bit zu übertragen.
und beim Empfangen muss ich die Zahl von 16 in 12 Bit noch angleichen.

Nochmals vielen Dank Lothar Miller

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alex schrieb:
> Jedoch muss ich den Wert des Buffers auf 2 stellen
Ja, das kommt darauf an, wie die Funktion implementiert ist. Und 16 Bit 
sind korrekterweise 2 Bytes...

> Nochmals vielen Dank Lothar Miller
De nada!

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.