2023年10月9日月曜日

stm32arduinoで多機能なピンの特定の機能を呼ぶときはaltが付いたピンのマクロの利用が必要


背景

stm32マイコンはuartやspiのバスを複数持っているものがあります。
1つのピンに割り当てられているバスが1種類なら問題ないのですが、複数のバスを割り当てられている場合はバスが利用するalt付きのピンを使利用したバスの定義が必要です。

とりあえず動くからとalt無しで動かしたら他のバスと混信する不具合に悩まされたので、stm32arduino環境での書き方を共有します。

プログラム作成対象: stm32h753zi

nucleo-stm32h753ziを利用しました。
記事を書いている時点で上記ボードのarduino環境はまだ公開されていない(次回2.7.0で対応される見込み)ので、以前試行錯誤して把握したstm32h743ziの環境を利用して動かしました。
nucleo-h753zi向けにPlatformIOを通してArduinoプロジェクトをビルドしてとりあえず動かせた

やりたいこと: PB3,PB4,PB5でSPI3を使いたい

stm32h753ziのデータシートのPB3,PB4,PB5を見ると、SPI1,SPI3,SPI6が利用可能と分かります。


SPI3に割り当てられているaltピンを調べる

stm32arduinoの場合はボードごとにピンの設定ファイルがあるので、それを見てSPIのバスがどのピンに割り当てられているか確認します。
設定ファイルはArduino_STM32_Coreのvariantsディレクトリの中にあるので、対象のマイコンのPeripheralPins.cppを探します。

今回はstm32h743ziの環境を利用しているので、下記のファイルを見ました。
stm32duino/Arduino_Core_STM32/variants/STM32H7xx/H742Z(G-I)T_H743Z(G-I)T_H747A(G-I)I_H747I(G-I)T_H750ZBT_H753ZIT_H757AII_H757IIT/PeripheralPins.c

SPIのピンは役割ごと(MOSI, MISO, SCK, SS)にまとまっています。

MOSIとして動くPB5のSPI3の割当を調べると、PB_5_ALT1として定義されていると分かりました。


同様に調べてSPI3向けのピンはMISOはPB_4_ALT1、SCKはPB_4_ALT1として割り当てられていると分かりました。



altピンを利用してSPI3を呼び出す

SPI3向けのaltピンを利用してSPI3を呼び出します。
今回はSPI_Bという変数でSPI3を使います。
// コンストラクタでピンを指定する書き方
#define PIN_SPI_B_SCK PB_3_ALT1
#define PIN_SPI_B_MISO PB_4_ALT1
#define PIN_SPI_B_MOSI PB_5_ALT1

#include <SPI.h>
SPIClass SPI_B(pinNametoDigitalPin(PIN_SPI_B_MOSI),
pinNametoDigitalPin(PIN_SPI_B_MISO),
pinNametoDigitalPin(PIN_SPI_B_SCK));

void setup() {
SPI_B.begin();
}

ALT付きのピンのマクロはstm32arduino内でPinNameという型の変数として扱われます。
一方、PB3などで呼べるピンはuint32_t型で定義されdigitalPinと呼ばれています。
記事を書いている時点ではSPIのコンストラクタにはdigitalPinを受け付ける実装が無いので、pinNametoDigitalPinという関数を利用してdigitalPinに変換して渡します。

setMOSIなどの関数はPinNameを受け付けるものdigitalPinを受け付けるものの2種類が用意されているため、setupでbegin前にピンを割り当てる方式でも良いです。
// setMOSIなどを使ってピンを指定する書き方
#define PIN_SPI_B_SCK PB_3_ALT1
#define PIN_SPI_B_MISO PB_4_ALT1
#define PIN_SPI_B_MOSI PB_5_ALT1

#include <SPI.h>
SPIClass SPI_B();

void setup() {
SPI_B.setMOSI(PIN_SPI_B_MOSI);
SPI_B.setMISO(PIN_SPI_B_MISO);
SPI_B.setSCLK(PIN_SPI_B_SCK);
SPI_B.begin();
}

上記の書き方でSPI3を呼び出せました。

余談: digitalPinで定義するとalt無しのSPIバスが割り当てられる

digitalPin PB3,PB4,PB5を使ってSPIを定義するとalt無しのPinNameで定義したのと同等のSPI1が割り当てられます。
stm32は同一のSPIバスを別のピンで呼び出しても内部で接続されるため、繋いでいるピンが違うものの同じ信号が出てきます。
意図せず同じバスを割り当てていまうと送信データが壊れることがあるので要注意です。

おわり

機能豊富なピンの特定の機能を呼び出す方法が分からなくて戸惑いましたが、stm32arduinoのマイコンごとのPeripheralPins(周辺機能のピン)を見て使いたい機能のピンを割り当てたら良いと分かりました。

参考

Arduino_Core_STM32

0 件のコメント :