Collegare dispositivi SPI

Da raspibo.
Jump to navigation Jump to search

SPI e' un bus seriale a (almeno) tre fili: clock, MISO (master input, slave output), MOSI (master output, slave input). "Almeno" perche' se volete collegare piu' unita' al bus occorre un filo di "abilitazione" per ogni unita'.

Raspberry PI ha il supporto sul pettine di contatti per funzionare come master con due unita' SPI collegate.

I fili da usare sono:

  • Pin 19/GPIO 10/SPI_MOSI
  • Pin 21/GPIO 9/SPI_MISO
  • Pin 23/GPIO 11/SPI_CLK
  • Pin 24/GPIO 8/SPI enable 0
  • Pin 26/GPIO 7/SPI enable 1

Usando questi fili si puo' usare il driver del kernel altrimenti e' possibile usare altri fili e gestire l'intero protocollo SPI via software (il cosiddetto bit banging).

Qui verrà descritto il funzionamento con il driver del kernel. Un esempio che usa bit banging si puo' trovare in questa spiegazione di Adafruit

Per poter usare il supporto del kernel per SPI occorre caricare il relativo modulo:

# modprobe spi_bcm2708

Compariranno (udev-magicamente) i due device /dev/spidev0.0 e /dev/spidev0.1, che corrispondono rispettivamente alle unita' che avrete collegato usando il pin 24 o il pin 26 per enable.

Per provare il funzionamento di SPI potete caricare dalla documentazione ufficiale del kernel linux il file spidev_test.c. Compilatelo:

gcc -o spidev_test spidev_test.c

e eseguitelo (come root).

# ./spidev_test -D /dev/spidev0.0
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)

00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 

Vengono visualizzati i dati ricevuti, nessuno in questo momento perche' MISO e' scollegato. Provate ora a collegare MISO con MOSI (il pin 19 col pin 21, in altre parole GPIO 10 con GPIO 9). In questo modo SPI legge i dati che spedisce. Infatti se si esegue nuovamente il programma:

# ./spidev_test ./spidev_test -D /dev/spidev0.0
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)

FF FF FF FF FF FF 
40 00 00 00 00 95 
FF FF FF FF FF FF 
FF FF FF FF FF FF 
FF FF FF FF FF FF 
DE AD BE EF BA AD 
F0 0D 

viene letto il vettore di byte spedito. (l'autore deve esseree vegetariano come me: dead beef baad f00d!).

Uso di SPI in C

Il programma spidev_test.c e' anche un ottimo esempio per imparare a dialogare con i dispositivi SPI usando il linguaggio C.

Il device SPI viene aperto come un normale file e ha ioctl specifici per settare i parametri del bus quali la velocita' e i bit per voce, e per la comunicazione.

In SPI si riceve lo stesso numero di byte inviati, Di fatto si invia un messaggio con una parte dummy nelle posizioni dove l'unita' mettera' la sua risposta. Nel messaggio ricevuto si leggeranno solo i byte significativi.

Per il dialogo con un device si usa la ioctl chiamata SPI_IOC_MESSAGE che vuole come parametro una (o piu') strutture spi_ioc_transfer. per esempio:

        int ret;
        uint8_t tx[]={1, 0x80, 0};
        uint8_t rx[]={1,0,0};
        struct spi_ioc_transfer tr = {
                .tx_buf = (unsigned long)tx,
                .rx_buf = (unsigned long)rx,
                .len = ARRAY_SIZE(tx),
                .delay_usecs = delay,
                .speed_hz = speed,
                .bits_per_word = bits,
        };
        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
        if (ret < 1) {
                perror("can't send spi message");
                abort();
        }
        /* la risposta del dispositivo e' in tr.rx_buf */

La lunghezza dei vettori tx e rx e i valori da passare dipendono dai dispositivi collegati.

Uso di SPI in Python

Il modo piu' comodo per usare SPI e' avvalersi della libreria py-spidev (che purtroppo per ora esiste solo per Python 2 e non e' ancora stata portata a Python 3).

Per installare py-spidev occorre git (se non l'avete sudo apt-get install git)

git clone git://github.com/doceme/py-spidev
cd py-spidev/
sudo python setup.py install

L'uso con py-spidev e' molto semplice:

import spidev
spidevice = spidev.SpiDev(0,0)

ret=spidevice.xfer2([1,0x80,0])
# ret e' la lista che contiene la risposta del dispositivo.