Arduinoプログラミング手法-(5)USI(Universal Serial Interface)によるTWI(I2C)実装

USIによるTWI(I2C)実装の例。前回のSPIで紹介した”USIPORTS.h”を利用している。

USIの全機能を使いマスター/スレーブ両対応、かつ、アービトレーション(バス調停)も行うマルチマスター対応となっている。USIでここまでやってる例はまだ見たことがない。バスがフル稼働しコリジョン(衝突)が多々発生する状況化でもエラーなしで動作し続けることができるのでバス上に複数のマスターやスレーブを接続する複雑なシステムを構築することも可能だ。自分ながら素晴らしい出来栄えだと思う。

但し、SCLラインのLOW保持による同期化を行わない、或いは、マルチマスター対応ではないFTDIのI2Cマスターなどとの混在はできない。それと、USIは通信終了割込がないため代わりにhandle()メソッドにより終了をポーリングするメソッドを提供している。最悪は受信データ処理(コールバック)が次の通信まで待ちされる可能性があるのでポーリングは必須と考えたほうが良いだろう。

性能的には、マスター側はFSモードの400Kがほぼ出るが、スレーブ側は、割り込み処理の不必要なレジスタ・プッシュ&ポップのロスにより200~250K程度しか出ない。割り込み処理をアセンブラ言語で最適化するともっと高い性能が出せるはずだがメンテナンス等何かと面倒なことになるので妥協。

ちなみに、repeated-startについてI2Cの仕様書を読むと、repeated-startできるのは、write成功後に続くread時のみと記載されているが、仕様的には、write-writeやread-write,read-read、及び、複数回に渡るrepeated-startもできるはず。意味があるかどうかは別にして...

【マスター側エコーバックの例】

【スレーブ側エコーバックの例】

【TWIマスター実装】

【TWIスレーブ実装(割込利用)】