この記事は現在一緒に開発やってくれてるオカダ
twitter.com
と共同でデバッグしてた時の記録です。
一応動いていますがHALのバグなのか正しい使い方なのかは不明です。
やる際は自己責任でお願いします。
とりあえずやってく
今回は二つのマイコンで通信するので二つNucleoを用意しないといけません。
Slave側の設定
CubeMXを立ち上げてI2Cを有効にする。
クロックなどは各自自由に設定してください
I2Cの設定はこんな感じにした。
アドレスは7bitモードと10bitモードがあるが今回は7bitモードにした。
アドレス値が0だがあとでコード内で記述するのでここでは放置
次にSW4STM32にインポートしていく。
ここでI2Cのアドレス設定する。
hi2c1.Init.OwnAddress1 = 0x01<<1;
ここでシフト演算子でアドレスをシフトしているのは後述するのでとりあえずこうしてください。
次に受信処理を書いていきます。
HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_I2C_Slave_Receive(&hi2c1,(uint8_t*)aRxBuffer, 1, 1000);
こんな感じに書きます。
aRxBufferは上のほうでこんな感じに定義してます。
uint8_t aRxBuffer[1] = {0};
無限ループ内はこんな感じになります
Master側の設定
上記と同様にCubeMXの設定をする。
今回はマスターなのでアドレスはノーケアでOK
AC6に読み込んで送信コードを書いていく
HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
が送信APIなのでそれを使って書いていく。
ここで注意するのがAddressをシフトして引数に入れることだ
んでそれにならって書くとこんな感じ
ここでは上部に何も記述してないが実際の動作コードでは送信バッファaTXBufferに0xAB、0xBAを順番に代入し交互に送られるようにした。
問題のシフトの説明
上記の例は動作するケースだけを示している。
それはシフト演算子でアドレスをシフトしているのできちんと読みこめています。
それについて最初まったく原因がわからず時間を溶かしました・・・・・・・
結局
CubeMXが出力するコードに問題があり自身のアドレスを示すレジスタの値がおかしいことになっていた。
設定レジスタはI2C_OAR1のOA1ビット(7:1bit)である
そこを見てみると
上記のように自身のアドレスをシフトして入れないとレジスタに正しく値がセットされていない。
CubeMX上でPrimaryアドレスにそのままの値を入れてもこうなってしまう
正しくはシフトがついた状態で出力されているもしくはHALの内部でシフトしてセットしているはずである。
よって使い方が悪いわけではなさそうなので一応バグに入るのかね?
これについては海外フォーラムでも話題になっていたみたいである。
先に読めばよかった・・・・・・・・
今回はこんな感じです
皆さんのお役に立てたらうれしいです。それでは!