アプリケーションからSAMA5D3 XplainedのI2C端子にアクセスして外部ペリフェラルを操作する実験を行いました。I2Cも組み込み分野では重要なインターフェースですが、広く用いられている割に扱いが気むずかしいインターフェースですので、事前に素性を知っておくに超したことはありません。
確認には先日のUART実験と同じくLEDボードを利用しました。
I2Cポート
回路図によれば、SAMA5D3 Xplained (以下SAX)のI2C信号は以下の写真の赤丸および黄色の丸二つのポートから取り出すことができます。
購入したArduino MEGAのシールドは赤丸のピンが無く、黄色の丸のポートを使うしかありません(赤丸のポートは”R3”と呼ばれるシールドならば付いているそうです)。
さて、マニュアルによると黄色の丸のポート(J20)はPA30,31とPC26,27が共用しています。そこで回路図を読むと下の図のようになっています。ちょっとわかりにくいですが、「共用されている」とされるPA30,31およびPA26,27はR162,R163で接続されています。ところが実際にはこの二つの抵抗は実装されていません。そのため、「共有されている」とされているJ20のI2Cポートは、実際にはPC26,27専用であり、これはTWI1となります。なお、赤丸のポート(J15)にはTWI0が接続されています。
接続試験
I2Sポートがどのように認識されているのか見てみましょう。
root@sama5d3-xplained:~# dmesg | grep i2c
[ 1.340000] at91_i2c f0014000.i2c: using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
[ 1.350000] at91_i2c f0014000.i2c: AT91 i2c bus driver (hw version: 0x402).
[ 1.360000] at91_i2c f0018000.i2c: using dma0chan2 (tx) and dma0chan3 (rx) for DMA transfers
[ 1.360000] at91_i2c f0018000.i2c: AT91 i2c bus driver (hw version: 0x402).
[ 1.360000] at91_i2c f801c000.i2c: can’t use DMA, error -19
[ 1.360000] at91_i2c f801c000.i2c: AT91 i2c bus driver (hw version: 0x402).
[ 2.540000] i2c /dev entries driver
root@sama5d3-xplained:~#
残念ながら検出されているのは分かりますが、あまり役に立つ情報はありません。しかし、I2Cペリフェラル(TWI)が認識されているのは間違いありません。
root@sama5d3-xplained:~# ls /dev/i2c*
/dev/i2c-0 /dev/i2c-1 /dev/i2c-2
root@sama5d3-xplained:~#
TWI1は/dev/i2c-1だと当たりをつけて調べてみましょう。i2cdetectという便利なコマンドが用意されています。
root@sama5d3-xplained:~# i2cdetect -r -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — 71 — — — — — —
root@sama5d3-xplained:~#
このコマンドは数字で与えられる番号のI2Cデバイスにどんなペリフェラルがぶら下がっているか、総当たりでスキャンを行います。上の結果から0x71のペリフェラルが検出されていますが、これは実際今回使用するLEDディスプレイが持つI2Cアドレスです。
ペリフェラル・アドレス0x71がつながっていると分かったのでコマンドを送ってみましょう。
root@sama5d3-xplained:~# i2cset -y 1 0x71 1 2 3 4 i
root@sama5d3-xplained:~#
i2csetコマンドは、i2cペリフェラルに対してデータを書き込むコマンドです。オプションの-yはユーザーに確認無しで実行することを示します。最後のiはi2cブロック転送、つまり多バイトを一気に送ることを示します。
これらのオプションを理解した上で説明すると、上のコマンドは「/dev/i2c-0に接続されている0x71番地のペリフェラルに、データとして0x01, 0x02, 0x03, 0x04の4バイトを一気に送る」となります。
LEDには4桁の数字1234が表示されます。
pythonでアクセスする
pythonからアクセスする場合はsmbusモジュールを使います。
root@sama5d3-xplained:~# python
Python 2.7.9 (default, Sep 5 2015, 19:22:49)
[GCC 4.9.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import smbus
>>> i2c = smbus.SMBus(1)
>>> address=0x71
>>> i2c.write_byte(address,0x76)
>>> i2c.write_byte(address,0x20)
>>> i2c.write_byte(address,0x49)
>>> i2c.write_byte(address,0x2)
>>> i2c.write_byte(address,0x53)
>>> quite()
root@sama5d3-xplained:~#
多バイト転送はまだ実験していませんが、メソッドは用意されているようです。