Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

異なるマイコン同士でSPI通信をしたい

解決したいこと

マイコン同士でSPI通信をしたいが、うまく受信できないのでアドバイスいただきたい。

発生している問題・エラー

以下の図のように配線して、STMマイコン(センサを統合してpicoに送信)→pico(気象データを受信)に風速と風向のデータを送信したいです。
ラズパイ:Raspberry Pi Pico, 電源はUSB(micro Python)
STMマイコン:NUCLEO-F303K8, 電源はUSB(c++)
開発環境:Thonny V4.1.6
USBは同じPCのUSBポートに接続

image.png

NUCLEO-F303K8 (STM32ピン) Raspberry Pi Pico (SPI1ピン) 機能
PA_5 GP10 SCK (クロック)
PA_6 GP11 MOSI (送信)
PA_7 GP12 MISO (受信)
PA_4 GP13 CS (チップセレクト)

STMマイコンのプログラム(mbed Keil Studio Cloudでコンパイル)

#include "mbed.h"

// SPIオブジェクトの作成 (SPI1: PA_7=MOSI, PA_6=MISO, PA_5=SCK, PA_4=CS)
SPI spi(PA_7, PA_6, PA_5); // MOSI, MISO, SCK
DigitalOut led(LED1);      // デバッグ用LED

int main() {
    printf("NUCLEO-F303K8 SPI Slave Example\n");

    while (true) {
        // スレーブとしてデータを返送
        uint8_t wind_speed = 52;  // 例: 5.2 m/s を10倍して送信
        uint8_t wind_dir = 73;   // 例: 73度

        // マスターからの要求に応答してデータを送信
        uint8_t received = spi.write(wind_speed);  // 1バイト目(風速を送信)
        received = spi.write(wind_dir);            // 2バイト目(風向を送信)

        // デバッグ情報
        printf("Sent: Wind Speed=%d, Wind Direction=%d\n", wind_speed, wind_dir);
        led = !led;  // デバッグ用LEDをトグル
    }
}

実行結果:
Sending: Wind Speed=52, Wind Direction=73
Sending: Wind Speed=52, Wind Direction=73
Sending: Wind Speed=52, Wind Direction=73
・・・・

Rasp picoのプログラム(Thonnyでコード)

from machine import Pin, SPI
import time

# SPI1の初期化 (GP10=SCK, GP11=MOSI, GP12=MISO, GP13=CS)
spi = SPI(1, baudrate=500000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, 
          sck=Pin(10), mosi=Pin(11), miso=Pin(12))
cs = Pin(13, Pin.OUT)  # CSピン(アクティブLow)

cs.value(1)  # CSピンを初期状態で非アクティブ (High)

print("SPI Master Ready")

while True:
    cs.value(0)  # CSピンをアクティブ (Low)

    # スレーブにダミーデータを送信しながらデータを受信
    data = spi.read(2, 0xFF)  # 2バイトを受信(ダミーデータとして0xFFを送信)

    cs.value(1)  # CSピンを非アクティブ (High)

    wind_speed = data[0] / 10.0  # 風速デコード(例: 52 → 5.2 m/s)
    wind_dir = data[1]           # 風向デコード

    print(f"Received: Wind Speed={wind_speed} m/s, Wind Direction={wind_dir}°")
    time.sleep(1)  # 1秒待機


実行結果:
Received: Wind Speed=0.0 m/s, Wind Direction=0°
Received: Wind Speed=0.0 m/s, Wind Direction=0°
Received: Wind Speed=0.0 m/s, Wind Direction=0°
・・・・

できていないこと

受信の値が指定した数値になりません。
原因は何でしょうか。

0

2Answer

SPIは、通常はマイコン側が「マスター」、デバイス(センサー)側が「スレーブ」となって、同一のSPIバスに、複数のSPIスレーブデバイスを接続することができます。UARTのような、一対一通信ではありませんが、複数のスレーブと同時に通信することはできないため、通信するスレーブを指定するためにマスター側が SS (Slave Select) を LOW にするのが一般的です。
よって、マイコン同士のSPIにおいても、どちらかが「マスター」、他方が「スレーブ」として振る舞う必要があります(そのように振る舞うプログラムを作成するということです)。

ピン割り当て(接続)ですが、MOSI(Master Out Slave In)は MOSI、MISO(Master In Slave Out)は MISO と接続します(クロス接続ではありません)。

なお、マイコンでスレーブ側を実装するのは少々面倒かも知れません。一対一通信であれば UART接続の方が簡単だと思いますが、通信速度はSPIに劣ります。

追伸;
どちらのマイコンもPCのUSBから電源を得るなら、VINーVSYSの接続は不要(やめた方はよいと思う)。GND同士の接続だけとする(同一PCなら、これも不要)。

0Like

STM32マイコンをSPIスレーブとして使う場合は、SPIクラスではなくSPISlaveクラスを使用する必要があると思います。

0Like

Your answer might help someone💌