Atmel Studioで、I2C Master制御プログラムを開発する方法を説明します。
I2C Masterのサンプル・コード
AVRマイコンには、I2C通信に使用できるTWI(Two Wire Interface)を備えた製品があるので、これを利用します。
//Example: I2C Master,7bit Address Mode
//Target: ATmega328
//Auther: easy labo
//Created: 2014.11.02
#include
void InitI2c(void){
TWSR = 0b00000000; // N=1
TWBR = 32; // 100kHz = Fosc/(16+2*TWBR*N) @Fosc=8MHz, N=1
}
//Start I2C Command
//Start with write bit: StartI2c( (7bit Slave Address << 1) | TW_WRITE )
//Start with read bit: StartI2c( (7bit Slave Address << 1) | TW_READ )
unsigned char StartI2c(unsigned char dataStartI2c){
unsigned char stateOfTWI;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
while( !(TWCR & _BV(TWINT)) );
stateOfTWI = TWSR & TW_STATUS_MASK;
if( stateOfTWI != TW_START && stateOfTWI != TW_REP_START ){
return 0;
}
TWDR = dataStartI2c;
TWCR = _BV(TWINT) | _BV(TWEN);
while( !(TWCR & _BV(TWINT)) );
stateOfTWI = TWSR & TW_STATUS_MASK;
if( stateOfTWI != TW_MT_SLA_ACK && stateOfTWI != TW_MR_SLA_ACK ){
return 0;
}
return 1;
}
//Stop I2C
void StopI2c(void){
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
while( !(TWCR & _BV(TWSTO)) );
}
//Transmit data form master
unsigned char TransI2c(unsigned char dataTransI2c){
TWDR = dataTransI2c;
TWCR = _BV(TWINT) | _BV(TWEN);
while( !(TWCR & _BV(TWINT) ) );
if( (TWSR & TW_STATUS_MASK) != TW_MT_DATA_ACK){
return 0;
}
return 1;
}
//Recieve data from salve, with ACK
unsigned char RecieveAckI2c(void){
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWEA);
while( !(TWCR & _BV(TWINT)) );
return TWDR;
}
//Recieve data from slave, with NACK
unsigned char RecieveNakI2c(void){
TWCR = _BV(TWINT) | _BV(TWEN);
while( !(TWCR & _BV(TWINT)) );
return TWDR;
}
以下、サンプル・コードの内容を見ていく事にします。
8行-11行
I2Cのクロック周波数設定を行います。TWSRでクロック設定用パラメータNを指定します。TWBR、N、Fosc(F_CPU)の値でI2Cのクロックが決定します。なお各レジスタの詳細は、ターゲット・マイコンのデータシートで確認します。
17行-35行
TWCRレジスタの、TWINT、TWSTA、TWENビットを”1″にすると、I2Cスタートを実行します。I2Cスタートが実行できたら、引数のdataStartI2cの値を送信します。通常、dataI2cは、7bit Slave Addressに、Write or Readビットを付加したデータになりますので、引数は、
39行-41行
TWCRの、TWINT、TWSTO、TWENビットを"1"にして、ストップビットを発行します。
45行-54行
TWDRにデータを入れて、TWCRのTWINT、TWENビットを”1″にするとTWDRのデータがスレーブに送信されます。この例では、TWSRをTW_STATUS_MASKでマスクした値をチェックして、スレーブとのACKに失敗した場合は、戻り値が0になる様にしています。
56行-60行
TWCRのTWINT、TWEN、TWEAビットを”1″にすると、スレーブからのデータを受信して、ACKを返します。TWCRのTWINTが”1″ならば受信完了で、TWDRに受信データが格納されます。
63行-67行
TWCRのTWINT、TWENビットを”1″にすると、スレーブからのデータを受信して、NACKを返します。TWCRのTWINTが”1″ならば受信完了で、TWDRに受信データが格納されます。
まとめ
実際は、通信相手となるI2Cスレーブ・デバイスの仕様に合わせて、サンプル・コードにある様な関数を組み合せてI2C通信を行います。また、この例では簡単な通信エラー検知を入れていますが、製品設計の場合は、想定以上の時間が過ぎてもACKが帰ってこない場合等は、タイムアウトして再送制御を行ったり、異常を通知して中断する仕組みなども必要に応じて実装します。
Sponsored Link