2017年5月19日金曜日

Nucleo(mbed OS5)のSPI通信を検証してみる。

ベースマシンではNucleo(mbed)のSPIでIC間の通信を行っている。UI系とシンセの制御系でNucleoボードを分けてみたが、ボード間のSPI通信でエラーが発生してしまい、分離するのをあきらめた。(参考:このブログの2016年10月あたり)

mbed OS 5がリリースされた時期も重なって何かと混乱してしまった。

検証のため、mbed OS 5を使ってNucleo同士でSPI通信させてみてみた。

Master側プログラム
https://developer.mbed.org/users/ryood/code/mbed-os_SPITest_Master/

#include "mbed.h"

SPI spiM(D11, D12, D13);
DigitalOut cs(D10);

int main()
{
    printf("SPIMaster Test\r\n");

    spiM.format(8, 0);
    spiM.frequency(1000000);

    uint8_t sdata = 0;

    for (;;) {
        cs = 0;
        uint8_t rdata = spiM.write(sdata);
        cs = 1;

        printf("Master: sdata:%d rdata:%d ", sdata, rdata);

        uint8_t err = sdata - rdata;
        if (err != 1) {
            printf("err:%d", err);
        }
        printf("\r\n");

        sdata++;
        
        //wait_ms(100);
    }
}

Slave側プログラム
https://developer.mbed.org/users/ryood/code/mbed-os_SPITest_Slave/

#include "mbed.h"

#define UART_TRACE  (1)

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

int main()
{
    printf("SPISlave Test\r\n");
   
    spiS.format(8, 0);
    spiS.frequency(1000000);
   
    uint8_t pdata = 0;
   
    for (;;) {
        if (spiS.receive()) {
            uint8_t rdata = spiS.read();
           
           
            #if (UART_TRACE)
            printf("Slave: rdata:%d", rdata);
           
            uint8_t err = rdata - pdata;
            if (err != 1) {
                printf(" err: %d", err);
            }
           
            printf("\r\n");
            #endif
           
            pdata = rdata;
           
            uint8_t sdata = rdata;
            spiS.reply(sdata);
        }
    }
}

NucleoのArduino Header同士をジャンパ線で直結すると通信はほぼほぼうまくいく。


UART出力

ブレッドボードを使って少し意地悪な状態にするとエラーが多発


UART出力

信号波形

直結

ch1:MOSI ch2:SCK

意地悪

ch1:MOSI ch2:SCK

意地悪のほうはSCKとMOSIの波形がずれているように見えるが、よくわからない(@@;
←MOSIは無通信時(CSがアクティブになっていない時)の状態は不定なので、クロック、信号線、CSを同時に測定しないとはっきりしない。

メモ:


まだわからないことだらけだが、SPI通信は配線の状況によって通信エラーが発生することはわかった。

ベースマシンではNucleoからシンセに回しているSPI信号をバス・バッファICのTC74HC541を入れて補強しているが、ケーブルが長いので通信エラーが発生している可能性は大きい。

できることならシンセを制御しているMPUはシンセの近くにしてUI系のMPUとは分けた方がいいのかも(@@?