SPI und der A/D Wandler AD7124-4

OP #4667279
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???
Moderator (Firma: Titel) Persönliche Seite #4667308
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...
OP #4667317
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...
Moderator (Firma: Titel) Persönliche Seite #4667840
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?
#4667903
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
OP #4668172
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
}
Moderator (Firma: Titel) Persönliche Seite #4668193
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
}
OP #4668195
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)
Moderator (Firma: Titel) Persönliche Seite #4668211
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...
Gast #4681008
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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren