STM HAL 同一SPIバス上ICのモード切り替え

 


SPI接続するICを2つ制御する場合、一番簡単なのは、SPIのバスを変えて2つ使う事。

これは簡単だが、場合によっては配線をその分必要とするので面積や、余剰のピン次第。

SPIのバスを1つにカスケードされたもののモードを動作中に変えられるか?

Can SPI clk polarity and clk phase be changed on the fly?

https://community.st.com/s/question/0D50X00009XkdzRSAR/can-spi-clk-polarity-and-clk-phase-be-changed-on-the-fly

とかでも質問があがっており、”これは実践的なテストであり、ドキュメントで保証されるものではありません。”と言われている・・・・

HandleSpiBMP.Init.CLKPolarity = SPI_POLARITY_HIGH;

HandleSpiBMP.Init.CLKPhase = SPI_PHASE_2EDGE;

を変えられるか?という事を試した。

結論:変えられる。

ただし、一筋縄ではいかない。ICの素性にもよる。

必ずロジアナが手元にあって波形を見ながらいろいろ試して初めてできるという事が結論である。


When controlling two SPI-connected ICs, the easiest way is to use two different SPI buses.
This is easy, but in some cases it requires more wiring, so it depends on the area and the extra pins.
Can the mode of the cascaded SPI buses be changed during operation?
In other words, is it possible to change the mode of a cascaded SPI bus during operation?
HandleSpiBMP.Init.CLKPolarity = SPI_POLARITY_HIGH;
HandleSpiBMP.Init.CLKPhase = SPI_PHASE_2EDGE;

Can I change the I tried.
Conclusion: It can be changed.
However, it is not a simple task. It is possible only when you have a logic analyzer and try various things while watching waveforms.


【回路の作製】

ブレッドボードでジャンパーワイヤーを使って接続するとモジャモジャに!



ロジアナへのひっぱり出すと・・・さらにモジャモジャ!

接続の詳細は割愛するが、SPIをカスケードして接続(マイコンのSCKの線からDACのSCKへ、そこからADCのSCKにと接続して、CCだけはマイコンからDAC用のGPIO(PA4)と、ADC用のGPIO(PA3)。DACはMISOを使わないので、この線はマイコンからADCへ)

【コード例】

やり方は、例えば、EDGE2をコードを自動生成させている場合、別のエッジを認識するSPIの設定を自分の関数として、自動生成されるMX_GPIO_Initをコピーして作り、EDGEの所だけ変える。

static void MX_SPI1_Init_EDGE1(void)

{


  /* USER CODE BEGIN SPI1_Init 0 */


  /* USER CODE END SPI1_Init 0 */


  /* USER CODE BEGIN SPI1_Init 1 */


  /* USER CODE END SPI1_Init 1 */

  /* SPI1 parameter configuration*/

  hspi1.Instance = SPI1;

  hspi1.Init.Mode = SPI_MODE_MASTER;

  hspi1.Init.Direction = SPI_DIRECTION_2LINES;

  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi1.Init.NSS = SPI_NSS_SOFT;

  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;

  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi1.Init.CRCPolynomial = 10;

  if (HAL_SPI_Init(&hspi1) != HAL_OK)

  {

    Error_Handler();

  }

  /* USER CODE BEGIN SPI1_Init 2 */


  /* USER CODE END SPI1_Init 2 */


}

これを関数を呼び出したら、呼んであげる。(毎回初期化するようなもの)

もう一つの関数側は、自動生成されるMX_GPIO_Initをコールする。つまり、

DACはMX_GPIO_Initのままで

ADCは関数冒頭で、MX_SPI1_Init_EDGE1(自作関数)を呼ぶ。

ちゃんとDACも動いて、ADCも動く・・・がしかし、一つ目のチャンネルが電圧が出てない。テスターを当てても出ていない。




一番最初に設定するものだ。
プログラム上、V3から設定してやると、V0は出るようになってV3が出てこなくなる。
つまり順番が問題で最初がアウトになる。

https://moons.link/post-356/

に一番最初だけ動かないという時の対処が載っていたのを覚えていたので、対処してみた。


__HAL_SPI_ENABLE(&hspi1);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  HAL_SPI_Transmit(&hspi1, (uint8_t*)SPIbuffer, 3, 100);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
の前に入れやったら解消できた。
__HAL_SPI_ENABLE(&hspi1);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  HAL_SPI_Transmit(&hspi1, (uint8_t*)SPIbuffer, 3, 100);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

結構このあたりシビアなので、 __HAL_SPI_ENABLE(&hspi1);を挟むようにしておいた方がSPIは安全かと。


コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

ILI9341 240X320 Arduino

Attiny85 FuseRest