Raspberry PiのSPI通信

bcm2835 ライブラリ(Ver:1.44)を使って、Raspberry Piで動作するSPI通信のプログラムを作成しました。SPIの設定は、InとOutを接続した簡単なものなので、特にSPIインタフェースを持つデデバイスを準備する必要はありません。実行したRaspberry Piのバージョンを次に示します。

Linux raspberrypi 3.18.0-trunk-rpi #1 REEMPT Debian 3.18.5-1~exp1+rpi16 (2015-03-28) armv6l GNU/Linux

Raspberry PiでのSPI通信の動作環境構築

初期の状態では、SPI通信がOFFになっているので、次のコマンドでSPIを有効にします。コマンドを入力すると選択画面が表示されるので、表示に従って選択していきます。

sudo raspi-config
  • 「8 Advanced Options」を選択する
  • SPI通信1

  • 「A6 SPI」を選択する
  • SPI通信2

その後、再起動します。

$ sudo reboot

再起動後、下のコマンドでspidev0.0、0.1が表示されているか確認します。

$ ls /dev/spi*
/dev/spidev0.0 /dev/spidev0.1

なお、2014年までの Raspbian では、/etc/modprobe.d/raspi-blacklist.conf を使って SPI の有効/無効 を切り替えるようになっていましたが、2015-01-31 リリースからは、より汎用的な Device Tree という仕組みが導入されたのに伴い、SPI のペリフェラル機能の有効化方法が変わり、raspi-blacklist.confへの設定はなくなりました。

lsmodコマンドを用いて、SPI 関連のモジュール(spidev、spi_bcm2708)が組み込まれていることを確認します。

# lsmod
Module                  Size  Used by
snd_bcm2835            18961  0
snd_pcm                76716  1 snd_bcm2835
snd_seq                56172  0
snd_seq_device          5605  1 snd_seq
snd_timer              19204  2 snd_pcm,snd_seq
snd                    53596  5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
soundcore               5579  1 snd
spidev                  6533  0
spi_bcm2708             6578  0

SPIテストプログラムによる動作確認

プログラムを実行する前に、SPIのinとoutを接続してループ状態にします。bcm2835 ライブラリを用いたSPI通信では、SPIの設定用の関数群が提供されています。また実際の送受信には、bcm2835_spi_transfer関数を使用します。

SPIテストプログラム「spi.c」

#include <bcm2835.h>
#include <stdio.h>
int main(int argc, char **argv)
{
    if (!bcm2835_init())
        return 1;
    bcm2835_spi_begin();
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                   // The default
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default

    uint8_t send_data = 0x23;
    uint8_t read_data = bcm2835_spi_transfer(send_data);
    printf("Sent to SPI: 0x%02X. Read back from SPI: 0x%02X.\n", send_data, read_data);
    if (send_data != read_data)
      printf("Do you have the loopback from MOSI to MISO connected?\n");
    bcm2835_spi_end();
    bcm2835_close();
    return 0;
}

SPIプログラムのビルドは次のコマンドを使用します。

$ gcc -o spi spi.c -l bcm2835

SPIプログラムの実行は次のように行います。

$ sudo ./spi
Sent to SPI: 0x23. Read back from SPI: 0x23.

試しに、ループ状態を解除すると次のメッセージが表示される。

$ sudo ./spi
Sent to SPI: 0x23. Read back from SPI: 0x00.
Do you have the loopback from MOSI to MISO connected?