Afficher/cacher Sommaire
SPI - comunication entre Rasberry et Arduino
Exigences
- 1 Raspberry Pi avec la dernière version de Raspbian
- 1 Arduino
Raspberry Pi avec la dernière version de Raspbian . Pour vous assurer que votre système est à jour, veuillez télécharger et exécuter rpi-update .
Câblage
Config. Broches SPI d’Arduino Uno, Arduino Nano et Arduino Mega
_ | MOSI | MISO | SCK | SS |
---|---|---|---|---|
Arduino Uno | 11 | 12 | 13 | 10 |
Arduino Nano | 11 | 12 | 13 | 10 |
Arduino Mega | 51 | 50 | 52 | 53 |
Arduino
Le choix d’un Arduino fonctionnant à 3,3 v simplifiera vos projets Raspberry Pi Arduino en permettant une connexion directe entre les broches d’entrée et de sortie des deux appareils sans nécessiter de décalage de niveau pour aligner les tensions et protéger les entrées Raspi.
Ouvrez votre ide Arduino et flasher le code ci-dessous sur votre Arduino.
Code Arduino arduino_spi_slave.pde
// Written by Nick Gammon
// February 2011
/**
* Send arbitrary number of bits at whatever clock rate (tested at 500 KHZ and 500 HZ).
* This script will capture the SPI bytes, when a '\n' is recieved it will then output
* the captured byte stream via the serial.
*/
#include <SPI.h>
char buf [100];
volatile byte pos;
volatile boolean process_it;
void setup (void)
{
Serial.begin (115200); // debugging
// have to send on master in, *slave out*
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// get ready for an interrupt
pos = 0; // buffer empty
process_it = false;
// now turn on interrupts
SPI.attachInterrupt();
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR; // grab byte from SPI Data Register
// add to buffer if room
if (pos < sizeof buf)
{
buf [pos++] = c;
// example: newline means time to process buffer
if (c == '\n')
process_it = true;
} // end of room available
} // end of interrupt routine SPI_STC_vect
// main loop - wait for flag set in interrupt routine
void loop (void)
{
if (process_it)
{
buf [pos] = 0;
Serial.println (buf);
pos = 0;
process_it = false;
} // end of flag set
} // end of loop
Raspberry Pi
Activation de SPI sur le Raspberry Pi
SPI sur le Pi est désactivé par défaut. Avant de pouvoir utiliser SPI dans vos programmes, il doit être activé. Le moyen le plus simple consiste à utiliser l’utilitaire raspi-config que vous pouvez lancer en entrant:
sudo raspi-config
Dans les écrans résultants, sélectionnez Options avancées, puis sélectionnez SPI. Vous devez répondre oui aux deux questions pour activer l’interface SPI et charger le module de noyau SPI par défaut.
Redémarrez le Pi pour charger le module de noyau SPI. Vous pouvez vérifier que la modification est effective en entrant lsmod sur la ligne de commande pour générer une liste des modules chargés. Le module spi spi_bcm2708 doit apparaître dans les résultats.
Le Pi a un fichier “liste noire” qui bloque le chargement des modules: /etc/modprobe.d/raspi-blacklist.conf . La ligne #blacklist spi-bcm2708
doit commencer par le symbole dièse “#” qui “met en commentaire” la ligne. Sans le hachage, SPI est sur la liste noire et ne se charge pas.
Les paramètres de l’arborescence de périphériques dans le fichier /boot/config.txt
Recherchez une ligne dans le fichier qui se lit comme suit: dtparam=spi= on
.
Si la ligne indique que spi est désactivé ou si elle est totalement absente, éditez le fichier en conséquence. Il suffit de faire de la ligne la dernière ligne du fichier.
N’oubliez pas que vous devrez redémarrer le Pi pour que les modifications apportées au module du noyau prennent effet.
Avec votre système rasbian mis à jour.Il faut charger les pilotes.
modprobe spi_bcm2708
modprobe spidev
Vérifier que les modules chargés:
lsmod
Taille du module utilisée par
spidev 5944 0
spi_bcm2708 5350 0
snd_bcm2835 21681 0
snd_pcm 81170 1 snd_bcm2835
snd_seq 59528 0
snd_timer 21602 2 snd_seq, snd_pcm
snd_seq_device 6924 1 snd_seq
snd 57427 5 snd_seq_device, snd_timer, snd_seq, snd_pcm, snd_bcm2835
snd_page_alloc 5343 1 snd_pcm
i2c_bcm2708 3822 0
Code Raspberry Pi
Enregistrez le code ci-dessous sous le nom spidev_test.c sur votre Raspberry Pi et compilez-le.
/*
* SPI testing utility (using spidev driver)
*
* Copyright (c) 2007 MontaVista Software, Inc.
* Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static void pabort(const char *s)
{
perror(s);
abort();
}
static const char *device = "/dev/spidev0.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay;
static void transfer(int fd)
{
int ret;
uint8_t tx[] = {
0x48, 0x45, 0x4C, 0x4C, 0x4F,
0x20,
0x57, 0x4F, 0x52, 0x4C, 0x44,
0x0A
};
uint8_t rx[ARRAY_SIZE(tx)] = {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)
pabort("can't send spi message");
/*
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
if (!(ret % 6))
puts("");
printf("%.2X ", rx[ret]);
}
puts("");
*/
}
static void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3]\n", prog);
puts(" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -b --bpw bits per word \n"
" -l --loop loopback\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
" -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n"
" -3 --3wire SI/SO signals shared\n");
exit(1);
}
static void parse_opts(int argc, char *argv[])
{
while (1) {
static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
{ "loop", 0, 0, 'l' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "lsb", 0, 0, 'L' },
{ "cs-high", 0, 0, 'C' },
{ "3wire", 0, 0, '3' },
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ NULL, 0, 0, 0 },
};
int c;
c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
if (c == -1)
break;
switch (c) {
case 'D':
device = optarg;
break;
case 's':
speed = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 'b':
bits = atoi(optarg);
break;
case 'l':
mode |= SPI_LOOP;
break;
case 'H':
mode |= SPI_CPHA;
break;
case 'O':
mode |= SPI_CPOL;
break;
case 'L':
mode |= SPI_LSB_FIRST;
break;
case 'C':
mode |= SPI_CS_HIGH;
break;
case '3':
mode |= SPI_3WIRE;
break;
case 'N':
mode |= SPI_NO_CS;
break;
case 'R':
mode |= SPI_READY;
break;
default:
print_usage(argv[0]);
break;
}
}
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
parse_opts(argc, argv);
fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
transfer(fd);
close(fd);
return ret;
}
Compilation
gcc spidev_test.c -o spidev_test
Fonctionnement
- Branchez votre Arduino sur votre bureau via le câble série.
- Ouvrez le moniteur série arduino et réglez le débit sur 115200.
- sur le Raspberry Pi, exécutez le code compilé.
sudo ./spidev_test
Vous devriez voir HELLO WORLD s’imprimer dans le moniteur série Arduino IDE.
Débogage
Assurez-vous que votre noyau dispose des pilotes requis (spi-bcm2708.ko et spidev.ko).
ls -al /lib/modules/`uname -r`/kernel/drivers/spi/
total 64
drwxrwxr-x 2 pi pi 4096 Aug 10 10:53 .
drwxrwxr-x 23 pi pi 4096 Aug 10 10:53 ..
-rw-rw-r– 1 pi pi 14428 Aug 10 10:53 spi-bcm2708.ko
-rw-rw-r– 1 pi pi 10852 Aug 10 10:53 spi-bitbang.ko
-rw-rw-r– 1 pi pi 15803 Aug 10 10:53 spidev.ko
-rw-rw-r– 1 pi pi 10693 Aug 10 10:53 spi-gpio.ko