2016年9月30日金曜日

Nucleo F401同士でSPI通信してみる。

Arduino Master <-> Nucleo Slaveで実験してみたので、MasterもNucleo F401RE(mbed)にしてSPI通信してみた。

ほんとはNucleo F401REではなく、Nucleo F446REが欲しかったのだが秋月で売り切れていたのでF401REをもうひとつ仕入れた。F446REは動作クロックが最大180MHzで12bit DAC他周辺機能も大幅に強化されていて1600円。mbedで使ってもメリットはいろいろありそう。またいずれ購入する予定。

配線図


Slave側のファームウェアは前回のまま。

Nucleo(Master)のプログラム(mbed)

https://developer.mbed.org/users/ryood/code/Nucleo_rtos_SPI_Master_Test/

mbed: Revision 121
mbed-rtos Revision 117

main.cpp

#include "mbed.h"
#include "rtos.h"

#define SPI_SPEED   (10000000)

BusOut Leds(PA_8, PB_10, PB_4, PB_5);
BusIn Switches(PA_0, PA_1, PA_4, PB_0, PC_1, PC_0);

SPI SpiM(PA_7, PA_6, PA_5); // mosi, miso, sclk
DigitalOut SpiMCs(PB_6);

InterruptIn stepChangeInterrupt(PC_7);

volatile bool isStepChanged = false;
uint8_t prevSendVal = 0x00;

void setChangeStep()
{
    isStepChanged = true;
}

int main()
{
    printf("\r\n\nNucleo rtos SPI Master Test..\r\n");
    
    // LED Check
    for (int i = 0; i <  5; i++) {
        Leds.write(0x0f);
        Thread::wait(100);
        Leds.write(0x00);
        Thread::wait(100);
    }
    
    // Setup Switches
    Switches.mode(PullUp);
    /*
    while(1) {
        printf("%x\r\n", ~Switches.read() &0x3f);
        Thread::wait(100);
    }
    */
    
    // Setup Interrupt
    stepChangeInterrupt.fall(&setChangeStep);
    
    // Setup SPI
    SpiMCs = 1;
    SpiM.format(8, 0);
    SpiM.frequency(SPI_SPEED);
    
    for (;;) {
        uint8_t sendVal = ~Switches.read();
        
        if (prevSendVal != sendVal || isStepChanged) {
            SpiMCs = 0;
            uint8_t receivedVal = SpiM.write(sendVal);
            SpiMCs = 1;
            
            prevSendVal = sendVal;
            
            if (isStepChanged) {
                Leds.write(receivedVal & 0x0f);
                isStepChanged = false;
            }
        }
    }
}

メモ:


この回路では関係ないが、タクトスイッチでInterruptInのテストをすると、以前やった時と同じようにmbedのInterruptIn::mode()でPullUpを指定しても内部PullUpされなかった。(参考:「Nucleo F401REでmbedのInterruptInが動作しない。」) VDD(3.3V)に抵抗でPull Upすれば動作する。

割り込み信号を立ち上がりで補足するInterruptIn::rise()でISRを指定すると割り込みがかからない。立ち下がりで捕捉するInterrupt::fall()だと割り込みがかかった。

割り込み信号

Vonが120nsぐらい。