Forum: Mikrocontroller und Digitale Elektronik Raspberry SPI Empfang Problem


von Tomas Schmidt (Gast)


Lesenswert?

Hallo Welt,

ich teste gerade das SPI Interface des Raspberry Pi 3 Model B. Dabei ist 
an den GPIO's und am SPI Interface nichts angeschlossen. Das Senden von 
Daten funktioniert (mit nem Scope gemessen), allerdings empfange ich 
immer die Daten, die ich auch versendet habe. Auch wenn ich den MISO Pin 
mit z.B. dem SCK Pin kurzschließe, "empfange" ich immer die Nachricht, 
die ich auch versendet habe.

Hat jemand einen Rat? Vielen Dank!
1
#include <stdio.h>
2
#include <fcntl.h>
3
#include <sys/ioctl.h>
4
#include <linux/spi/spidev.h>
5
#include <inttypes.h>
6
#include <stdlib.h>
7
#include <wiringPiSPI.h>
8
9
int main()
10
{
11
  unsigned char* buffer = "Hallo Welt!!!\n";
12
  int i =0;
13
  if(wiringPiSPISetup(1, 500000)==-1)
14
  {
15
    printf("Could not initialise SPI\n");
16
    return 0;
17
  }
18
  while(1)
19
  {
20
    wiringPiSPIDataRW(1, buffer, 8);
21
    printf("Data send %i, %s\n", i++, buffer);
22
  }
23
  
24
  return 0;
25
}

von WiringPiSPI (Gast)


Lesenswert?

Hi,

Gordon hat vor dem ioctl-Aufruf so programmiert:
...
 memset (&spi, 0, sizeof (spi)) ;
 spi.tx_buf        = (unsigned long)data ;
 spi.rx_buf        = (unsigned long)data ;
 spi.len           = len ;
...

Das erklärt, wieso Du das "empfangen" kannst, was Du gesendet hast, wenn 
Du nichts empfängst :-)

von Tomas Schmidt (Gast)


Lesenswert?

Hallo WiringPiSPI,

danke für deine Antwort! Ich bin aber noch nicht auf die Lösung des 
Problems gekommen. Ich habe die Funktion für Debugzwecke erweitert:
1
int wiringPiSPIDataRW (int channel, unsigned char *data, int len)
2
{
3
  int ret,i;
4
  struct spi_ioc_transfer spi ;
5
6
  channel &= 1 ;
7
8
// Mentioned in spidev.h but not used in the original kernel documentation
9
//  test program )-:
10
11
  memset (&spi, 0, sizeof (spi)) ;
12
13
  spi.tx_buf        = (unsigned long)data ;
14
  spi.rx_buf        = (unsigned long)data ;
15
  spi.len           = len ;
16
  spi.delay_usecs   = spiDelay ;
17
  spi.speed_hz      = spiSpeeds [channel] ;
18
  spi.bits_per_word = spiBPW ;
19
  ret = ioctl (spiFds [channel], SPI_IOC_MESSAGE(1), &spi) ;
20
  for(i=0;i<12;i++)
21
  printf("%x ", ((char*)spi.tx_buf)[i]);
22
  for(i=0;i<12;i++)
23
  printf("%x ", ((char*)spi.rx_buf)[i]);
24
  return ret;
25
}

Die Ausgabe der einzelnen Bytes enthält jeweils die abgesendete 
Nachricht.

Ich kenn mich mit der ioctl Funktion nicht so aus, kann es sein, dass 
sie nur den Prozess startet und ich die Antwort irgendwie per Interrupt 
erhalte?

Danke und viele Grüße

von WiringPiSPI (Gast)


Lesenswert?

Hi,

der Hinweis auf die Implementierung von wiringPiSPIDataRW sollte nur 
erklären, wieso man die gesendeten Daten wieder empfangen kann.

Die Debug Ausgabe hat aber nicht geschadet :-)

>Ich kenn mich mit der ioctl Funktion nicht so aus, kann es sein, dass
>sie nur den Prozess startet und ich die Antwort irgendwie per Interrupt
>erhalte?

Nein, denn wenn alles gut geht liefert die Funktion wiringPiSPIDataRW 
die empfangenen Daten in dem Bereich, auf den der 2. Parameter zeigt und 
der ioctl-Aufruf steht ja im return Befehl:

return ioctl (spiFds [channel], SPI_IOC_MESSAGE(1), &spi) ;


Ich denke, ich steck nachher mal was zusammen und teste auch mal. Kann 
aber etwas dauern :-)

Viele Grüße

von Tomas Schmidt (Gast)


Lesenswert?

Die ioctl Funktion innerhalb der wiringPiSPIDataRW Funktion gibt -1 
zurück. Das Setup Funktioniert: fd=3.

Mich wundert ja, dass das Senden funktioniert. Leider empfange ich aber 
immer noch nichts und ich weiß nicht weiter... :-/

von WiringPiSPI (Gast)


Lesenswert?

Hi,

hol Dir spidev_test.c.

https://github.com/torvalds/linux/blob/master/tools/spi/spidev_test.c

Ein Test ohne und dann mit Verbindung zwischen MOSI und MISO sieht damit 
so aus:

pi@spipi:~/spitest $ sudo ./spidev_test -v -p "1234"    -D 
/dev/spidev0.1
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)
TX | 31 32 33 34 _ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _ 
_ __ __ __ __ __ __ __ __ _  | 1234
RX | 00 00 00 00 _ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _ 
_ __ __ __ __ __ __ __ __ _  | ....
pi@spipi:~/spitest $ sudo ./spidev_test -v -p "1234"    -D 
/dev/spidev0.1
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)
TX | 31 32 33 34 _ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _ 
_ __ __ __ __ __ __ __ __ _  | 1234
RX | 31 32 33 34 _ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _ 
_ __ __ __ __ __ __ __ __ _  | 1234

Viel Erfolg!

von WiringPiSPI (Gast)


Lesenswert?

Na,weiter gekommen?

spidev_test.c sollte bei Dir auch funktionieren. Wenn nicht stimmt was 
am Raspi nicht.

Dein Testprogramm wird aber trotzdem nicht so laufen, wie Du denkst.

In wiringPiSPIDataRW sieht man ja, wie der Puffer verwendet wird. Du 
hast aber keinen Zeiger auf einen Puffer übergeben, sondern einen Zeiger 
auf eine Stringkonstante.

Ändere mal Dein Testprogramm so ab:

int main()
{
//  unsigned char* buffer = "Hallo Welt!!!\n";
 unsigned char buffer [32];
 int i =0;
  if(wiringPiSPISetup(1, 500000)==-1)
  {
    printf("Could not initialise SPI\n");
    return 0;
  }
  while(1)
  {
    strcpy(buffer,  "Hallo Welt!!!\n");
    wiringPiSPIDataRW(1, buffer, 8);
    printf("Data send %i, %s\n", i++, buffer);
  }

  return 0;
}

Dann teste mit offenen MOSI und MISO Ports und mit kurzgeschlossenen.

Dann oder spätestens wenn Du zusätzlich noch mit

    wiringPiSPIDataRW(1, buffer, 1);

testest, also in jedem Durchlauf nur 1 Byte per SPI raus- bzw. raus- und 
reinschiebst, sollte alles klar sein.

von Tomas Schmidt (Gast)


Lesenswert?

Hallo WiringPiSPI,

vielen Dank für deine Unterstützung! Beide Programme laufen jetzt. Der 
Fehler war der Zeiger auf die Stringkonstante.

Viele Grüße und danke nochmal!

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.