株式会社インデペンデンスシステムズ横浜

システム開発エンジニアの西田五郎が運営しております。Raspberry Pi や Arduino その他新規開発案件のご依頼をお待ちしております。

Arduino

Arduino UnoでSPI通信(その1)Arduino Uno2台で通信

投稿日:2017年3月11日 更新日:

ArduinoでのSPI通信についてです。SPI通信(Serail Peripheral Interface:SPI)はマイコン系と周辺デバイス間の短距離間で利用されている同期型のシリアル通信の一種です。同様の通信方法としては、I2cがあります。ArduinoやRaspberry Piの周辺デバイスでは、LCDやADコンバータ等で採用されていると思います。I2Cと同様に使いこなしたい通信方法の一つだと思います。

ここでは、2台のArduino Unoを以下のように接続してマスタとスレーブにしてごく簡単な通信を確認しました。Arduino UnoはそれぞれPCに接続しています。

主に以下を参考にしました。ありがとうございます。
Arduinoリファレンス
Arduinoリファレンス日本語訳
ArduinoでSPIの双方向通信をしてみた

ここから具体的な内容です。

Arduino Uno間の配線について
SPIでは以下の配線を使います。
MISO (Master In Slave Out):スレーブからマスタへのライン
MOSI (Master Out Slave In):マスタからスレーブへのライン
SCK (Serial Clock) :データ転送同期用のクロック信号
SS (Slave Select):スレーブデバイスを選択、つまりマスタへのデータ転送を可能にするためのピン。

SSのピンがSPIの特徴の一つでこのピンを利用して複数のスレーブを制御することになります。このピンがLowの場合にマスタとの通信が有効になり、Highの場合はマスタとの通信を無視することになります。

マスタ、スレーブそれぞれ以下のように接続しました。
SS – Pin10
MOSI – Pin11
MISO – Pin12
SCK – Pin13

以下はマスタ側ですが、スレーブ側の同じピンに接続します。

スケッチの内容
Arduinoでは、SPI.hをインクルードして、SPIライブライが利用出来ます。以下のようなスケッチを書きました。処理としては、マスタ側のIDEのシリアルモニタから入力した文字をそのままスレーブ側から送信します。このようなスケッチで単純な通信の確認が出来たという内容です。

マスタ側

/*
 * SPIマスタ
 * SS   - Pin10
 * MOSI - Pin11
 * MISO - Pin12
 * SCK  - Pin13
 */

#include <SPI.h>

#define SSPin 10

void setup() {
  Serial.begin (9600); 
  Serial.println("Master");

  pinMode(SS,OUTPUT); //SSピンを出力設定

  SPI.setBitOrder(MSBFIRST);  //最上位ビット(MSB)から送信
  SPI.setClockDivider(SPI_CLOCK_DIV4);  //通信速度をデフォルト
  SPI.setDataMode(SPI_MODE2);   //アイドル5Vで0V→5Vの変化で送信する
  SPI.begin();  //開始
}

void loop() {
  char snd;
  char rcv;

  //UARTから読み込み
  snd = Serial.read();

  //データがあれば送信
  if(snd != -1){

    //このSlaveをセレクトする
    //(マスタ通信は有効です)
    SetSSPin(LOW);

    //送信
    SPI.transfer(snd);
    delay(100);

    //受信
    rcv = SPI.transfer(0);

    //データ確認
    Serial.println(rcv);
  }
}

/*
 * SSピンの設定
 * Lowでマスタからの通信が有効(セレクト)
 * (Highではマスタから通信出来ない(無視される)セレクト解除の状態)
 */
void SetSSPin(int val)
{ 
    digitalWrite(SSPin, val); 
}

SPIライブラリを利用していますので、詳細が必要な場合は上記の参考にしたサイトを参照して頂ければと思いますが、要点は以下です。

初期設定で以下を設定しています。
SSピンを出力
ビット送信の順序を最上位ビット(MSBFIRST)
通信速度をデフォルト(SPI_CLOCK_DIV4)
送信のタイミングをアイドル5Vで0V→5Vの変化で送信(SPI_MODE2)

loop() では、UARTで文字入力があれば、スレーブ側へ送信しています。ここでの要点は、やはりSSピンの設定です。SSピンをLOWに設定してこのマスタをスレーブの通信を有効にしています。実際には必要なタイミングに応じてHIGHにも設定
してまたLOWに設定する処理になると思います。ここでは単純にLOWに設定しているだけです。これだけでここでは通信が出来ました。

スレーブ側

/*
 * SPIスレーブ
 * SS   - Pin10
 * MOSI - Pin11
 * MISO - Pin12
 * SCK  - Pin13
 */

#include <SPI.h>

void setup() {
  pinMode(MISO,OUTPUT); //MISOを出力

  SPI.setBitOrder(MSBFIRST);  //最上位ビット(MSB)から送信
  SPI.setClockDivider(SPI_CLOCK_DIV4);  //通信速度をデフォルト
  SPI.setDataMode(SPI_MODE2);   //アイドル5Vで0V→5Vの変化で送信する
  SPCR |= _BV(SPE);
    
  SPI.attachInterrupt(); 
}

// SPI割り込み処理
ISR(SPI_STC_vect)
{
  byte ch = SPDR;    //SPIの受信バッファから取得
  SPDR = ch;  //送信バッファに書き込む
}

void loop() {
  // put your main code here, to run repeatedly:
}

MISOを出力に設定して、マスタ側と同様に初期設定をして割り込みを有効にしています。割り込み処理で受信データをそのまま送信しています。部分的にレジスタも使っています。(※必要な場合は以下等を参照して下さい。)
SPI関連レジスタ

動作確認
以下のようにマスタ側のシリアルモニタで確認出来ました。Hello!と送信すると1文字ずつ返ってきました。この時にシリアルモニタの下の部分で「改行なし」に設定すると分かりやすいです。

これで単純な通信がとりあえずは確認出来たということで、次回は以下で実際のデバイスの温度センサADT7310を使ってみます。
Arduino UnoでSPI通信(その2)温度センサADT7310


AdSense

AdSense

-Arduino

執筆者:

関連記事

AndroidでUSBシリアル通信(その2)ライブラリサンプルのArduinoスケッチ

AndroidでUSBシリアル通信の2回目です。前回はハードウェア構成、ソフトウェア構成等全体的な内容について書きました。今回はAndroidの通信相手となるArduinoのスケッチの動作確認を行って …

Arduino UnoでSPI通信(その2)温度センサADT7310

Arduino UnoでSPI通信の2回目です。前回のArduino UnoでSPI通信(その1)Arduino2台で通信ではArduino Uno2台でSPI通信を確認しました。今回は実際のデバイス …

温度センサADT7410(その2)Arduinoでの利用

温度センサADT7410の2回目です。前回はI2C通信の簡単な概要とADT7410モジュールをRaspbery Piに接続してアドレスの確認まで行いました。今回はArduinoでADT7410を使って …

Arduino IDEのWindows10でのインストール(2020/05/04版)

現時点でのArduino IDEのWindows10でのインストール方法についてです。 Arduinoでの開発を始めるための最初の難関というほどでもないかもしれないですが、開発環境であるArduino …

感染症対策のためのIoT技術(その3)超音波距離センサーでの距離測定

感染症対策のためのIoT技術について書いています。今回は超音波距離センサーでの距離測定についてです。 新型コロナウイルスによる感染症の対策が始まってから意識する必要が出てきたソーシャルディスタンスとい …