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はターゲットのアドレス、読み出すレジスタのアドレス、サイズ、読み出し先を指定して実行する。
- unsigned char data;
- HAL_I2C_Mem_Read(&hi2c1, MP_SLAD, MP_INT_ENABLE, 1, &data, 1, 1000);
結果は図のように、レジスタアドレスをWriteした後、自動でリピートスタートでReadを実行してくれる。
Writeも同様。書き込むデータを準備しておいて、同じように実行する。レジスタアドレスの後にそのままデータが続く。
DMAの使用
DMAを使ったReadも、ほとんど変わらず実行できた。処理を実行後、通信が完了すると割込みの関数が呼ばれるので、ここでフラグなどをセットすることで、通信完了を判断することができる。
- unsigned char data[DATA_SIZE];
- int read_end;
- void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
- {
- read_end = 1;
- }
- void ReadStart( void )
- {
- read_end = 0;
- HAL_I2C_Mem_Read_DMA(&hi2c1, SLAVE_ADDRESS, RESISTER_ADDRESS, 1, data, DATA_SIZE);
- }