SPI Slave 16 Bit empfangen

OP #3538175
Lesenswert?

Hallo!

Ich arbeite gerade an einem Projekt und versuche, die Daten von einem 16 
Bit AD-Wandler (AD977) über SPI einzulesen.
Mein Microcontroller (ATMega328) ist der Slave und der AD-Wandler ist 
der Master.

Der AD-Wandler sendet mir die passenden Daten, und ich werte sie 
folgendermaßen aus:
1
int i = 0;
2
word bData=0x00;
3
byte nData = 0x00;
4

5
void setup_spi()
6
{
7
  SPCR  &=~ (1<<SPIE);  //Interrupt ausschalten
8
  SPCR  |=  (1<<SPE);  //SPI einschalten
9
  SPCR  &=~  (1<<DORD);  //MSB zuerst
10
  SPCR &=~  (1<< MSTR); //SPI als Slave
11

12
  SPCR  &=~ (1<<CPOL);  //Clock Polarität
13
  SPCR  &=~ (1<<CPHA);  //Clock Phase
14

15
  DDRB|=0x01; //RC 8
16
  DDRB&=~0x04; //SS 10 (BUSY bei ADC)
17
  DDRB&=~0x08; //MOSI Eingang 11
18
  DDRB |=0x10; //MISO 12, Ausgang !!!!
19
  DDRB&=~0x20;//Clock 13
20
}
21

22
void adc()
23
{
24
  //PORTB |= 0x01;
25
  delayMicroseconds(100);
26
  PORTB &=~ 0x01;
27
  int i =0;
28
  while(i<100) i++;
29
  PORTB |= 0x01;
30
  
31
  //erste 8 Bit
32
  while(!(SPSR & (1<<SPIF)));
33
  bData = SPDR <<8; 
34
   
35
   
36
   //zweite 8 Bit
37
  while(!(SPSR & (1<<SPIF)));
38
  bData=SPDR;
39

40
  //Serial.println(bData);
41
  //Serial.print("          ");
42
  //Serial.print(nData);
43

44
}
Seit dem ich aber die zweite Übertragung hinzugefügt habe, also die 
zweite while-Schleife, funktioniert das Programm nicht mehr.
Weiß jemand, woran das liegen könnte?

Liebe Grüße
Alina
Gast #3538436
Lesenswert?

Karl Heinz schrieb:
> Was heißt 'funktioniert nicht mehr'.
>   while(!(SPSR & (1<<SPIF)));
>   bData = SPDR <<8;
>
>
>    //zweite 8 Bit
>   while(!(SPSR & (1<<SPIF)));
>   bData=SPDR;
>
> die letzte Zeile muss  bData |= SPDR;
> lauten.


Funktioniert nicht mehr heißt, das der AD-Wandler dann überhaupt keine 
Daten mehr sendet.

Oh okay danke.
Gast #3539597
Lesenswert?

Hi

>Habe es so versucht, aber leider funktioniert es immer noch nicht..

Schon mal das Datenblatt gelesen? Bei AVRs werden Interruptflags meist 
durch Schreiben einer 1 gelöscht. Das Datenblatt sagt zu SPIF:

Bit 7 – SPIF: SPI Interrupt Flag

When a serial transfer is complete, the SPIF Flag is set. An interrupt 
is generated if SPIE in SPCR is set and global
interrupts are enabled. If SS is an input and is driven low when the SPI 
is in Master mode, this will also set the SPIF
Flag. SPIF is cleared by hardware when executing the corresponding 
interrupt handling vector. Alternatively, the
SPIF bit is cleared by first reading the SPI Status Register with SPIF 
set, then accessing the SPI Data Register
(SPDR).

MfG Spess
#3539602
Lesenswert?

>     SPSR&=~(1<<SPIF);

Das kann schon mal nicht funktionieren, weil das hier ein Interrupt-Flag 
ist, welches durch einschreiben einer 1 gelöscht wird.
Aber im Grunde braucht das auch keiner. Lies dir mal die Beschreibung 
durch, wie dieses Flag wieder automatisch gelöscht wird. Durch die 
Kombination aus Zugriff auf das SPSR Register und Zugriff auf SPDR 
löscht die Hardware dieses Flag ganz von alleine.

Ich denke man sollte jetzt mal eines klären:
Liegt das Problem auf AVR Seite oder liegt es auf AD977 Seite.
Wie taktest du die Übertragung? Den Takt würde ich mal verlangsamen und 
mir ansehen, ob aus dem AD977 überhaupt 16 Bit rausgetaktet werden oder 
nicht. Den Takt mach ich deswegen langsamer, damit ich mit meinen 
beschränkten Messmöglichkeiten (im großen und ganzen eine popelige LED) 
was feststellen kann. Ein Logikanalysator wäre eleganter, aber sowas hab 
ich nicht.

Ich denke, das wäre jetzt mal meine erste Untersuchung: Taktet der AD 
überhaupt 16 Bit raus: ja oder nein.
OP #3539620
Lesenswert?

Karl Heinz schrieb:
> Das kann schon mal nicht funktionieren, weil das hier ein Interrupt-Flag
> ist, welches durch einschreiben einer 1 gelöscht wird.
> Aber im Grunde braucht das auch keiner. Lies dir mal die Beschreibung
> durch, wie dieses Flag wieder automatisch gelöscht wird. Durch die
> Kombination aus Zugriff auf das SPSR Register und Zugriff auf SPDR
> löscht die Hardware dieses Flag ganz von alleine.
>
> Ich denke man sollte jetzt mal eines klären:
> Liegt das Problem auf AVR Seite oder liegt es auf AD977 Seite.
> Wie taktest du die Übertragung? Den Takt würde ich mal verlangsamen und
> mir ansehen, ob aus dem AD977 überhaupt 16 Bit rausgetaktet werden oder
> nicht. Den Takt mach ich deswegen langsamer, damit ich mit meinen
> beschränkten Messmöglichkeiten (im großen und ganzen eine popelige LED)
> was feststellen kann. Ein Logikanalysator wäre eleganter, aber sowas hab
> ich nicht.
>
> Ich denke, das wäre jetzt mal meine erste Untersuchung: Taktet der AD
> überhaupt 16 Bit raus: ja oder nein.

Danke für deine Antwort.
Beim AD-Wandler funktioniert alles einwandfrei, wie im Timing Diagramm, 
dass habe ich mit dem Oszilloskop gemessen.

> Durch die
> Kombination aus Zugriff auf das SPSR Register und Zugriff auf SPDR
> löscht die Hardware dieses Flag ganz von alleine.

Das steht ja im Datenblatt:
Alternatively, the SPIF bit is cleared by first reading the
SPI Status Register with SPIF set, then accessing the SPI Data Register 
(SPDR).

Weißt du, wie ich dass dann softwaremäßig lösen müsste?

Liebe Grüße
#3539632
Lesenswert?

Alina Koch schrieb:

> Alternatively, the SPIF bit is cleared by first reading the
> SPI Status Register with SPIF set, then accessing the SPI Data Register
> (SPDR).
>
> Weißt du, wie ich dass dann softwaremäßig lösen müsste?

Schaun wir mal.
Das hier
1
  while(!(SPSR & (1<<SPIF)));
2
  bData = SPDR <<8;
ist dein Code.

Was steht im Datenblatt
* the SPIF bit is cleared by first reading the SPI Status Register with 
SPIF set

Also. SPIF muss im SPSR gesetzt sein.
Die while Schleife
1
  while(!(SPSR & (1<<SPIF)));
wird nur dann verlassen, wenn genau das der Fall ist. SPIF ist gesetzt

Was steht weiter im Datenblatt
* then accessing the SPI Data Register (SPDR).

Wie gehts in deinem Code weiter
1
  bData = SPDR <<8;
ich würde sagen, das qualifiziert 100%-ig als 'accessing'.

Fazit: Beide Voraussetzungen erfüllt. -> die Hardware löscht das Flag -> 
du brauchst gar nichts tun.



>
> Liebe Grüße

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