2015年9月24日木曜日

AVRをI2Cスレーブとして使う 送信・受信

AVRをI2Cスレーブとして使う スレーブからバイト列の送信(割り込みで処理) 」と同じ回路でテストしてみた。



処理としては、

AVR(Slave)→Arduino(Master)
AVRからタクトスイッチの押し下げ状態を含めた8Byteのデータを送信。Arduinoは受け取ったデータをSerial通信でパソコンに送る。

Arduino(Maseter)→AVR(Slave)
Arduinoから0..7の範囲でインクリメントした1Byteデータを送信。AVRは受け取ったデータの位置にあるLEDを点灯(LEDの点灯が流れる)。同時にタクトスイッチの押し下げ状態をORしてLEDを点灯。


AVRで使用したTWIのステータスコードは

  // TWI ステータスコード  
  // Rx  
  #define     TWI_SLA_W_ACK          0x60  
  #define     TWI_RX_DATA_ACK          0x80  
  #define     TWI_RX_STOP               0xA0  
  // Tx  
  #define     TWI_SLA_R_ACK          0xA8  
  #define     TWI_TX_DATA_ACK          0xB8  
  #define     TWI_TX_DATA_NACK     0xC0  

AVRはスレーブだがRX(受信)、TX(送信)両方の動作をする。I2C通信の開始時にマスターから送られる最初のI2Cアドレスの次のW/Rビットを見てRX、TXの処理に入る。

 データの送受信の処理はTWI割り込みルーチン内でTWIステータスコードでSwitch文で処理した。

  switch (TWSR & 0xF8) {  
      // Slave TX  
      case TWI_SLA_R_ACK:  
           TXdata_n = 0;  
      case TWI_TX_DATA_ACK:  
           TWDR = TXdata[TXdata_n++];  
           break;  
      case TWI_TX_DATA_NACK:  
           break;  
      // Slave RX  
      case TWI_SLA_W_ACK:  
           break;  
      case TWI_RX_DATA_ACK:  
           RXdata = TWDR;  
           break;  
      case TWI_RX_STOP:  
           break;  
      default:  
           twi_error(0x55);  
 }  

ほんとはRXモードのときにTX用のステータスコードを受け取った場合などの例外処理をしないといけないと思うが、かなりめんどくさそうなので今回は端折った。

のちのち禍根を残すことになるかもしれないが(^q^;

Atmel Studioのプロジェクト
https://github.com/ryood/Arduino_master_AVR_sleve/tree/master/Atmel%20Studio/I2C_Slave_Rx_Tx_ATMega88V_Byte_Sequence_Interrupt

Arduinoのスケッチ
https://github.com/ryood/Arduino_master_AVR_sleve/tree/master/Arduino/master_tx_rx