STM32 I2Cのスレーブモード

2025年2月9日日曜日

【STM32】 LL

t f B! P L

 I2Cスレーブの設定

あまり使用例が見当たらないSTM32のI2Cスレーブモードについてのメモ。
STM32のI2Cはデフォルトではスレーブモード。
STRATビットの送信でマスタに切り替わり、STOPビットの送信でスレーブモードに戻ります。

設定手順

STM32G0xシリーズとして、I2C2をマスタ、I2C1をスレーブとして使います。 
同一デバイス上で動作させる為、スレーブは割り込みを使うことになります。

スレーブアドレスの設定と有効化 

LL_I2C_SetOwnAddress1()でスレーブアドレスをセット。 
LL_I2C_EnableOwnAddress1()でスレーブアドレスを有効化する。 
OwnAddress1を使う場合、10ビットアドレスも設定できる。
デフォルトでは設定レジスタOAR1のOA1MODEが0で、7ビットモード。 

各種ビットの設定 

割り込み関連はCR1レジスタになります。
ACK/NACKの設定のみCR2レジスタです。

ADDRIE

アドレス一致割り込みの制御。
スレーブが通信の開始を検知する方法がアドレス一致割り込みになる。

RXIE

受信割り込み。
RXDRレジスタにデータがあるとき1がセットされ、RXDRが読みだされた時にクリアされる。

TXIE

送信割り込み。
TXDRが空であるときにセットされ、TXDRに書き込まれるとクリアされる。

STOPIE

STOPビットの検出割り込み

NACK

CR2レジスタ。
0であるとき、現在の受信バイト後にACKを返す。
基本はACKで返すべきなのでそのままで良いですが、マスタからの受信データを元に何らかの処理を行う際は通信完了後に1をセットし、NACKを返す用に設定した方が安全です。
EEPROMの書き込みビジー状態をイメージしてもらうとわかりやすいかもしれません。

通信手順

①ADDR一致で通信開始を検出する

設定したスレーブアドレスと一致している場合、割り込みが入る。
続いてISRレジスタのDIRビットをチェックする。
DIRが0のとき、スレーブは受信を行い、1のときは送信を行う。

マスタから送信されるアドレスの最下位ビットが0のとき、1のときと同じ。

②DIRに応じて処理を実行

送信または受信の処理を行う。
受信の場合、事前に用意した受信バッファの容量が不足しないように監視します。

③通信の終了

STOPビットを受信したら通信は終了です。

コード例

main.c内

I2Cの設定を行います。

Master側
I2Cに使うピンの設定(GPIO)
I2Cへのクロック供給。タイミングの指定等です。
タイミング値はCubeIDEの生成値をそのまま使っています。ここでは400KHz設定です。

Slave側
Masterと同様の設定に加え、各種割り込みの許可、OwnAddress(自身のアドレス)
ACKの設定を行っています。

i2c.c内

今回スレーブモードではI2C1を利用しています。
__NVIC_EnableIRQ(I2C1_IRQn);を実行することで割り込みハンドラのI2C1_IRQHandler()が実行可能になります。
I2C1_IRQHandler()からは以下の関数を呼び、各フラグ状態に応じた処理を行います。

bufは128バイトの配列です。
スレーブ、かつ受信のみであればスレーブ側が何か準備することはありません。
※最大転送数が128と勘違いしていてこの数値になっています。
STM32のI2C通信で一度に転送できる最大サイズは255バイトです。

まとめ

各種割り込みフラグの設定さえしてしまえば比較的シンプルに実装することができると思います。
GPIOの設定についてはSTM32のGPIO設定と同じ方法やマクロを利用しています。

追記

GitHubに今回のプログラムを一部編集したものを投稿しました。
simple_I2C


Translate

検索

QooQ