今回は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に環境温度が格納されます。
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//?!
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
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ライブラリのシリアル通信は思った以上に考えることが少なく、
すんなり動いてくれました。