ショウのマイクロマウス研修

ショウのマイクロマウス制作-Part11

ショウのマイクロマウス研修
DSC_0095

こんにちはショウです。前回は連続でAD変換をやりました。今回はエンコーダやジャイロセンサと通信するために使用するSPI通信を行います。

今回はMPU9250モジュールを使って動作確認をします。

MPU9250モジュール

CubeMX

今回はSPI3を使います。
CategoriesからSPI3を選択してModeをFull-Duplex Masterを選びます。
そうするとPC10,11,12がSCK、MISO、MOSIに設定されます。


SPIにはSCK、MISO、MOSIの他にもう一本通信するデバイスを選択するCSが必要になります。CSはGPIOで設定するので、隣のPD2をGPIOとして設定します。
CubeMXで行うSPIの設定は、Datasize、FirstBit、Baud Rate、CPOL、CPHAを使うデバイスに合わせて設定します。
今回はMPU9250に合わせてData Sizeは8bit、First BitはMSB Firstに設定しました。
Baud RateはPrescalerで設定します。今回はMPU9250の仕様に合わせて1MHz以下になるように256に設定しています。CPOLはデータ通信時以外におけるクロック信号のHigh、LOWを設定し、CPHAはデータを取得するクロックのエッジが立ち上がりか立ち下がりかを指定しています。CPOLはHigh、CPHAは2Edge(今回は立ち上がり)に設定しました。

LLライブラリをつかったSPI通信プログラム

今回はMPU9250とSPI通信ができているかチェックするWho am Iレジスタでチェックします。
MPU9250のデータシートを確認すると、Who am Iレジスタは71を返してくるので、printfを使って返ってくるレジスタをチェックします。

下の参考サイトを見ながらプログラムは以下のように作りました。

void SPI3_Start(void)

{
  LL_SPI_Enable(SPI3);
  LL_SPI_SetRxFIFOThreshold(SPI3, LL_SPI_RX_FIFO_TH_QUARTER);
}

void SPI_Communication(SPI_TypeDef *SPIx, uint8_t *tx_data,uint8_t *rx_data, uint8_t length, GPIO_TypeDef *GPIOx, uint32_t CS_Pin)
{
  uint8_t count = length;

  LL_GPIO_ResetOutputPin(GPIOx, CS_Pin);

  if( LL_SPI_IsActiveFlag_RXNE(SPIx) == SET)LL_SPI_ReceiveData8(SPIx);
  if( LL_SPI_IsEnabled(SPIx) == RESET) LL_SPI_Enable(SPIx);

  while(count > 0){
    LL_SPI_TransmitData8(SPIx, *tx_data++);
    while(LL_SPI_IsActiveFlag_TXE(SPIx) == RESET );
    while(LL_SPI_IsActiveFlag_RXNE(SPIx) == RESET );
    *rx_data++ = LL_SPI_ReceiveData8(SPIx);
    count--;
  }
  LL_GPIO_SetOutputPin(GPIOx,CS_Pin);
}

void MPU9250_whoami(void)
{
  uint8_t tx_data[2];
  uint8_t rx_data[2];

  tx_data[0] = (0x75 | 0x80);
  tx_data[1] = 0x00;

  SPI_Communication(SPI3, tx_data, rx_data ,2 ,GPIOD,LL_GPIO_PIN_2);

  printf("who am i = %x\r\n",rx_data[1]);
}

SPI3_Start関数にLL_SPI_SetRxFIFOThreshold(SPI3, LL_SPI_RX_FIFO_TH_QUARTER)という処理を追加しています。これはFRXTHビットをセットしています。

FRXTHビットはデータ受信終了を知らせるRXNEビットをセットするデータサイズを指定するビットです。今回は8bitでデータを通信するのでFRXTHビットセットする必要があります。

LL_SPI_SetRxFIFOThresholdの第2引数にはLL_SPI_RX_FIFO_TH_HALFとLL_SPI_RX_FIFO_TH_QUARTERのどちらかが入ります。これは通信するデータサイズに合わせて変更します。今回はデータをセットするLL_SPI_RX_FIFO_TH_QUARTERを使います。

データシートを確認するとSPIの設定の項目の中にFRXTHビットを設定するという項目が入っているのですが、デバッカを使用してFRXTHビットを確認したところ、設定されていませんでした。

CubeMXを使って設定をすると機能のほとんどの設定を自動で行ってくれるのですが、今回このFRXTHビットは自動設定していませんでした。

このFRXTHビットが設定されていないとRXNEビットがクリアされずに、SPI_Communication関数内のwhile(LL_SPI_IsActiveFlag_RXNE(SPIx) == RESET )の処理を抜けられずに処理が止まってしまいます。

なのでSPIを開始するタイミングで直接レジスタに書き込む処理を入れました。

私はこれに気付かず処理が途中で止まってしまって手間取りました。

動作確認

ブレットボードを使ってNUCELOとMPU9250モジュールを繋いで動作確認を行います。

先程のMPU9250_whoami関数をmain関数のループの中に入れて71が返ってくるかTeraTermで確認しました。

ちゃんと71が返って来たので、SPI通信が正しくできていることが確認できました。

来週はジャイロの値を取得するように設定していきます。

参考URL

STM32 + LL のSPI通信を使用してICM-20602と通信する | Sora's Activity Record
STM32マイコンのペリフェラル関連記事を一覧にまとめました。 今回はSTM32F401REのNUCLEOボードとSatoさんがスイッチサイエンスに委託販売をしているICM-206...
タイトルとURLをコピーしました