2016年10月13日

SPI/I2C シリアル通信

今回はSTM32でのSPI/I2C シリアル通信について紹介します。

環境はこれまで同様、
・STM32F303K8
 +SW4STM32(System Workbench for STM32)
 +STM32CubeMX
です。


◆HALライブラリを使用したI2C通信
HALライブラリを使用したI2C通信でSTM32側がマスタの場合、
PICマイコンなどのようにACKとかRepeatStartなど考える必要はありません。
下記の読み込みか書き込みかの関数を使い分けるだけです!

HAL_I2C_Mem_Read( I2C_HandleTypeDef *hi2c,
                  uint16_t DevAddress,
                  uint16_t MemAddress,
                  uint16_t MemAddSize,
                  uint8_t *pData,
                  uint16_t Size,
                  uint32_t Timeout);

HAL_I2C_Mem_Write( I2C_HandleTypeDef *hi2c,
                  uint16_t DevAddress,
                  uint16_t MemAddress,
                  uint16_t MemAddSize,
                  uint8_t *pData,
                  uint16_t Size,
                  uint32_t Timeout);



非接触赤外線センサMLX90614を読みだした場合
#define DevAddress  (0xB4)
⇒0x5A
として読み書きされます。
R/Wを含めてアドレスを指定するようです。

環境温度読み込み時の例は下記の通り。


HAL_I2C_Mem_Read( hi2c,
                  (uint16_t)DevAddress,
                  0x06,
                  I2C_MEMADD_SIZE_8BIT,
                  (uint8_t*) ret,
                  3,
                  100);

res=(float)(ret[0]+(ret[1]<<8))/100.0;
resに環境温度が格納されます。

MLX90614_i2c-STM32.png

LabToolを使用してデータ通信状態。
直接LabToolをI2Cラインへ接続するとインピーダンスが変わってしまうため、
1k~10kの抵抗を挟んでロギングしました。

I2Cはアドレスの表記が7bitアドレスでR/Wを含めるか、含めないか
チップメーカによってまちまちなのでそこがいつも引っかかるところです。

また、マイコンがいつもと違うと同様にまちまちなので
今回のような地味な検証が後々役立ちます。


思った以上にすんなり動いてくれました。



◆HALライブラリを使用したSPI通信
I2C同様、SPIも思った以上にシンプルでした。
デバイスのデータシートと睨めっこしながら、
main.c内のMX_SPI1_Initの設定を確認してください。
通信できない時はSPIのクロック極性やサンプル位置設定が
間違っていることがほとんどです。

hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;//SPI_POLARITY_HIGH//?!
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;//SPI_PHASE_1EDGE//?!


HAL_SPI_TransmitReceive( SPI_HandleTypeDef *hspi,
                      uint8_t *pTxData,
                      uint8_t *pRxData,
                      uint16_t Size,
                      uint32_t Timeout);

実際にあるデバイスで通信した場合
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,0);//CS
HAL_SPI_TransmitReceive(&hspi1,sData,rData,1,100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,1);//CS


送受信を想定してTransmitReceiveを使用していますが、
受信専用の関数
HAL_SPI_Receive( SPI_HandleTypeDef *hspi,
               uint8_t *pData,
               uint16_t Size,
               uint32_t Timeout);
送信専用関数
HAL_SPI_Transmit( SPI_HandleTypeDef *hspi,
                uint8_t *pData,
                uint16_t Size,
                uint32_t Timeout);
もあります。
ただ、実際に実験してみてはいませんが、
どちらかの場合でも送受信関数TransmitReceiveで
空データを使うことで同じ関数でいけそうな気がします。



SPIについても思った以上にすんなり動いてくれました。

PICの時はRepeatStartのタイミングなど色々苦労させられましたが、
STM32のHALライブラリのシリアル通信は思った以上に考えることが少なく、
すんなり動いてくれました。



posted by Crescent at 00:00| Comment(0) | TrackBack(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック