Atmel Studio入門:I2C

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が帰ってこない場合等は、タイムアウトして再送制御を行ったり、異常を通知して中断する仕組みなども必要に応じて実装します。

→その他のAtmelマイコン関連情報

Sponsored Link