Forum: Mikrocontroller und Digitale Elektronik Empfangen über SPI von ADC-Daten


von Benedikt H. (benni_1)


Lesenswert?

Hallo,
ich habe folgendes Problem:
Ich möchte mit einem ATmega128 von einem ADC (LTC2452) über SPI 
Messwerte einlesen.
Dabei verwende ich folgende Funktion zum empfangen eines Bytes:
1
uint8_t SPI_receive_byte()  // Byte empfangen
2
{
3
  SPDR = 0;    // Wert in Buffer speichern
4
  while(!(SPSR)&(1<<SPIF));
5
        // warten bis Zeichen verfügbar (Übertragung fertig)
6
  return SPDR;          // empfangenen Wert zurückgeben
7
}
Von dieser Funktion erhalte ich jedoch keinen Rückgabewert, laut 
Oszilloskop gibt der ADC aber Werte aus.
Laut Datenblatt müssen zwei Byte für eine vollständige Übertragung 
empfangen werden.
Vielen Dank im Vorraus

von holger (Gast)


Lesenswert?

>  while(!(SPSR)&(1<<SPIF));

  while(!(SPSR&(1<<SPIF)));

von Benedikt H. (benni_1)


Lesenswert?

Vielen Dank für die schnelle Antwort Holger!

Aber leider konnte ich das Problem dadurch nicht beheben.
Es kann doch nicht so schwer sein, als Master Daten über das SPI zu 
empfangen. (das Senden an DigiPots funktioniert ja auch)

Der ATmega scheint einfach keine Daten annehmen zu wollen. Hat irgendwer 
noch eine andere Idee?

von Frank (Gast)


Lesenswert?

Wie sieht die Konfiguration der SPI aus?
Polarität?
Mode?
CLK rate?
...

Richtig angeschlossen?
Schaltplan?
...

von Benedikt H. (benni_1)


Lesenswert?

Hallo Frank!

Ja, richtig angeschlossen, durchgepiepst und mit dem Oszilloskop auf 
beiden Seiten des Busses gemessen.
ATmega <-> ADC
SCK    -> SCK
Enable -> /CS
MISO   -> SDO (serial data out)
(MOSI gibt's nicht)
-----
Die CLK-Rate des ADC geht bis 2MHz und ist auf 1MHz eingestellt.
Polarität und Mode passt auch.
-----
hier etwas mehr Code:
1
void spiInit(void) //Datasheet pg. 162
2
{
3
4
  DDRB |= ((1<<PB5)|(1<<PB7));    // MOSI, SCK => Output
5
  DDRB &= ~(1<<PB6);              // MISO => Input
6
7
  DDRD |= ((1<<PC0));             //ADC SS-Pin => Output
8
9
  SPCR |= ((1<<SPE)|(1<<MSTR)|(1<<SPR0)); // SPI enable, Master, f/16 
10
  SPCR |= (1<<CPOL);      // CLK mit falling Edge beginnen
11
  SPCR |= (1<<CPHA);      // Sample auf Trailing-Edge
12
}
13
14
uint16_t SPI_receive_ADC()  
15
{
16
  cli();      // Interrupts deaktivieren
17
  PORTC |= (1<<PC0);  // ADC Enable aus
18
    PORTC &= ~(1<<PC0);  // Enable-Pin für ADC aktivieren
19
20
  uint16_t averageData = 0;    
21
  averageData = (SPI_receive_byte()<<8);
22
  averageData |= SPI_receive_byte();
23
24
  PORTC |= (1<<PC0);  // ADC Enable aus
25
  sei();      // Interrupts aktivieren
26
  return averageData;
27
}
28
29
uint8_t SPI_receive_byte()  // Byte empfangen
30
{
31
  SPDR = 0x00;            // Wert in Buffer schreiben
32
  while(!(SPSR&(1<<SPIF)));  // warten bis Übertragung fertig
33
  return SPDR;        // empfangenen Wert zurückgeben
34
}

von holger (Gast)


Lesenswert?

Setz PB0 (SS) mal auf Ausgang.

von Jim M. (turboj)


Lesenswert?

>  DDRD |= ((1<<PC0));

Sollte das nicht besser DDRC sein? Außerdem musst Du bei AVRs den NSS 
Pin als Ausgang schalten, sonst tut SPI Master Mode nicht richtig.

Edit: Mist, zu langsam. ;-)

: Bearbeitet durch User
von Benedikt H. (benni_1)


Lesenswert?

Zwar schon etwas spät für eine Antwort, aber falls es zufällig jemanden 
interessiert:
Offensichtlich hatte ich zu irgendeinem Zeitpunkt am ATmega den MISO Pin 
als Output gesetzt und HIGH drauf geschrieben. Gleichzeitig hat mein 
SPI-Slave ein LOW an seinem MISO Pin gesetzt.
Somit hatte ich einen Kurzschluss zwischen ATmega und Slave und der AVR 
hat zuerst schlapp gemacht. Als ich einen neuen Chip eingelötet habe hat 
wieder alles funktioniert.

Ich kann also nur jedem raten, den MISO Pin seines ATmegas mit einem 
100ohm Widerstand gegen Kurzschlüsse abzusichern..

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.