STM32 LLライブラリでI2C

2025年2月10日月曜日

【STM32】 LL

t f B! P L

 LLライブラリでI2C通信

LLライブラリを用いたI2C通信の手順や設定内容についてまとめます。
今回もSTM32G0xシリーズでの例です。

初期設定

ペリフェラルの設定ではなく各通信毎の設定を記述します。
CR2レジスタが設定先です。

SADD

0~9ビットまでの10ビットが対象です。
通信先のスレーブアドレスをセットします。アドレスが7ビットの場合は1~7ビットまでが範囲になります。

RD_WRNビット

0であれば送信、1であれば受信になります。

STARTビット

1をセットすることでSTARTコンディションが生成され、通信が開始します。

STOPビット

1をセットすることで現在の転送が完了した後にSTOPコンディションが生成されます。
後述するAUTOENDビットと関連します。AUTOENDであるならSTOPは自動で送られます。

NACKビット

スレーブ時のみ。

NBYTES

転送データサイズを設定します。
ビット幅は8ビットとなっている点に注意してください。
1度の転送で扱えるデータサイズは255(0xFF)バイトまでとなります。

AUTOENDビット

0であるとき、SOFTENDとなりNBYTESバイトの転送完了後、TCフラグがセットされます。
1であるとき、AUTOENDとなりNBYTESバイトの転送完了後、STOPコンディションが生成されます。
基本はAUTOENDモードで良いです。
ただしスレーブデバイスに対して特定のデータを求める動作ではSOFTENDとします。
例えばEEPROMの読み込みたいデータを指定(write)し読み込む(read)場合です。
SOFTENDにしないとRESTARTが送信されない状態になります。

通信手順

他のシリアル通信と同様、各ステータスをチェックしながら進めていくことになります。

BUSYビット

STARTコンディションが検出されると1がセット。
STOPコンディションが検出されると0にクリアされます。

TXEビット

I2C送信に用いるTXDRレジスタの状態を表します。
現在TXDRが空であるなら1、データがある状態なら0になります。

RXNEビット

I2C受信に用いるRXDRレジスタの状態を表します。
現在RXDRにデータがあるなら1、データがないなら0になります。

STOPFビット

STOPコンディションが検出されたとき1がセットされます。

TCビット

CR2のRELOAD、AUTOENDが共に0であるときにNBYTESバイト転送完了するとセットされます。
AUTOENDの項でも書いたようにwrite→readをRESTARTを挟んで行う場合はこのビットでwriteの完了を検知します。

コード例

書き込み先(レジスタ等)を指定する関数(HAL_I2C_mem_Write)および
データのみを送信する関数(HAL_I2C_Master_Transmit)の2つになります。

MemWrite関数


CR2レジスタの設定はコメントアウトしているLL_I2C_HandleTransfer()を一部省略したものです。
Regはスレーブのレジスタ指定用、またRegSizeとして引数で分岐します。
スレーブ側デバイスでアドレス幅が16ビットのものがあったので単純に1バイトずつ分割して送っています。

MasterTransmit関数


MemWriteと異なり、単にデータを送るだけなのでシンプルです。

MemRead関数


スレーブデバイスに一度送信をしてから受信を行います。
スレーブ側に複数のメモリがある場合(EEPROM等)に使うことを想定しています。
Write関数と異なり、最初はSOFTENDを指定します。

RegSizeのWriteを行い、TCビットをチェックします。
TCビットがセットされた後、再度CR2へRead・AUTOEND・引数lengthを設定します。

RESTARTコンディションについて

AUTOENDの設定のみではなく、RESTARTコンディションを送信するには設定手順に注意が必要です。
以下は私が試した中での結論になります。
・すべての設定項目を一度に書き込む
リファレンスマニュアルを読む限り、SOFTENDである時にNBYTES転送後にRESTARTが送られます。

CR2に対して個々にビット設定をする場合、設定の順序に気をつける必要があるかと思われます。
MemRead関数を例とするとRegSizeバイトのWrite後、NBYTES設定→STARTのセット、とするとRESTARTは送られず、一度STOPを挟んでからSTARTが送られてしまいました。

おそらくSTARTビットが立った際にNBYTESに新しい値があることから転送前であると認識されてしまうのでは?と予想しています。
ただしNBYTESは転送毎に変化するわけでは無かったのでかなり怪しい予測です。
以上の点から、特にMemReadのような動作をする場合にはCR2はまとめて設定した方が無難だと思っています。

Translate

検索

QooQ