CubeMXとHALを使ってI2Cの通信をテストした。結果としては、とても簡単で使いやすかった。

テスト構成

今回はSTM32F030F4を使用した。I2Cのデバイスは、MPU-6050という加速度センサとジャイロセンサが入ったものである。

CubeMXの設定

I2Cの設定は、特に難しい部分はなく、通信速度をターゲットに合わせたものにすることくらい。MPU-6050では400kHzとする。

DMAを使用したいので、設定をしておく。送信と受信で別々にDMAの設定が必要である。今回は受信のみを使用する。

コード

HALのAPIとしては、I2CのマスターとスレーブのAPIの他に、EEPROM等との通信用のAPI(HAL_I2C_Mem_xx)が用意されている。今回使ったMPU-6050もそうだが、一般的なI2Cデバイスであれば後者のAPIを使った方が楽な場合が多い。

まずはブロックモードでのReadとWriteの処理。unsigned charの配列を用意しておく。Readはターゲットのアドレス、読み出すレジスタのアドレス、サイズ、読み出し先を指定して実行する。

  1. unsigned char data;
  2. HAL_I2C_Mem_Read(&hi2c1, MP_SLAD, MP_INT_ENABLE, 1, &data, 1, 1000);

 

結果は図のように、レジスタアドレスをWriteした後、自動でリピートスタートでReadを実行してくれる。

Writeも同様。書き込むデータを準備しておいて、同じように実行する。レジスタアドレスの後にそのままデータが続く。

DMAの使用

DMAを使ったReadも、ほとんど変わらず実行できた。処理を実行後、通信が完了すると割込みの関数が呼ばれるので、ここでフラグなどをセットすることで、通信完了を判断することができる。

  1. unsigned char data[DATA_SIZE];
  2. int read_end;
  3. void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
  4. {
  5.     read_end = 1;
  6. }
  7. void ReadStart( void )
  8. {
  9.     read_end = 0;
  10.     HAL_I2C_Mem_Read_DMA(&hi2c1, SLAVE_ADDRESS, RESISTER_ADDRESS, 1, data, DATA_SIZE);
  11. }