ArduinoとSTM32マイコンをつないでマイコンシステム開発をしてみる その17 ~検証実験⑨~
マイコンシステム開発の要件定義から総合テストまでの工程をたどってみます。
題材としては、空調管理システムにします。
機材はいま手元にあるArduino1台とSTM32マイコン1台を使います。
実装に入る前に検証実験をおこないます
以下の3点をおこないます。
① STM32で計測した気温データをSPI通信でArduinoに送信。
1)STM32単体で、計測した気温データをUSB経由で端末エミュレータに出力。(完了)
2)SPI通信でSTM32からArduinoにテストデータを送信。(トラブルシューティング中)
② Arduinoは気温データを受信し、LCDに表示。
③ ArduinoからSTM32に制御データを送信し、LEDを点灯。
(前回の続きです)
2)SPI通信でSTM32からArduinoにテストデータを送信。(トラブルシューティング中)
STM32F405RGT6からArduinoUNOへSPI通信でテストデータ(0x55)を送信しています。
しかし、ArduinoUNOでは0x55で受信されずに、違う値で受信されてます。
受信データが異なる原因調査を行います
1.STM32とArduinoのSPI設定に不一致はないか
① クロック極性(CPOL)と位相(CPHA)
・STM32側
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
・Arduino側
プログラムにはCPOLやCPHAを設定するコードが含まれていません。
デフォルト値が使用されており、
CPOL = 0(クロックはアイドル時Low)、
CPHA = 0(立ち上がりエッジでデータをサンプリング)で動作します。
クロック極性(CPOL)と位相(CPHA)は一致しているので問題なし
② データサイズ
・STM32側
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
・Arduino側
デフォルトの8ビット設定になっています。
データサイズも8ビットで一致しているので問題なし
③ 通信速度(SPIクロック)
スレーブ側(Arduino)では設定不要。マスター(STM32)が供給するクロックで動作します。
・STM32側
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
STM32のクロック周波数を8で割った値に設定しています。
STM32のクロック周波数の設定を確認します。
STM32では、SPIクロックはAPBクロック(APB1またはAPB2)から供給されますので、APB2クロック(PCLK2)のところを確認します。
PCLK2 = 48 MHz とわかりました。
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
だと、48 ÷ 8 で SPIクロックは6 MHz となります。
・Arduino側
通常のシステムクロックは16MHzです。
ここが怪しいことが判明しました!
・STM32マスター側のSPIクロックはスレーブの速度に適応する必要がある。
・SPI通信はマスターがクロックを生成するため、マスター側のSPIクロックが速すぎると、スレーブが正しくデータを受信できない可能性がある。
・ArduinoのデフォルトSPI設定は最大約 4MHz(システムクロックの1/4)とされることが一般的。そのため、STM32マスター側のSPIクロックは4MHz以下に設定するのが安全。
STM32側のプログラムを修正
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
STM32のクロック周波数を16で割った値に設定しています。
48 ÷ 16 3MHz
これで、ArduinoのデフォルトSPI設定は最大約 4MHzより小さくなりました
これでプログラムを実行してみます。
成功!
送信データを同じデータ値を受信することができました!