はじめに
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受信、送信データを受信データで書き換える動作をします。
main.c
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
}