Comment configurer un réseau point à point de type SPI ?

NIVEAU 2

Objectifs

  • Comprendre le protocole SPI
  • Visualiser les différents signaux nécessaires à la transmission d’une information

Pré-requis

Protocole SPI

Transmission maître/esclave

Le protocole de communication SPI (Serial Peripheral Interface, développé par Motorola) permet d’établir une liaison de transmission de données série synchrone entre un maître et plusieurs esclaves. La liaison se fait à l’aide de 4 fils (voir schéma suivant – vu du maître) :

  • SCK : signal d’horloge, imposé par le maître
  • MOSI / SDO : données sortant du maître
  • MISO / SDI : données reçues par le maître
  • SS / CS : signal de sélection de l’esclave – cette ligne est spécifique à chaque esclave

Ce protocole est souvent utilisé dans les systèmes embarqués pour faire communiquer de manière numérique des capteurs ou des organes de ce système entre eux sous la forme d’un réseau. Ce réseau a pour avantages d’être rapide (car synchrone) et facile à mettre en oeuvre. Il permet de transmettre des informations binaires sous forme de paquet (souvent 1 octet à chaque fois) en Full-Duplex.

L’inconvénient majeur de ce protocole de communication vient de sa nécessité à avoir un fil de sélection par esclaves à adresser indépendamment. Il existe d’autres protocoles de communication où la sélection de l’esclave se fait par adressage dans le message transmis (voir tutoriel Configurer un réseau adressable I2C).

N.B. MOSI = Master Out Slave In, MISO = Master In Slave Out, SDI = Serial Data In, SDO = Serial Data Out

Principe de transmission

Le signal SCK est un signal d’horloge imposé par le maître (souvent le microcontroleur).
Le signal MOSI permet au maître de transmettre une information numérique (commande ou donnée) à l’esclave.
Le signal MISO permet au maître de recevoir une donnée depuis l’esclave.

Par défaut, la ligne de transmission est au repos et le signal SS de chacun des esclaves est au niveau logique ‘1’, signifiant qu’aucune communication n’est en cours.

Lorsque l’on souhaite démarrer une communication, il faut alors passer le signal de sélection (SS) d’un (ou plusieurs) esclave(s) à ‘0’ pour leur signaler le début d’une transmission. La communication est ensuite rythmée par une horloge (SCK). Les données sont souvent transmises par paquet de 8 bits (ou un octet) entre le maître et l’esclave sur la ligne SDO vu du maître, connectée à SDI sur l’esclave.
Lorsque la transmission est terminée, le signal SS de chacun des esclaves repasse à ‘1’.

Lorsque la communication nécessite une réponse de l’esclave, il est alors nécessaire de transmettre depuis le maître une donnée “inutile” (souvent que des ‘1’) qui ne servira qu’à générer le signal d’horloge sur SCK pour rythmer la réponse de l’esclave. Cette transmission se fait alors par la ligne SDO de l’esclave, reliée sur l’entrée SDI (ou MISO) du maître.

Modes de transmission

Selon le périphérique utilisé, il peut exister 4 modes de communication en SPI (voir schéma ci-dessous).

SPI sous MBED

Connexion SPI sur la carte Nucleo L476RG

Les broches de connexion de la liaison SPI sur la carte Nucleo L476RG sont les suivantes :

  • SCK : broche D13 / configurée en sortie
  • MISO : broche D12 / configurée en sortie
  • MOSI : broche D11 / configurée en entrée
  • CS : broche D8 / configurée en sortie

Toutes les broches ne peuvent pas être reliées au module SPI du microcontroleur. Il faut se référer au brochage de la carte Nucléo et vérifier que les broches portent un nom de type SPI_xxx.

Configuration du mode SPI de la carte Nucleo L476RG

L’ensemble des classes et des fonctions permettant de réaliser des opérations avec les modules du microcontroleur se trouvent dans la bibliothèque “mbed.h (ou “mbed-os.h”). Il est donc indispensable d’avoir au préalable inclut cette bibliothèque :

#include "mbed.h"

Déclaration des entrées/sorties

La première étape est la déclaration des broches utilisées pour la liaison SPI. Il faut la placer après la déclaration des ressources externes (bibliothèques) et avant toute définition de fonction (voir tutoriel Tester ma première application sur Nucléo – Code d’exemple /* Déclaration des entrées/sorties */).

SPI spi(D11,D12,D13); // mosi, miso, sck
DigitalOut CS(D8);

Dans un premier temps, on déclare, à l’aide du constructeur de la classe SPI, le nom de la liaison dans le reste du programme (ici la variable spi) et les broches MOSI, MISO et SCK à utiliser sur la carte.
Pour chacun des périphériques associés à cette liaison, il faudra ensuite ajouter une sortie numérique standard (ici la broche D8, nommée CS dans le reste du code).

Paramétrage de la liaison SPI

Avec le compilateur MBED, il est possible de changer les paramètres suivants :

  • la fréquence de transmission
  • le mode de transmission
  • le nombre de bits transmis par paquet

Pour cela, il faut utiliser les fonctions suivantes de la classe SPI :

spi.format(8,3);          
spi.frequency(10000);

La fonction format() prend deux paramètres : le nombre de bits par paquet transmis et le mode de transmission (entre 0 et 3).
La fonction frequency() permet de régler la fréquence en Hertz de l’horloge.

Attention : Le composant SPI esclave doit être capable de recevoir les données à la fréquence d’horloge imposée, c’est souvent lui qui est limitant !

Envoi d’une donnée sur la liaison SPI

Pour pouvoir ensuite demander à la carte Nucléo de transmettre une donnée sur la liaison SPI, il faut utiliser la fonction write de la classe SPI.

Cette fonction attend un paramètre qui est la donnée à envoyer. Elle dépend du format que vous avez spécifié dans la fonction format() : 1 octet si vous êtes sur 8 bits, 2 octets si vous êtes sur 16 bits…

Dans l’exemple suivant, on transmet la valeur 0x0300 par exemple sur 16 bits.

spi.write(0x0300);

Exemple de transmission

Voici un exemple permettant de tester une liaison SPI (sans esclave).

#include "mbed.h"

SPI spi(D11,D12,D13); // mosi, miso, sclk
DigitalOut CS(D8);

int main(){
    int i;
    CS = 1;
    spi.format(8,3);          // Setup the spi for 8 bit data, high steady state clock,
    spi.frequency(10000);     // second edge capture, with a 1kHz clock rate
    wait_ms(10);

    while(1){
        for(i = 0; i < 100; i++){
            CS = 0;
            spi.write(i);
            CS = 1;
            wait_ms(200);
        }
    }
}    

Dans cet exemple, on utilise la fonction write associée à la classe SPI pour transmettre un octet toutes les 200 ms.

Tutoriel lié

MInE Prototyper Prototyper avec Nucleo et MBED

Nucléo – Configurer un réseau point à point de type SPI