2016年12月9日金曜日

Raspberry Pi 3とNucleo F401REでSPI通信させてみる。

Sparkfunのチュートリアルhttps://learn.sparkfun.com/tutorials/raspberry-pi-spi-and-i2c-tutorialを参考にした。

配線図




3.3V系同士なので信号レベルは気にせず接続できる。

Raspberry Pi 3B(Master)


Raspberry PiのOSはNOOBSで、SPI通信のライブラリにはWiringPiををインストールして使った。

sparkfunの記事にある通り、
>sudo raspi_config
で、SPIを有効化した。

spitest2.cpp

#include <iostream>
#include <errno.h>
#include <wiringPiSPI.h>
#include <unistd.h>

using namespace std;

static const int CHANNEL = 1;

int main()
{
   int fd, result;
   unsigned char buffer[100];

   cout << "Initializing" << endl ;

   fd = wiringPiSPISetup(CHANNEL, 500000);

   cout << "Init result: " << fd << endl;

   unsigned char cnt = 0;
   while (1) {
           buffer[0] = cnt;
           cnt++;
           result = wiringPiSPIDataRW(CHANNEL, buffer, 1);
           cout << "result: " << result << " recieve: " << int(buffer[0]) << endl;
           usleep(10000);       // wait 10ms
   }
}

オシロで信号を捕捉しやすくするために、while(1)の無限ループでSPI通信をさせたが、ラズパイのCPUが発熱してPCとのTCP/IP通信のエラーが発生したのでusleep()を使ってウェイトをかけるようにした。


コンパイル


>g++ spitest2.cpp -lwiringPi -o spitest2


Nucleo F401RE (Slave)


参考「Arduino UnoをSPI Master、Nucleo F401REをSPI Slaveにして通信してみる。

今回はタイミングがシビアではないのでprintfで受信結果を表示するようにした。

main.cpp

#include "mbed.h"

#include "SPISlave.h"


SPISlave SpiS(D11, D12, D13, A2);    // mosi, miso, sclk, ssel


int main()

{

    printf("*** SPI Test: Raspberry Pi 3:Master Nucleo:Slave ***\r\n");

   

    SpiS.format(8, 0);

    SpiS.frequency(500000);

   

    uint8_t cnt = 0;

    SpiS.reply(cnt);

    while (1) {

        if (SpiS.receive()) {

            int v = SpiS.read();

            printf("%d\r\n", v);

            SpiS.reply(cnt++);

        }

    }

}

実行


Raspberry Piで

./spitest2

とコマンドを打って実行すると、ラズパイ用のコンソールと、Nucleoからのシリアル出力用のコンソールから送受信結果が
出力される。



SPI信号波形


MOSI


ch1:MOSI ch2:SCK

MISO


ch1:MISO ch2:SCK

CS


ch1:CS ch2:SCK


MISOとMOSIは1kΩのRでプルダウンしているが、これを入れないとHi-Zになったとき(?)に信号波形が崩れるため。SCKとCSはプルダウンしなくても平気な感じだ。

MOSI(プルダウンなし)


MISO(プルダウンなし)