|
I2Cデバイスの扱い方 †CAT724, CAT845に搭載されているLinuxOSにはI2Cデバイスの通信ドライバが含まれています。このためI2CターゲットICとの通信はとても簡単です。 本ページの内容はCAT724, CAT845固有の部分を除けばそれ以外の組込みLinuxでもだいたい同じです。 まずはI2C通信をread()とwrite()を使って自作プログラムする方法を説明します。次にカーネルの既存のドライバを組み込む方法を説明します。 2013/2/21 y.ebihara
2017/11/26 CAT845追記
CAT724のカーネル 2013年2月21日以後のバージョンでユーザ空間からのI2C通信に対応しました。まずはカーネルのバージョンを上げてください。 カーネルイメージ(zImage) リンク切れの場合はこちらから最新を取得してください。 を取得したのち、 CAT724kのLinux rootユーザコマンドラインにて # cp zImage_3.0.4_cat724_20130221 /dev/mtdblock1 でもカーネルのバージョンアップができます。 目次 CAT724のI2C仕様 †/dev/i2c-0 ... SH7724の I2C0 の通信バス。ユーザ回路で使用可能 /dev/i2c-1 ... SH7724の I2C1 の通信バス。ユーザ回路で使用可能 /dev/i2c-2 ... CAT24 CPU上のGPIOによるソフトウェアで実装したI2C。 CAT74 CPUボード上でEEPROMとRTCが接続さてている 注意:EB724AにはEEPROM用のパターンがあり、/dev/i2c-0 にはスレーブアドレス0xA0,0xA2が予約されています。U6に24LC04Bを実装していただくと512バイトのEEPROMとして使用できます。あるいは、スレーブアドレス0xA0を別に使用したい場合は 後述するように カーネルの一部をコメントアウトしてください。 サンプル回路 †I2Cの温度センサであるLM75をI2C0に接続したサンプルを用いて説明します。
CAT845のI2C仕様 †
I2Cアドレスは 0b1001000 (0x48) プログラム解説 †全体の流れ †I2CターゲットICと通信するには
1,2の部分 /* LM75温度センサがつながっているI2Cバスの指定 */ #define I2CDEVICE "/dev/i2c-0" // CAT845の場合 /dev/i2c-4 とする /* LM75温度センサのI2Cアドレス指定(7bitアドレス値) */ #define LM75_ADDR (0x90 >> 1) int main(){ int fd; /* ファイルディスクリプタ */ int addr = LM75_ADDR; int ret; /* I2C 通信デバイスのオープン */ fd = open(I2CDEVICE,O_RDWR); if(fd<0){ perror(I2CDEVICE); exit(1); } /* 通信相手のI2Cアドレス(7bit)を固定する */ ret = ioctl(fd, I2C_SLAVE, addr); if(ret<0){ perror(I2CDEVICE); exit(2); } 3の部分(詳細は後述) /* -------------------------------------------------------------*/ /* それぞれの I2C 処理 */ /* config レジスタの書き込み */ lm75_write_config(fd, 0x60); /* 0b 0110 0000 */ /* config レジスタの読み出しと表示 */ lm75_read_config(fd); /* 温度の読み出しと表示 */ lm75_read_temp(fd, NULL); /* 温度上限を27度、正常復帰温度を26度とする */ lm75_write_Tos_Thyst(fd, 27<<8, 26<<8); 4の部分 /* -------------------------------------------------------------*/ /* 使い終わったら close() する */ close(fd); } /* mainの終わり プログラム終了 */ 通信部分詳細 †*温度レジスタを読む †
はkernelのI2Cドライバが自動的に送信します。アプリでは通信本体のみ read()、write() するだけとなります。 LM75の場合は電源投入直後であれば単純に2バイトread()することで温度(2byte)の読み出しが可能です。 int lm75_read_temp(int fd, int *temp) { int ret; unsigned char data[2]; unsigned short x; int value; /* I2Cターゲットから2バイト読む */ ret = read(fd, data, 2); if(ret<0){ perror(I2CDEVICE); return -EIO; /* IOエラー */ } /* 通信結果の生データをを表示する */ printf("0x%02x 0x%02x\n", data[0], data[1]); x = (data[0]<<8) | data[1]; /* 一旦 unsigned のまま単純に16bitにして */ value = x; /* 符号付きintに拡張する*/ /* value を 256で割ったのが温度(C) になる */ printf("%lf \n",(double)((double)value/256)); if(temp != NULL){ *temp = value; /* 温度(C)の 256倍値 */ } return 0; /* 成功 */ } configレジスタへの書き込み †LM75では <レジスタポインタ番号> <データ> の順で書き込みを行うことでレジスタ値のセットができます。詳細は次の通りです。configレジスタはポインタ1です。 int lm75_write_config(int fd, int config) { int ret; unsigned char data[2]; data[0] = 1; /* 0b 0000 0001 */ data[1] = config; /* I2Cターゲットへ2バイト書く */ ret = write(fd, data, 2); if(ret<0){ perror(I2CDEVICE); return -EIO; /* IOエラー */ } return 0; /* 成功 */ } Tos、Thystレジスタへの書き込み †LM75ではTos(温度上限)、Thyst(温度正常復帰ヒステリシス)を書き込むことでO.S.端子にコンパレータ出力ができます。 int lm75_write_Tos_Thyst(int fd, int Tos, int Thyst) { int ret; unsigned char data[3]; /* Tos レジスタへの書き込み */ data[0] = 0x03; /* レジスタ・ポインタ 0b 00000011 */ data[1] = (Tos >> 8); /* 上位バイト */ data[2] = (Tos & 0xFF); /* 下位バイト */ /* I2Cターゲットへ3バイト書く */ ret = write(fd, data, 3); if(ret<0){ perror(I2CDEVICE); return -EIO; /* IOエラー */ } /* Thyst レジスタへの書き込み */ data[0] = 0x02; /* レジスタ・ポインタ 0b 00000010 */ data[1] = (Thyst >> 8); /* 上位バイト */ data[2] = (Thyst & 0xFF); /* 下位バイト */ /* I2Cターゲットへ3バイト書く */ ret = write(fd, data, 3); if(ret<0){ perror(I2CDEVICE); return -EIO; /* IOエラー */ } return 0; /* 成功 */ } configレジスタの読み出し †LM75ではレジスタポインタを1バイトwrite()し、次いで読み出したいレジスタ内容を1バイトもしくは2バイトread()することでレジスタの読み出しが行えます。 configレジスタを読みだすサンプル int lm75_read_config(int fd) { int ret; unsigned char data[1]; unsigned char config; data[0] = 1; /* 0b 0000 0001 */ /* I2Cターゲットへ1バイト書く */ ret = write(fd, data, 1); if(ret<0){ perror(I2CDEVICE); return -EIO; /* IOエラー */ } /* I2Cターゲットから1バイト読む */ ret = read(fd, data, 1); if(ret<0){ perror(I2CDEVICE); return -EIO; /* IOエラー */ } /* 結果を表示 */ config = data[0]; printf("LM75 read config = 0x%02x\n",config); return 0; /* 成功 */ } ダウンロード †
コンパイルして実行するには 開発PCにて $ sh4-linux-gnu-gcc i2c_test.c CAT724にて NFSなどで該当ディレクトリに移動してから # ./a.out 既存のI2Cドライバをカーネルに組み込む方法 †LinuxカーネルにはいくつかのI2Cターゲットドライバが用意されています。LM75のドライバもあります。 カーネルをconfigし、ソースを一部編集するとそれらのドライバを組み込むことができます。目的に合うドライバがあれば、I2C通信部分を自作する必要はありません。 手順を示します。 ソースの展開 †開発PCにて作業ディレクトリ work を作り、最新カーネルを展開してください。 $ mkdir work $ cd work $ tar xzf linux-3.0.4_cat724_20130221.tgz $ cd inux-3.0.4_cat724 コンフィグおよびソースの編集 †コンフィグレーションを一旦デフォルトに戻してから、menuconfigに入ります。 $ make cat724_defconfig $ make menuconfig LM75ドライバを組み込みます Device Drivers ---> <*> Hardware Monitoring support ---> <*> National Semiconductor LM75 and compatibles カーネルビルド †$ make CAT724への組み込み †出来あがった arch/sh/boot/zImage がカーネルのですので、これをCAT724にて # cp zImage /dev/mtdblock1 として上書きし、再起動します。 CAT724上で # echo lm75 0x48 > /sys/class/i2c-adapter/i2c-0/new_device とするとLM75ドライバが組み込まれます。 CAT724での使用方法 †rootユーザコマンドラインにて # cat /sys/class/i2c-adapter/i2c-0/0-0048/temp1_input 25500 上記は 25.500 度である意味 # echo 27000 > /sys/class/i2c-adapter/i2c-0/0-0048/temp1_max # echo 26000 > /sys/class/i2c-adapter/i2c-0/0-0048/temp1_max_hyst 温度上限を 27.00度、正常復帰ヒステリシスを26.00度にする例 CAT845での使用方法 †CAT845のrootユーザコマンドラインにて # echo lm75 0x48 > /sys/class/i2c-adapter/i2c-4/new_device i2c i2c-4: new_device: Instantiated device lm75 at 0x48 lm75 4-0048: hwmon0: sensor 'lm75' 温度の取り方 # cat /sys/class/hwmon/hwmon0/device/temp1_input 22000 上記は 22.000 度である意味 #!/bin/sh ONDO=`cat /sys/class/hwmon/hwmon0/device/temp1_input` echo "scale=3; $ONDO / 1000" | bc 注意 †カーネルにはたくさんのドライバが用意されていますが個々のドライバの組み込み方法や使い方は個々のドライバによって異なりますので、上記を例に研究してください。 sysfsを使ったデバイスの確認方法 †# ls -l /sys/bus/i2c/devices/ lrwxrwxrwx 1 root root 0 Aug 1 2000 0-0050 -> ../../../devices/platform/i2c-sh_mobile.0/i2c-0/0-0050 lrwxrwxrwx 1 root root 0 Aug 1 2000 0-0051 -> ../../../devices/platform/i2c-sh_mobile.0/i2c-0/0-0051 lrwxrwxrwx 1 root root 0 Aug 1 2000 2-0032 -> ../../../devices/platform/i2c-gpio.2/i2c-2/2-0032 lrwxrwxrwx 1 root root 0 Aug 1 2000 2-0050 -> ../../../devices/platform/i2c-gpio.2/i2c-2/2-0050 lrwxrwxrwx 1 root root 0 Aug 1 2000 2-0051 -> ../../../devices/platform/i2c-gpio.2/i2c-2/2-0051 lrwxrwxrwx 1 root root 0 Aug 1 2000 i2c-0 -> ../../../devices/platform/i2c-sh_mobile.0/i2c-0 lrwxrwxrwx 1 root root 0 Aug 1 2000 i2c-1 -> ../../../devices/platform/i2c-sh_mobile.1/i2c-1 lrwxrwxrwx 1 root root 0 Aug 1 2000 i2c-2 -> ../../../devices/platform/i2c-gpio.2/i2c-2 これらのデバイスが登録されていることが確認できます。スレーブ番号は右に1bitシフトしています。 時計IC (/dev/i2c-2, 0032) # cat /sys/bus/i2c/devices/2-0032/name rx8581 # cat /sys/bus/i2c/devices/2-0032/rtc/rtc0/date 2014-06-30 # cat /sys/bus/i2c/devices/2-0032/rtc/rtc0/time 10:27:26 I2Cドライバ補足 †debianのi2c-tools †CAT724での実行例 †# apt-get install i2c-tools # i2cdetect -y -r 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- # i2cdetect -y -r 2 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: UU UU 52 53 54 55 56 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- CAT845での実行例 †root@cat845:~# i2cdetect -y -r 4 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- 関連 †
|