Forum: Mikrocontroller und Digitale Elektronik SPI und der A/D Wandler AD7124-4


von Jan H. (janiiix3)


Lesenswert?

Hallo,

ich bekomme leider keine Antwort (DOUT) vom oben genannten Chip.
MOSI, SCK, CS passen soweit (mit dem Oszi gemessen).
Habe das EVAL Board von AD (sollte also an der HW wohl nicht liegen).

Hier mal meine Config.:
1
    /* set MOSI and SCK output, all others input */
2
    MOSI_DDR  |=  (1<<MOSI_BIT);
3
    MISO_DDR  &= ~(1<<MISO_BIT); 
4
    SCK_DDR    |=  (1<<SCK_BIT);
5
    SS_DDR    |=  (1<<SS_BIT);   // software slave select signal
6
    SS_HA_DDR  |=  (1<<SS_HA_BIT);  // hardware slave select signal
7
    
8
    SS_HA_PORT  |=  (1<<SS_HA_BIT);
9
    
10
    /* enable SPI, Master */
11
    SPCR |= ((1<<SPE) | (1<<MSTR));
12
    
13
    /* clear the bit´s (for multi init) */
14
    SPCR &= ~((1<<SPR0) | (1<<SPR1)); // fclk/4
15
    SPSR &= ~(1<<SPI2X);
16
    
17
    /* clear the bit´s (for multi init) */
18
    SPCR &= ~((1<<CPOL) | (1<<CPHA));
19
    
20
    /* config "Clock Polarity and "Clock Phase" */
21
    switch(clock_option)
22
    {
23
      case 0 : {SPCR &= ~((1<<CPOL) | (1<<CPHA)); }break; // mode 1
24
      case 1 : {SPCR |=  (1<<CPHA);        }break; // mode 2
25
      case 2 : {SPCR |=  (1<<CPOL);        }break; // mode 3
26
      case 3 : {SPCR |=  ((1<<CPOL) | (1<<CPHA));  }break; // mode 4
27
      default: {return 0;              }; // error
28
    }
29
    
30
    /* config SPI Bus Speed fclk/prescaler */
31
    switch (prescaler)
32
    {
33
      case 0:    {SPSR |=  (1<<SPI2X);              }break; // 2
34
      case 1:    {SPCR |=  (1<<SPR0); SPSR |=  (1<<SPI2X);    }break; // 8
35
      case 2:    {SPCR |=  (1<<SPR1); SPSR |=  (1<<SPI2X);    }break; // 32
36
      case 3:    {SPCR |=  (1<<SPR0); SPSR |=  (1<<SPI2X);    }break; // 64
37
      case 4:    {SPCR |=  ((1<<SPR1) | (1<<SPR0));      }break; // 128
38
      default:  {return 0;                    }; // error
39
    }
40
    return 1;

1
void spi_master_transmit(uint8_t cData)
2
{
3
  /* start transmission */
4
  SPDR = cData;
5
  
6
  /* wait for transmission complete */
7
  while(!(SPSR & (1<<SPIF)));  
8
}
9
10
uint8_t spi_receive(void)
11
{  
12
  /* Wait for reception complete */
13
  while(!(SPSR & (1<<SPIF)));
14
15
  /* return data register */
16
  return SPDR;  
17
}
1
uint8_t AD7124_read_uint8(uint8_t reg)
2
{
3
  uint8_t temp = 0;
4
  unsigned char buffer[1] = {0};
5
  
6
  buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg);
7
  spi_enable_chip();
8
  spi_disable_chip(); // start transmission condition
9
  
10
  spi_master_transmit(buffer[0]); // register address
11
  spi_master_transmit(0x00); // dummy byte
12
13
  itoa(buffer[0],Buffer,10);
14
  send_str_uart("\r\n");
15
  send_str_uart("Addr.: ");
16
  send_str_uart(Buffer);
17
  send_str_uart("\r\n");
18
  send_str_uart("Rec.: ");
19
  
20
  temp = (uint8_t)spi_receive(); // first byte
21
  
22
  spi_enable_chip(); // stop transmission condition
23
  
24
  return (uint8_t)temp;
25
}
1
/* Communication Register bits */
2
#define AD7124_COMM_REG_WEN    (0 << 7)
3
#define AD7124_COMM_REG_WR     (0 << 6)
4
#define AD7124_COMM_REG_RD     (1 << 6)
5
#define AD7124_COMM_REG_RA(x)  ((x) & 0x3F)

hat jemand eine Idee???

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


Lesenswert?

Jan H. schrieb:
> MOSI, SCK, CS passen soweit (mit dem Oszi gemessen).
Hast du das gegen das Timing im Datenblatt kontrolliert?
Die Namen sind doch sehr gewöhnungsbedürftig:
spi_enable_chip();
spi_disable_chip(); // start transmission condition
Wenn was disbled ist, dann ist es inaktiv.
Oder andersrum: der Slave ist aktiv, wenn sein low aktiver SS# Eingang 
low ist...

> MOSI, SCK, CS passen soweit (mit dem Oszi gemessen).
Zeig doch mal...

> ich bekomme leider keine Antwort (DOUT) vom oben genannten Chip.
Die MISO Leitung ist also komplett ruhig?

BTW: welches Register willst du denn da auslesen? Ich würde mit dem 
Versionsregister anfangen...

von Jan H. (janiiix3)


Lesenswert?

Ich kann aktuell leider kein Foto machen.

Ja, ist vielleicht wirklich ein bisschen Irreführend. Passt aber. Er 
wechselst von High --> Low und zum Schluss wieder auf High.

Das Timing, habe ich noch nicht in Betracht gezogen, dass sollte doch 
wohl für das auslesen des ID Register okay sein.

Übrigens versuche ich das ID Register zu lesen (0x05) und die 
Entsprechenden Bits werden dafür auch gesetzt (hoffe ich doch mal das 
dass so richtig ist laut Datenblatt)

Sch*** KommunikationsRegister...

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


Lesenswert?

Jan H. schrieb:
> Das Timing, habe ich noch nicht in Betracht gezogen
Aber auf Bitebene (Position Pegelwechsel von MOSI und SCLK) schon, oder?

von Jan H. (janiiix3)


Lesenswert?

Lothar M. schrieb:
> Jan H. schrieb:
>> Das Timing, habe ich noch nicht in Betracht gezogen
> Aber auf Bitebene (Position Pegelwechsel von MOSI und SCLK) schon, oder?

Wie genau meinst du das jetzt???
Also die Pegel sind vorhanden MOSI, SCLK, CS
Habe auch zwischen CS mal ein delay gepackt, verschiedene SPI Modes 
getestet. Vom Chip keine Reaktion auf MISO...

von Jan H. (janiiix3)


Lesenswert?

Achja,

Wenn ich die Leitungen "MOSI - MISO" Verbinde, bekomme ich auch die 
Daten die ich sende.

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


Lesenswert?

Jan H. schrieb:
> Wenn ich die Leitungen "MOSI - MISO" Verbinde, bekomme ich auch die
> Daten die ich sende.
Das ist klar, da hat der Empfänger den gleichen SPI Mode wie der 
Sender...

>> Aber auf Bitebene (Position Pegelwechsel von MOSI und SCLK) schon, oder?
> Wie genau meinst du das jetzt???
> Also die Pegel sind vorhanden MOSI, SCLK, CS
Mir geht es nicht um die Pegel sondern darum, wann die Pegel wechseln. 
Oder mit anderen Worten: den SPI Mode.  Hast du den ausgewählt, der zum 
Timing m Datenblatt passt?

von Arc N. (arc)


Lesenswert?

Jan H. schrieb:
> hat jemand eine Idee???

Zwei Sachen: Zum einen benötigt das Teil ein "Delay between consecutive 
read/write operations" in Abhängigkeit des Power Modes zw. 3/MCLK ns bis 
12/MCLK ns. Dazu nach dem Aufwachen aus dem Standby 130 MCLK-Zyklen.
Zum anderen, siehe Abschnitt Digital Communication, ist der Ablauf dort 
etwas anders als im Programm:
1
Ist:
2
    /CS = Low;
3
    SPDR = registerAddr; WaitForSPI();
4
    SPDR = dummyValue; WaitForSPI();
5
    WaitForSPIF(); result = SPDR;
6
    /CS = High;
7
Soll:
8
    /CS = Low
9
    SPDR = registerAddr; WaitForSPI(); dummyResult = SPDR;
10
    SPDR = dummyValue; WaitForSPI(); result = SPDR;
11
    /CS = High;
Vollständiger:
https://github.com/analogdevicesinc/no-OS/tree/master/drivers/ad7124

von Jan H. (janiiix3)


Lesenswert?

Wo genau ist in meinem Programm waitforSPI(); ?
Meinst du damit das Empfangen?

von Jan H. (janiiix3)


Lesenswert?

Hier mal mein aktueller Stand.
Ich habe auch schon den Prescaler sehr weit runter gesetzt, aktuell bin 
ich bei 16MHZ / 128...
1
uint8_t AD7124_read_uint8(uint8_t reg)
2
{
3
  uint8_t temp = 0;
4
  
5
  /* build command */
6
  unsigned char buffer[1] = {0};
7
  buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg);
8
  
9
  spi_enable_chip();  // \CS High
10
  spi_disable_chip(); // \CS Low  -> start transmission condition
11
  
12
  spi_master_transmit(buffer[0]);      // register address
13
  temp = (uint8_t)spi_receive(); // dummy result
14
  
15
  _delay_ms(10);  
16
  
17
  spi_master_transmit(0x00); // dummy byte
18
  temp = (uint8_t)spi_receive(); // dummy result
19
20
  
21
  spi_enable_chip(); // stop transmission condition
22
  
23
  return (uint8_t)temp;
24
}

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


Lesenswert?

Jan H. schrieb:
> Hier mal mein aktueller Stand.
Liest du auch die Fragen? Und suchst Antworten darauf?
Hast du schon mal das Timing deines SPI-Interfaces gegen das Datenblatt 
kontrolliert? Und zwar Bit für Bit? Klar is das Arbeit, aber dieses 
blinde Herumgestochere hier bringt dich auch nicht weiter...

Jan H. schrieb:
> Wo genau ist in meinem Programm waitforSPI(); ?
Das da ist es:   while(!(SPSR & (1<<SPIF)));

> Meinst du damit das Empfangen?
SPI sendet und empfängt gleichzeitig. Um etwas zu empfangen muss etwas 
gesendet werden. Nach dem Senden ist auch der Empfang fertig...
Insofern könnte man diese Routine universeller machen:
1
uint8_t  spi_master_transmit_and_receive(uint8_t cData)
2
{
3
  /* start transmission */
4
  SPDR = cData;
5
  
6
  /* wait for transmission complete */
7
  while(!(SPSR & (1<<SPIF)));  
8
9
  /* return data register */
10
  return SPDR;  
11
}

von Jan H. (janiiix3)


Lesenswert?

Morgen,

nein das habe ich leider noch nicht gemacht. Werde ich gleich mal 
messen.
Du meinst sicherlich vom ersten Pegelwechsel zum nächsten (erste 
steigende Flanke bis zur nächsten steigenden Flanke).


\CS   -> Pulsdauer = 2,2µS (454KhZ), Bis nächste Flanke = 134µS 
(7,440KHz)
\SCLK -> Pulsdauer = 4,0µS (250KhZ), Bis nächste Flanke = 8µS   (125KHZ)

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


Lesenswert?

Jan H. schrieb:
> Du meinst sicherlich vom ersten Pegelwechsel zum nächsten (erste
> steigende Flanke bis zur nächsten steigenden Flanke).
Ich meine, dass du das Timingdiagramm im Datenblatt mit allen seinen 
Zeiten und Bezügen kontrollieren und einhalten musst. Denn im Datenblatt 
steht, wie man diesen Chip ansteuert. Und DU musst sicherstellen, dass 
du diese Parameter einhältst.
Dort auf den Seiten 11 und 12 findet sich das Timing auf Hardware- und 
Bitebene:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7124-4.pdf
Und auf den Seiten 38 und 50 findet sich die Kommunikation auf der 
Protokollebene...

von Jan H. (janiiix3)


Lesenswert?

Hallo,

kann es sein, dass ich einen großen Fehler gemacht habe und den Chip 
(was das Digitalteil angeht) mit 5V Pegeln bedient habe? Kann ich 
dadurch das Digitalteil toasten?
Der Chip arbeitet mit 3,3V...?!

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


Lesenswert?

Jan H. schrieb:
> Kann ich dadurch das Digitalteil toasten?
Kann sein, ist aber tendenziell eher unwahrscheinlich...

von Jan H. (janiiix3)


Lesenswert?

Ich habe einen anderen AD Wandler der annähernd das gleiche 
Kommunikationsprotokoll aufweist, dort funktioniert MISO...
Komisch...

von Thomas Rollmann (Gast)


Lesenswert?

Moin zusammen,
ich studiere gerade das Datenblatt.
Da steht geschrieben: "wenn sie etwas lesen möchten, müssen sie zuerst 
ein register beschreiben".
Nur mal so als Anregung, ich mache nur die Hardware, nicht das Programm.

Im übrigen bin ich ziemlich sicher, dass der ADC mit 5V "getoastet" 
wird, sofern diese zwischen AVDD und AVSS anliegen (vgl. "absolute 
maximum ratings)

Viel Erfolg!

von Jan H. (janiiix3)


Lesenswert?

Hallo Thomas,

wo steht das denn?

von Jan H. (janiiix3)


Lesenswert?

Hat denn keiner einer Idee?

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.