Forum: Mikrocontroller und Digitale Elektronik SPI Slave 16 Bit empfangen


von Alina K. (alinakoch)


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

von spess53 (Gast)


Lesenswert?

Hi

>Weiß jemand, woran das liegen könnte?

Ich würde mal auf SPIF tippen.

MfG Spess

von Florian (Gast)


Lesenswert?

Sendest Du denn 2 Bytes aus? Ev. wartet sich Deine while - Schleife zu 
Tode weil gar nix mehr kommt?

von Karl H. (kbuchegg)


Lesenswert?

Was heißt 'funktioniert nicht mehr'.
1
  while(!(SPSR & (1<<SPIF)));
2
  bData = SPDR <<8; 
3
   
4
   
5
   //zweite 8 Bit
6
  while(!(SPSR & (1<<SPIF)));
7
  bData=SPDR;

die letzte Zeile muss
1
  bData |= SPDR;
lauten.

von Alina Koch (Gast)


Lesenswert?

Müsste ich dann vor der zweiten while-Schleife das SPIF zurücksetzen? 
Mit SPSR &=~(1<<SPIF)?

von Alina Koch (Gast)


Lesenswert?

spess53 schrieb:
> Ich würde mal auf SPIF tippen.
>
> MfG Spess

Müsste ich dann vor der zweiten while-Schleife das SPIF zurücksetzen?
Mit SPSR &=~(1<<SPIF)?

LG

von Alina Koch (Gast)


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.

von Alina K. (alinakoch)


Lesenswert?

Florian schrieb:
> Sendest Du denn 2 Bytes aus? Ev. wartet sich Deine while - Schleife zu
> Tode weil gar nix mehr kommt?

Die Übertragung wird mit dem Setzen des RC-Pins gestartet:
1
delayMicroseconds(100);
2
PORTB &=~ 0x01;
3
int i =0;
4
while(i<100) i++;
5
PORTB |= 0x01;

Wenn ich davor Bytes aussende ändert sich leider auch nichts...

von Alina K. (alinakoch)


Lesenswert?

Alina Koch schrieb:
>> Ich würde mal auf SPIF tippen.
>>
>> MfG Spess

1
//erste 8 Bit
2
  while(!(SPSR & (1<<SPIF)));
3
4
  bData = SPDR;
5
    SPSR&=~(1<<SPIF);
6
7
  SPDR=0x00;
8
  
9
  //zweite 8 Bit
10
  while(!(SPSR & (1<<SPIF)));
11
  nData=SPDR;

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

von spess53 (Gast)


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

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Alina K. (alinakoch)


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

von Karl H. (kbuchegg)


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

von Alina K. (alinakoch)


Lesenswert?

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

Ja das stimmt, aber trotzdem funktioniert es nicht :(
Ich danke dir trotzdem für deine schnelle Antwort.

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.