はじめに
RX64MマイコンでI2C通信を試した際のポイントをまとめた記事です。
構成
- RXマイコンに搭載されている__SCI0__ を I2Cマスター に設定
- RXは3.3V 信号なので3.3Vでプルアップ
- Arduinoが5V信号なのでケーブルの途中で __I2Cレベルシフタ__を挟む
SCI0の設定
生成されるコード
スマートコンフィグレータが吐き出したコードのプロトタイプ宣言を以下に示します。
先頭の「R_rx64m_SCI0」の部分は、__コンポーネント追加ダイアログで入力した名前__が反映されますので
デフォルトの名称とはことなっています。
void R_rx64m_SCI0_I2C_Create(void);
void R_rx64m_SCI0_I2C_Start(void);
void R_rx64m_SCI0_I2C_Stop(void);
void R_rx64m_SCI0_I2C_Create_UserInit(void);
void R_rx64m_SCI0_I2C_IIC_Master_Send(uint8_t adr, uint8_t * const tx_buf, uint16_t tx_num);
void R_rx64m_SCI0_I2C_IIC_Master_Receive(uint8_t adr, uint8_t * const rx_buf, uint16_t rx_num);
void R_rx64m_SCI0_I2C_IIC_StartCondition(void);
void R_rx64m_SCI0_I2C_IIC_StopCondition(void);
void r_rx64m_SCI0_I2C_transmitend_interrupt(void);
static void r_rx64m_SCI0_I2C_callback_transmitend(void);
static void r_rx64m_SCI0_I2C_callback_receiveend(void);
このうち使用するのは以下
| 関数 | 説明 | 
|---|---|
| R_rx64m_SCI0_I2C_Create | 各種レジスタの設定、起動時初期化で1回コールします。 | 
| R_rx64m_SCI0_I2C_Start | 使用開始前に1回コールします。 | 
| R_rx64m_SCI0_I2C_IIC_Master_Send | ライト用関数。マスター(CPU)からスレーブ(Arduino)へデータを送りつけます。 | 
| R_rx64m_SCI0_I2C_IIC_Master_Receive | リード用関数。マスター(CPU)からアドレスとR/WビットをReadにした内容を送信し、スレーブからの応答を受け取ります。 | 
テストコード
RXマイコン側
R_rx64m_SCI0_I2C_IIC_Master_Send と R_rx64m_SCI0_I2C_IIC_Master_Receive__の2つの関数の__第一引数であるadr にはI2Cのアドレスを入れます。
I2Cの規格では最初の1Byteは アドレス7bit + 方向1bit (0がWrite 1がRead) となっています。
Send と Receive 2つの関数があるので、方向を示すbitは関数内で処理していると予想しましたが、実際は第一引数がそのまま出ている様子でした。(オシロで確認しました)
よって
- R_rx64m_SCI0_I2C_IIC_Master_Send__の第一引数のLSBは__常に0
- R_rx64m_SCI0_I2C_IIC_Master_Receive__の第一引数のLSBは__常に1
とすると上手く動作します。。。
3Byte送信し、3Byte受信、送信データを受信データで書き換える動作をします。
void main(void){
    uint8_t     adr         =0      ;//7bit address
    uint8_t     dir         =0      ;//0:Write 1:Read
    uint8_t     tx_buf[4]   ={}     ;//
    uint8_t     rx_buf[4]   ={}     ;//
    
    R_rx64m_SCI0_I2C_Create();
    R_rx64m_SCI0_I2C_Start();
    
    while(1){
	//---- I2C Send RX to Arduino ----
        adr     =0x08    ;//7bit address
        dir     =0x00    ;//0:Write 1:Read
        adr     =(adr << 1) | (dir & 0x00);
        R_rx64m_SCI0_I2C_IIC_Master_Send(adr,&tx_buf[0],3);
        delay_ms(10);
        //---- I2C Send RX to Arduino ----
        adr     =0x08    ;//7bit address
        dir     =0x01    ;//0:Write 1:Read
        adr     =(adr << 1) | (dir & 0x01);
        R_rx64m_SCI0_I2C_IIC_Master_Receive(adr,rx_buf,3);
	
        printf("[0]=%02x , [1]=%02x , [2]=%02x\n" , rx_buf[0] , rx_buf[1] , rx_buf[2]);
        tx_buf[0] = rx_buf[0];
        tx_buf[1] = rx_buf[1];
        tx_buf[2] = rx_buf[2];
	delay_ms(10);
    }
}
Arduino側のコード
受け取った3Byteのデータを
- 1Byte目 は+1してリード時返す
- 2Byte目 は+2してリード時返す
- 3Byte目 は+3してリード時返す
# include <Wire.h>
byte dt[4]={};
//-----------------------------------------------
// データを受信時の処理
//-----------------------------------------------
void I2C_ReceiveHandler(int howMany) {
    int i=0;
    Serial.print("Receive :") ;
    while( Wire.available() ){
         dt[i] = Wire.read();
         i++;
    }
    Serial.print(dt[0] , HEX);
    Serial.print(" ");
    Serial.print(dt[1] , HEX);
    Serial.print(" ");
    Serial.println(dt[2] , HEX);
}
//-----------------------------------------------
//リクエスト受付時の処理
//-----------------------------------------------
void I2C_RequestHandler(){
    Serial.println("Responce :") ;
    Wire.write(dt[0] + 1) ;
    Wire.write(dt[1] + 2) ;
    Wire.write(dt[2] + 3) ;
    }
//-----------------------------------------------
//初期化
//-----------------------------------------------
void setup(){
    Serial.begin(9600); 
    Wire.begin(0x08);  //I2C Address set
    Wire.onRequest(I2C_RequestHandler);
    Wire.onReceive(I2C_ReceiveHandler);
    Serial.println(" Start");
}
//-----------------------------------------------
// main loop
//-----------------------------------------------
void loop(){
  delay(10);
  // no operate
}




