広告
*I&sup{2};Cとは [#z8051f6f]
I&sup{2};C(あいすくえあしー)はシリアルの通信規格の一つでセンサーなどに使われている。~
より詳しい説明などはネットを調べればたくさん出てくるのでそちらを参考に。

ここでは実際に使う上で知っておいた方が良さそうな情報だけ書いてみる。

*細かなこと [#h0453633]

**デバイスのアドレスが8bitで書かれているものと7bitで書かれているものがある。 [#xe2540ed]
デバイスのデータシートを見るとデバイスのアドレスが8bitで書かれているものと7bitで書かれているものがある。~
これは、8bitの場合、書き込み読み込みビットがLSBに入っているためで、7bitの場合はその読み書きビットが入っていない。つまりどちらも同じ。

[[Raspberry Pi]]などで使うときi2cdetectで表示されるのは最後の読み書きビットは含まないので7bitのアドレスとして表示されている。

**10bitアドレスもある [#j6f0d764]
ものによっては10bitアドレスもあるらしいが、見たことはない。

**同じアドレスのデバイスを複数使いたい場合 [#o1d30866]
外付けの抵抗などでアドレスを変えられるものもあるが、物によってはアドレスを変えられない。~
そこで、SCLのラインを切り替えたりする方法もあるらしいが、切り替えラインを必要とするので面倒である。

世の中にはI2Cのアドレス切り替えデバイスがあるのでそれを使うとよい。~
例えば[[LTC4316:http://www.linear-tech.co.jp/product/LTC4316]]や[[LTC4317:http://www.linear-tech.co.jp/product/LTC4317]]など。~
注意すべきところはLTC4316/4317の出力のSCL、SDAラインも別途プルアップする必要がある。~
また、データシートに載っているアドレス設定用の抵抗値がE48系列(E96系列)なので入手がしにくい。~
1MΩと681kΩというのを1MΩと680kΩにすれば良いかと思う。あるいはオープンとショートの組み合わせ。

**Repeated Start Conditionのデバイスに注意 [#bf032fc3]
[[Repeated Start Condition:http://www.i2c-bus.org/repeated-start-condition/]]([[エレキジャックの解説:http://www.eleki-jack.com/2007/04/1232.html]])になっているデバイスを[[Raspberry Pi]]で読み込もうとするとちゃんと読めない(変な値になっている)。~
i2cgetなどでうまく読めなかった場合はこれを疑ってみると良いと思う。

[[Rabbit Noteさんの記事:http://rabbit-note.com/2015/02/15/raspberry-pi-i2c-repeated-start/]]にその対処法が載っているが、これでもうまく行かない場合がある。~
ネットでもいろいろ議論になっているみたいだけど、いまいち決定打が無いようだ。

一つの解に「[[bcm2835:http://www.airspayce.com/mikem/bcm2835/]]」というライブラリを使う方法がある。~
これは多分GPIOとして直接ポートを叩いていると思う。そのため、これを使うとi2cdetectやi2cget,i2csetなどが使えなくなる。
***[[bcm2835:http://www.airspayce.com/mikem/bcm2835/]]の使い方 [#s9167f44]
-アーカイブを取ってきて解凍、インストールする
 tar zxvf bcm2835-1.xx.tar.gz
 cd bcm2835-1.xx
 ./configure
 make
 sudo make check
 sudo make install
-主要部分~
単純には初期化して、スレーブアドレスを指定して、読み書きして、終了する
--ヘッダーのインクルード
 #include <bcm2835.h>
--初期化
 if (!bcm2835_init()){
   printf("Error initialize\n");
 }
 bcm2835_i2c_begin();
--スレーブアドレスの設定
 uint8_t slave_addr;
 bcm2835_i2c_setSlaveAddress(slave_addr);
--レジスタアドレスの指定
 char reg;  //レジスタアドレス
 bcm2835_i2c_write(&reg,1);
--単純な読み込み
 char reg;  //レジスタアドレス
 char buf[2];  //読み込んだデータを入れる
 int len=1;  //読み込み長さ
 int ret;  //返り値(エラーなど)
 bcm2835_i2c_write(&reg,1);
 bcm2835_i2c_read(buf,len);
--Repeated Start Conditionに対応した読み込み
 char reg;  //レジスタアドレス
 char buf[2];  //読み込んだデータを入れる
 int len=1;  //読み込み長さ
 int ret;
 ret=bcm2835_i2c_read_register_rs(&reg,buf,len);
--書き込み(データを書き込む場合)
 int ret;
 char write[2];  //レジスタアドレスと書き込むデータを入れる
 //例えば,write[0]=reg;write[1]=data;
 ret=bcm2835_i2c_write(write,2);
---&color(Red){bcm2835_i2c_write()を2回に分けるとちゃんと書き込めない};
--終了
 bcm2835_i2c_end();
 bcm2835_close();
-コンパイル(ファイル名が「foo.c」の時)
 gcc -o foo foo.c -l bcm2835
--&color(Red){実行にはroot権限が必要};
-単純な例(インクルードするヘッダーやアドレス等は適当に設定する)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <bcm2835.h>
 #include <stdint.h>
 #define slave_addr 0x00
 #define reg 0x00
 #define write_data 0x00
 
 int main(){
   unsigned char buf[2];
   uint8_t ret;
   char write[2];
   char reg_addr=(char) reg;
 
   //Initialize
   if (!bcm2835_init()){
      printf("Error initialize\n");
   }
   printf("Program start\n");
   bcm2835_i2c_begin();
 
   printf("Send Slave address\n");
   bcm2835_i2c_setSlaveAddress(slave_addr);
 
   //Read : Repeated Start Condition
   printf("Read data\n");
   ret=bcm2835_i2c_read_register_rs(&reg_addr,buf,1);
   if(ret==BCM2835_I2C_REASON_OK){
      printf("Read OK:%02x\n",buf[0]);
   }else{
      printf("Error:%d\n",ret);
      return ret;
   }
 
   //Read : Normal
   ret=bcm2835_i2c_write(&reg_addr,1);
   if(ret!=BCM2835_I2C_REASON_OK){
      printf("Write Error:Reg\n");
      return ret;
   }
   ret=bcm2835_i2c_read(buf,1);
   if(ret==BCM2835_I2C_REASON_OK){
      printf("Read OK:%02x\n",buf[0]);
   }else{
      printf("Error:%d\n",ret);
      return ret;
   }
 
   //Write
   write[0]=reg_addr;
   write[1]=(char) write_data;
   ret=bcm2835_i2c_write(write,2);
 
   //End
   bcm2835_i2c_end();
   bcm2835_close();
 }

広告

リロード   差分   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS