RL78/G1D 簡易i2cのやり方について

初めまして。恐らく初歩的な質問となると思うのですが、よろしければご教授お願い致します。

使用している総合開発環境はCS+forCCです。

RL78/G1D R5F11AGJ の簡易i2cを使用して6軸加速度センサLSM6DS3との通信を実現したいと思っています。

今まではArduinoを使用していたのですが、諸事情によりRL78/G1Dに変更することになりました。

ハードウェアマニュアルやサンプルプログラムを見ながら試行錯誤しているのですが、いまいち要領を得ません。

シリアルアレイユニットのIIC00をコード生成後、加速度センサの値を読みたい時のおおまかな流れは以下の様な理解で良いのでしょうか?

/*********************************************************************************************/

R_SAU0_Create()/*シリアルアレイユニット0、IIC00初期設定*/

R_IIC00_Master_Send(uint8_t slave_address,uint8_t register_address,1)/*スレーブアドレス、アクセスするレジスタアドレス、バッファーサイズを指定*/

/***r_iic00_interrupt()により転送完了割り込みが発生,アドレスフィールド送信***/

R_IIC00_Master_Receive(uint8_t slave_address, (uint8_t *)data_address, buffer_size) /*data_addressはスレーブから受け取ったデータを格納*/

/***r_iic00_interrupt()により転送完了割り込みが発生,data_addressに指定したレジスタアドレスの値をバッファーサイズ分格納***/

 

/*********************************************************************************************/

割り込み処理についてよく理解ができておらず、その辺りの流れに頭を悩ませております。

この様なちゃんとした?マイコンを扱うのが初めてで、右も左もわからない状態なのですが是非よろしくお願いいたします。

 

 

以下にコード生成されたMaster_Send,Master_Receive,r_iic00_interruptのソースを貼ります。

/***********************************************************************************************************************
* Function Name: R_IIC00_Master_Send
* Description : This function starts transferring data for IIC00 in master mode.
* Arguments : adr -
* set address for select slave
* tx_buf -
* transfer buffer pointer
* tx_num -
* buffer size
* Return Value : None
***********************************************************************************************************************/
void R_IIC00_Master_Send(uint8_t adr, uint8_t * const tx_buf, uint16_t tx_num)
{
g_iic00_master_status_flag = _00_SAU_IIC_MASTER_FLAG_CLEAR; /* clear IIC00 master status flag */
adr &= 0xFEU; /* send mode */
g_iic00_master_status_flag = _01_SAU_IIC_SEND_FLAG; /* set master status flag */
SCR00 &= ~_C000_SAU_RECEPTION_TRANSMISSION;
SCR00 |= _8000_SAU_TRANSMISSION;
/* Set paramater */
g_iic00_tx_count = tx_num;
gp_iic00_tx_address = tx_buf;
/* Start condition */
R_IIC00_StartCondition();
IICIF00 = 0U; /* clear INTIIC00 interrupt flag */
IICMK00 = 0U; /* enable INTIIC00 */
SIO00 = adr;
}
/***********************************************************************************************************************
* Function Name: R_IIC00_Master_Receive
* Description : This function starts receiving data for IIC00 in master mode.
* Arguments : adr -
* set address for select slave
* rx_buf -
* receive buffer pointer
* rx_num -
* buffer size
* Return Value : None
***********************************************************************************************************************/
void R_IIC00_Master_Receive(uint8_t adr, uint8_t * const rx_buf, uint16_t rx_num)
{
g_iic00_master_status_flag = _00_SAU_IIC_MASTER_FLAG_CLEAR; /* clear master status flag */
adr |= 0x01U; /* receive mode */
g_iic00_master_status_flag = _02_SAU_IIC_RECEIVE_FLAG; /* set master status flag */
SCR00 &= ~_C000_SAU_RECEPTION_TRANSMISSION;
SCR00 |= _8000_SAU_TRANSMISSION;
/* Set parameter */
g_iic00_rx_length = rx_num;
g_iic00_rx_count = 0U;
gp_iic00_rx_address = rx_buf;
/* Start condition */
R_IIC00_StartCondition();
IICIF00 = 0U; /* clear INTIIC00 interrupt flag */
IICMK00 = 0U; /* enable INTIIC00 */
SIO00 = adr;
}

/***********************************************************************************************************************
* Function Name: r_iic00_interrupt
* Description : None
* Arguments : None
* Return Value : None
***********************************************************************************************************************/
static void __near r_iic00_interrupt(void)
{
if (((SSR00 & _0002_SAU_PARITY_ERROR) == 0x0002U) && (g_iic00_tx_count != 0U))
{
r_iic00_callback_master_error(MD_NACK);
}
else if(((SSR00 & _0001_SAU_OVERRUN_ERROR) == 0x0001U) && (g_iic00_tx_count != 0U))
{
r_iic00_callback_master_error(MD_OVERRUN);
}
else
{
/* Control for master send */
if ((g_iic00_master_status_flag & _01_SAU_IIC_SEND_FLAG) == 1U)
{
if (g_iic00_tx_count > 0U)
{
SIO00 = *gp_iic00_tx_address;
gp_iic00_tx_address++;
g_iic00_tx_count--;
}
else
{
R_IIC00_StopCondition();
r_iic00_callback_master_sendend();
}
}
/* Control for master receive */
else
{
if ((g_iic00_master_status_flag & _04_SAU_IIC_SENDED_ADDRESS_FLAG) == 0U)
{
ST0 |= _0001_SAU_CH0_STOP_TRG_ON;
SCR00 &= ~_C000_SAU_RECEPTION_TRANSMISSION;
SCR00 |= _4000_SAU_RECEPTION;
SS0 |= _0001_SAU_CH0_START_TRG_ON;
g_iic00_master_status_flag |= _04_SAU_IIC_SENDED_ADDRESS_FLAG;

if (g_iic00_rx_length == 1U)
{
SOE0 &= ~_0001_SAU_CH0_OUTPUT_ENABLE; /* disable IIC00 out */
}

SIO00 = 0xFFU;
}
else
{
if (g_iic00_rx_count < g_iic00_rx_length)
{
*gp_iic00_rx_address = SIO00;
gp_iic00_rx_address++;
g_iic00_rx_count++;

if (g_iic00_rx_count == (g_iic00_rx_length - 1U))
{
SOE0 &= ~_0001_SAU_CH0_OUTPUT_ENABLE; /* disable IIC00 out */
SIO00 = 0xFFU;
}
else if (g_iic00_rx_count == g_iic00_rx_length)
{
R_IIC00_StopCondition();
r_iic00_callback_master_receiveend();
}
else
{
SIO00 = 0xFFU;
}
}
}
}
}
}

Parents
  • チョコです。

    RL78の割り込みを使ったシリアル制御でのコード生成されたAPIは基本的に,
    "R_IIC00_Master_Send"関数はスレーブへのデータ送信の起動を行い,
    スレーブ・アドレスを送信開始しただけで戻ってきます。
    ("R_IIC00_Master_Receive"関数も同様です。)
    指定されたデータの送信が完了したかどうかは,INTIIC00割り込み
    ハンドラーで判断しています。
    そこで,コード生成された"r_cg_serial_user.c"ファイルの中に
    "r_iic00_callback_master_sendend"関数が定義されています。
    指定されたデータの送信が完了したら,この関数が呼び出されるので,
    そこに「通信ステータスを示すフラグ」を送信完了にセットする処理
    を記述してください。(そのフラグは,"R_IIC00_Master_Send"関数を
    呼び出すときにクリアしておいてください。)
    送信がエラーになった(スレーブが存在しなかった等,スレーブ
    からACK応答がなかった)場合には,"r_iic00_callback_master_error"
    関数が呼び出されるので,そこには「通信ステータスを示すフラグ」
    を「通信エラー」にセットする処理を記述してください。
    "R_IIC00_Master_Send"関数を呼び出したら,そのフラグが「送信完了」
    にセットされるのを確認することで,送信完了を知ることができます。
    また,「通信エラー」になっていたら,スレーブが正常に応答しなかった
    ことが分かります。
    同様に,"R_IIC00_Master_Receive"関数で,指定されたデータの受信が
    完了したときには,"r_iic00_callback_master_receiveend"関数が
    呼び出されるので,「通信ステータスを示すフラグ」を「受信完了」に
    セットする処理を記述してください。
    (こういったフラグ類は,コード生成で準備してもらえば,使う方は
    割り込み処理の中を気にしなくて楽なんですが。)

    とにかく1バイトの送受信ごとに,INTIIC00が発生するので,そんなのは
    無視(勝手にやらせておいて)結果だけを確認して制御するようにして
    ください。

    また,RL78でのスレーブ・アドレスは8ビットで表現しているので,
    LSM6DS3の1101010bや1101011bは0xD4や0xD6と表してください。

    個人的には,コード生成されたシリアル関係のAPIは余り好きではないので,
    通常は自分で作ったライブラリを使っています。
  • チョコ様、丁寧なご回答ありがとうございます。フラグを立てればいいのですね!
    もう一つお聞きしたいのですが、レジスタの値をnバイト読むとき、tx_numで指定した分が だけ渡したレジスタアドレスに読まれるのでしょうか?
    if (g_iic00_rx_count < g_iic00_rx_length)
    {
    *gp_iic00_rx_address = SIO00;
    gp_iic00_rx_address++;
    g_iic00_rx_count++;
    ここの記述の部分なのですが
    例えばレジスタアドレスが0x002Bで、tx_numが2だとしたら0x002Bの値が*gp_iic00_rx_addressに代入され、0x002Cの値がが*(gp_iic00_rx_address+1)のアドレスに代入されるという認識でよろしいでしょうか?
    お手数おかけしますが、宜しければご回答よろしくお願いします。
  • チョコです。
    >レジスタの値をnバイト読むとき、tx_numで指定した分が だけ渡したレジスタアドレスに読まれるのでしょうか?
    指定した数の読み出した(I2Cバスから受信した)レジスタの値が,指定された受信データのバッファ領域に順番に格納されていきます。

    >例えばレジスタアドレスが0x002Bで、・・・・
    はい,そうです。
    最初に受信したデータ(=0x002Bの値)が指定されたバッファ・アドレス(*gp_iic00_rx_address)に格納され,次のアドレス(*(gp_iic00_rx_address+1))には次のデータ(=0x002Cの値)が格納されていきます。
  • チョコです。
    鈴木さん,現状の通信関係のコード生成されたAPIでは,慣れた人でないと使い辛いです。他のスレッドでも同様の書き込みがありました。改版(フラグ管理の追加)の検討をよろしくお願いします。
    (ついでに,ドキュメントも是非見直してください。)

    japan.renesasrulz.com/.../rl78-g13-csi
Reply Children
No Data