I2C通信
シリアル通信で1対1以外に、1対多なども可能な有用な通信。いろんなところで解説されているので ほかも参考に。
I2C通信は、
USARTのように1-1の通信以外に、マスターとスレーブとなった2つが通信でき、スレーブ側には複数も可能。
通信のデバイスが局になってアドレスを設定出来るので、
いっぱいデバイス(局)をつないでおいて、送りたい局へ送るという2局通信、 また一斉に送る通信もできる。
通信は双方向、信号線は2本でよいというのも手軽に使えそうで魅力を感じます。
通信形式自体が複雑なのでこういうタイプの通信が初めてだと通信形式の理解はわかりにくいです。
AVRで I2C通信
AVRはI2Cと同様のTWI(Two Wired Interface)の機能をもつチップがありTWIでI2Cができる。
AVRはmega8シリーズ、ATmega8/48/88 などにTWIの機能が備わっています。これを使うとハードの設定機能に頼ってI2C通信ができる。
ATtiny2313にはTWIの機能はなし。
AVRのTWI(Two Wired Interface)の特徴
- バイト単位、割り込みでのI2C通信。
- アドレスは7ビット、128個までの局が可能。
- 400kHzまでのデータ速度
- I2C規約互換
I2C通信の形
信号ライン(バス)は2本で、いくつものデバイスを通信ラインにつなげて、ブラさっがっている、どこと-どこでも通信ができる有用な通信。
通信信号ラインは2本(SDA,SCL)ですが、注意はプルアップされたライン(R1,R2)で接続される。
ぶら下がった(つながっている)デバイス(局)のなかでマスターとスレーブ間が通信をする。マスター、スレーブは設定で決めますが、固定ではなく、動的に変更できます。
どれかがまず、マスター(主人)になり、通信の主導権を握る。そしてスレーブ(奴隷)になったものがそれに従うという通信方法。
マスターは通信の主導権を持ち、自分から送るか、スレーブに指示して送らせるか、など通信の形を決める
- マスター送信 → スレーブ受信
- マスター受信 ← スレーブ送信
マスター(主人)は通信の主導権を持ちますが、マスターは(主人)ですが、
王様とは違うので、王様ゲームのように、
自分と関係ない ”DはBにデータを送れ” というように、自分が関わらない通信は作れません。
- マスターが通信を終了して降りれば、他がまたマスターとなり通信ができる。
- マルチマスターという用語がありますが、同時に2つはマスターとはなれない。
- マスターから放送局みたいに一斉送信(ジェネラルコール)も可能
一対一の通信の流れ
I2C通信、まず1対1通信方法の流れ。
I2C通信それそれの段階の手続きの簡単流れです。
パルス状態も考えると複雑になるので考えず、TWIの機能設定で通信を作る方法の説明です。
データシートを元に
マスター送信動作 → スレーブ受信動作 の簡単な流れ
(用語はデータシートから)
【マスター側】
- マスターが開始条件を送出。(逆に言うと開始条件を送出でマスターになる)
- 続くアドレスパケット送出( SLA_ )で、送信( SLA_W )か受信( SLA_R )動作か決まる
SLA_W でマスター送信動作 MT
SLA_R でスレーブ受信動作 MR - 受信したスレーブ局から応答
応答があれば、続いて
- データ送信
受信したスレーブ局から応答 - 終了条件送出で 通信終わり、バス解放(するとまだどこかがマスターになって通信が可能)
【スレーブ側】
- スレーブの設定をする、自分の局アドレスを設定する。
・自分あてのSLA_を受け取ると、
続く
SLA_W でスレーブ受信動作
SLA_Rで スレーブ送信動作 - スレーブ応答
・データを受ける - スレーブ応答
・停止条件受け取り終了
というような流れ。
基本の流れ以外にも
どの局でも、放送局にも受信局にもなれるので、通信のタイミングによっては、待ってましたとばかりに一斉にみんながマスターになろうと同じ時期に名乗りを上げたりすると、調停がされたり、また通信の再送などもありますが、そういう処理は今回除外。
2C通信設定 手順
以下、データシートに従った設定と流れ。
AVRの機能を使ったTWIの設定、通信方法
通信にはI2Cは マスター(1つ) と スレーブ(1つかそれ以上)がいます。
マスターが開始条件を出して通信が始まり、マスターが終了条件を出して通信終わる。
通信が終了すると、通信ライン(バス)が解放される。するとまたどれかがマスターになって新たな通信ができる。
マイコンの機能を使い、レジスタに通信設定する方法ですが、データシートはじっくり読むと設定手順がまとめられています。
自分でも分類、設定表を作ることがあるのでその視点で見ると、この表、じっくり読むと、すごくうまく整理されて記述されていると思えてきます。
マスター送信動作、状態や応答について
マスター送信動作 ステータステーブル
- Status Code (最左列)
- TWCRの設定によって(ステータスレジスタ)TWSRで 装置や通信状態を得ることができる。
それぞれの状態で、このStatus CodeをTWSRで得ることができ、ACK応答などが返る場合などは右側に記載 - NextActionbyTWI (最右列)hariware 状態によってその応答などが記述されている。
- ハード(装置)が、状態により通信規約で返すことになるACK、NACK信号など
* ACK信号はマスターでもスレーブでも受信した方が出す信号。
マスター送信動作 通信の流れとステータス
マスターとスレーブのやりとりについての記述チャート
マスターのチャート。スレーブから応答がある場合を、色の抜いた枠で示されている。(各記号などはデータシート参照のこと)
チャートでは、つつがなく通信が進んだ場合が最上、
どっかで衝突、調停などスムーズにいかない場合、状態が移る遷移が下に。
それら各状態をStatus Cocd (TWSR) :$08 などのステータス値で得ることができる。
最上のチャートをステータスと併せた表
マスター送信動作
通信開始 | → | アドレス: 送信先を流す |
→ | アドレス宛先があれば ACK返ってくる |
→ | 続いて データ送出 |
→ | 受信されると ACK返ってくる |
→ | 終了条件 送出 |
S | SLA_W送出 | A | Data | A | P | |||||
状態 $08 | $18 | $28 |
こんなスムーズにいかず、どっかで通信不良があると対応動作として通信の規約に従い状態が下に遷移
プログラム
テストとして通信段階に従い、通信とチェックを上から順に作っていきました。
マスター送信動作 → スレーブ受信動作 の設定で 1対1の通信 2局間の通信です。
I2C通信テスト プログラム
2局間 2つのチップ間で通信するので、当然ですが2つのチップが必要です。
- 受信は受信用のAVRmaga8/48/88
- 送信は送信用のAVRmaga8/48/88 に別々に書き込みます。
通信は一度だけ。
まずは先に受信チップを起動し、待機(受信待ち)する。
送信チップを起動すると、自動的に通信が始まる。
●回路
通信ラインは10kΩでプルアップされたPC4,PC5で接続
回路は受信、送信共に同じ
LED接続
通信の各段階はPB1 LEDで確認できます。
データの受け渡しは PD6,7 LED
●テストプログラム
送信側 プログラム
ファイル名
#include
//状態値
#define START 0x08 //スタート状態値
#define RECEIVE 0x60 //自分あての受信状態値
#define MT_SLA_ACK 0x18 //アドレス:SLA_Wを正常送信チェック値
#define MT_DATA_ACK 0x28 //データを正常送信チェック値
void wait( int );
int main(){
unsigned char i;
DDRB = 0x03; //0b00000011; //LED ピン 出力設定
DDRD = 0xC0; //0b1100 0000; //LED ピン 出力設定
TWBR = 0xFF; //分周 2KHz
PORTB = 0x02; //0b00000001; //初期値
wait(1000);
PORTB = 0x00;
wait(1000);
TWCR = 0xA4; //①I2C開始条件送出
while( !( TWCR & (1<< TWINT) ) ); //②結果待ち
while( ( TWSR & 0xF8 ) != START ); //③送信可?
TWDR = 0x80 ; // あて先アドレス設定
TWCR = ( 1<< TWINT )| ( 1<< TWEN ) ; //アドレス送信開始
while( ! ( TWCR & ( 1<< TWINT ) ) ); //④あて先アドレス送信完了待ち
PORTB = 0x02; //送信先の応答待ち
wait(1000);
while( ( TWSR & 0xF8 ) != MT_SLA_ACK ); //⑤アドレス:SLA_W 正常送信チェック
PORTB = 0x00; //送信先の応答確認受け取り 合図 LED消灯
//データ送信
i = 0xC0; //送信データ
PORTD = i; //データ送信 合図
wait(1000);
TWDR = i; //送信データセット
TWCR = ( 1<< TWINT )| ( 1<< TWEN ) ;//送信開始
while( ! ( TWCR & ( 1<< TWINT ) ) );//⑥完了待ち
while( ( TWSR & 0xF8 ) != MT_DATA_ACK ); //⑦データ 正常送信チェック
PORTD = 0x00; //送信データ受け取り確認 合図 LED消灯
TWCR = ( 1<< TWINT )| ( 1<< TWSTO )| ( 1<< TWEN ) ; //I2C停止条件送出 バスの開放
PORTB = 0x02; //停止の目印
}
void wait( int time ){
int j;
unsigned char k;
for ( j=0; j < time ;j++){
for ( k=0; k<100 ;k++);
}
}
受信側のプログラム
処理の流れ (ほほソースファイル同様です)
マスター送信動作 処理の簡単な流れ
- TWCR = START
I2C開始条件 送出 TWCR.INT = 1 ? 送出完了? (TWINT=1まで待機)
(TWSR & 0xF8 ) = START ? 開始条件完了?
- TWDR=アドレス 送信先アドレス設定
- TWCR=SLA_W アドレス送信 SLA_W(アドレスデータ+R/W)
TWCR.INT = 1 ? 送出完了? (TWINT=1まで待機)
(TWSR & 0xF8 ) = ?MT_SLA_ACK 完了? - TWDR=データ データ設定
- TWCR= MT_DATA_ACK データ送信
送出完了? (TWINT=1まで待機) (TWSR & 0xF8 ) =?
MT_DATA_ACK 完了? - TWCR= END I2C停止条件 送出
実行
先に受信チップを起動し、待機(受信待ち)する。
続いて送信チップを起動すると、自動的に通信が始まる。
通信データ
- 送信データは、LED PD6, 7 で最初は送るとき点灯。
- 送信終了するとLEDは消灯
- そして、受信側にデータ移り、受信側LED PD6, 7点灯する。
通信段階合図LED
各段階で送信、受信側の合図LEDが点灯、消灯しながら通信が進む。
各段階の合図LEDの動作はプログラムソースで確認のこと。
- 通信終了で 、送信側 合図LED 点灯
- 受信側 合図LED 消灯
最後にこうならなかったら、終了信号の送受信がうまく処理できていない。
- twtter
- google+
- hatena