STM32でI2C通信をやってみる

この記事は現在一緒に開発やってくれてるオカダ
twitter.com
と共同でデバッグしてた時の記録です。

一応動いていますがHALのバグなのか正しい使い方なのかは不明です。

やる際は自己責任でお願いします。


とりあえずやってく

今回は二つのマイコンで通信するので二つNucleoを用意しないといけません。

Slave側の設定

CubeMXを立ち上げてI2Cを有効にする。
クロックなどは各自自由に設定してください

I2Cの設定はこんな感じにした。

f:id:gsmcustomeffects:20170403011226p:plain

アドレスは7bitモードと10bitモードがあるが今回は7bitモードにした。
アドレス値が0だがあとでコード内で記述するのでここでは放置

次にSW4STM32にインポートしていく。

ここでI2Cのアドレス設定する。

hi2c1.Init.OwnAddress1 = 0x01<<1;

f:id:gsmcustomeffects:20170403013426p:plain

ここでシフト演算子でアドレスをシフトしているのは後述するのでとりあえずこうしてください。

次に受信処理を書いていきます。

HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)

というAPIブロッキング受信なのでそれを使っていきます。

HAL_I2C_Slave_Receive(&hi2c1,(uint8_t*)aRxBuffer, 1, 1000);

こんな感じに書きます。
aRxBufferは上のほうでこんな感じに定義してます。

uint8_t aRxBuffer[1] = {0};

無限ループ内はこんな感じになります

f:id:gsmcustomeffects:20170403015132p:plain

Master側の設定

上記と同様にCubeMXの設定をする。

f:id:gsmcustomeffects:20170403015318p:plain

今回はマスターなのでアドレスはノーケアでOK

AC6に読み込んで送信コードを書いていく

HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

が送信APIなのでそれを使って書いていく。

ここで注意するのがAddressをシフトして引数に入れることだ

f:id:gsmcustomeffects:20170403022048p:plain

んでそれにならって書くとこんな感じ

f:id:gsmcustomeffects:20170403015515p:plain

ここでは上部に何も記述してないが実際の動作コードでは送信バッファaTXBufferに0xAB、0xBAを順番に代入し交互に送られるようにした。

実際に動作させていく

両方のI2CピンとGNDピンをつなぎバス間部分をロジアナでみてみる

f:id:gsmcustomeffects:20170403015919p:plain

きちんと交互にデータが来ていることがわかる。

ちなみにその時の送受信レジスタの値はこのようになっている。

f:id:gsmcustomeffects:20170403020702p:plain

問題のシフトの説明

上記の例は動作するケースだけを示している。

それはシフト演算子でアドレスをシフトしているのできちんと読みこめています。
それについて最初まったく原因がわからず時間を溶かしました・・・・・・・

結局

CubeMXが出力するコードに問題があり自身のアドレスを示すレジスタの値がおかしいことになっていた。

設定レジスタはI2C_OAR1のOA1ビット(7:1bit)である

f:id:gsmcustomeffects:20170403022913p:plain

そこを見てみると

f:id:gsmcustomeffects:20170403021443p:plain

f:id:gsmcustomeffects:20170403021512p:plain

上記のように自身のアドレスをシフトして入れないとレジスタに正しく値がセットされていない。
CubeMX上でPrimaryアドレスにそのままの値を入れてもこうなってしまう

正しくはシフトがついた状態で出力されているもしくはHALの内部でシフトしてセットしているはずである。

よって使い方が悪いわけではなさそうなので一応バグに入るのかね?

これについては海外フォーラムでも話題になっていたみたいである。
先に読めばよかった・・・・・・・・

community.st.com

今回はこんな感じです

皆さんのお役に立てたらうれしいです。それでは!