stlと申します。
RA2E1マイコンで簡易I2Cの機能を使用しています。デバッグを実行してみると、送信用のAPI関数の戻り値としては「成功」となりますが、オシロスコープでピンの出力を確認すると、SDAとSCLKの出力波形が確認できず、関数の実行タイミングで5Vから0Vに変化するだけでした。 この問題について何かわかることがありますでしょうか?
チョコです。
RL78は日頃使っていますが、RAは使ったことがありませんので、想像になりますが、コメントさせてもらいます。
おそらく、SCを使ってコード生成されていると思いますが、送信用のAPIは送信処理を起動するだけで戻ってきている
のではないでしょうか。
また、「SDAとSCLKの出力波形が確認できず、関数の実行タイミングで5Vから0Vに変化するだけでした。」は、
スタート・コンディションが発行された状態ではないかと思います。
つまり、通信が開始した時点までの波形しか確認していないのではないでしょうか。
通信が完了したことを確認して、そこまでの波形を確認されることをお勧めします。
以上
ご回答ありがとうございます。
>>通信が完了したことを確認して、そこまでの波形を確認されることをお勧めします。
送信用のAPIが、通信が完了までいかなくても起動した段階で「成功」を返してきている可能性があるということでしょうか?
>送信用のAPIが、通信が完了までいかなくても起動した段階で「成功」を返してきている可能性があるということでしょうか?
はい、そうです。通信関係のAPIのこのことがかふぇルネでも結構問題になっていました。
RAのSCは見たことはありませんが、RL78やRXのSCの通信関係のAPIは通信完了まで待たずに戻ります。
RL78のSCAPIマニュアルをダウンロードしたところ、いつの間にか戻り値がなくなっていました。
これだけでは、判らないので、RL78/G15で実際にIIC00で送信APIを生成してみました。
下のように、スレーブアドレスをIIC00に書き込んだところで戻っています。また、APIマニュアルの記述のように戻り値はなくなっています。
SCは少なくともベアメタルでのマルチタスクをサポートしているので、通信完了を待つことはありません。
これは、RAでも同じだと思われます。(出ている症状からも送信完了を待たないのは明らかです。)
APIの戻り値が送信完了を示しているわけではないとしたら、送信が完了していることの確認は、オシロスコープでそこまでの波形を見る以外方法はないということになるのでしょうか?
あくまで、RL78/G15のケースですが、以下に示すIIC00の割り込み処理(Config_IIC00_user.cの「r_Config_IIC00_interrupt関数)の中で、指定した数のデータの送信が完了すると、147行目で r_Config_IIC00_callback_master_sendend関数を呼び出しています。
このr_Config_IIC00_callback_master_sendend関数で完了したことを示すフラグをセットするような処理を書き込むことができるようになっています。この、74行目と75行目の間にそのような処理を追加することになります。
ここまで、きちんとサポートするようにずっと訴えているのですが、いまだに対応してもらっていません。
RAで類似のコールバック関数を探してそこでフラグをセットして、そのフラグがセットされるのを待つようにしてください。
RAの場合だと、コールバック関数の引数に送信完了を示す値が代入されるようになっていました。そちらを確認してみると、そもそも送信が完了しませんでした。原因を探してみます。
R_IIC_MASTER_Open
R_IIC_MASTER_CallbackSet
R_IIC_MASTER_SlaveAddressSet
SDAとSCLがLowに落ちると書いてあるのでスタートコンディションには入っていそうですが、上の3つはR_IIC_MASTER_Writeの前に実行していますよね?
OpenはAPI関数で実行しています。コールバックとスレーブアドレスセットはプロパティで設定を行っています。
RAはRLやRXとは全く違うようですね。また、RA2E1には、そもそもSCはないようですね。
どうも、FSPで処理しているようで、APIも全く異なるようです。
もしかするとOpenでスタート・コンディションを発行してI2Cバスを確保しているのですかね。
APIも全く異なるようなので、これ以上はコメントを控えさせていただきます。
簡易I2Cと書いてあるので、SCIインタフェースを使用したI2Cという様に考えて書き込みします。
RA2E1のチップで試してみましたが、特に設定をしなくても、波形がでました。
#include "hal_data.h" FSP_CPP_HEADER void R_BSP_WarmStart(bsp_warm_start_event_t event); FSP_CPP_FOOTER volatile int g_i2c_tx_flag = 0; volatile int g_i2c_rx_flag = 0; /*******************************************************************************************************************//** * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function * is called by main() when no RTOS is used. **********************************************************************************************************************/ void hal_entry(void) { /* TODO: add your own code here */ fsp_err_t err; unsigned char tx_buffer[10] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10}; R_SCI_I2C_Open(&g_i2c9_ctrl, &g_i2c9_cfg); g_i2c_tx_flag = 0; err = R_SCI_I2C_Write(&g_i2c9_ctrl, &tx_buffer[0], 1, false); if (err != FSP_SUCCESS) { __NOP(); } while(1) { //送信完了待ち if (g_i2c_tx_flag == 1) break; } while(1) { __NOP(); //送信完了 } #if BSP_TZ_SECURE_BUILD /* Enter non-secure code */ R_BSP_NonSecureEnter(); #endif } /*******************************************************************************************************************//** * This function is called at various points during the startup process. This implementation uses the event that is * called right before main() to set up the pins. * * @param[in] event Where at in the start up process the code is currently at **********************************************************************************************************************/ void R_BSP_WarmStart(bsp_warm_start_event_t event) { if (BSP_WARM_START_RESET == event) { #if BSP_FEATURE_FLASH_LP_VERSION != 0 /* Enable reading from data flash. */ R_FACI_LP->DFLCTL = 1U; /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */ #endif } if (BSP_WARM_START_POST_C == event) { /* C runtime environment and system clocks are setup. */ /* Configure pins. */ IOPORT_CFG_OPEN (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME); } } #if BSP_TZ_SECURE_BUILD FSP_CPP_HEADER BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable (); /* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */ BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable () { } FSP_CPP_FOOTER #endif void sci_i2c_master_callback(i2c_master_callback_args_t * p_args) { //SLAVEを接続していない場合 //割り込みには飛んでくるが //p_args->event == I2C_MASTER_EVENT_ABORTED if (p_args->event == I2C_MASTER_EVENT_TX_COMPLETE) { g_i2c_tx_flag = 1; } else if (p_args->event == I2C_MASTER_EVENT_RX_COMPLETE) { g_i2c_rx_flag = 1; } }
FSPの設定では、I2C_Master(r_sci_i2c)を追加しただけです。動作確認用に使ったhal_entry.cを貼り付けます。
R_SCI_I2C_Write() は、直ぐにFSP_SUCCESSを返します。(その時点ではデータ転送は行われていません。)
コールバック関数(sci_i2c_master_callback())が呼ばれて、
p_args->event == I2C_MASTER_EVENT_TX_COMPLETE
となっていれば、データ送信が完了しています。
・FSPで設定したSLAVEアドレスのデバイスがつながっている場合
→送信完了と書いてある行まで到達します
・FSPで設定したSLAVEアドレスのデバイスがつながっていない場合
→SCL, SDAから波形は出ます
→コールバック関数に来ます
p_args->event == I2C_MASTER_EVENT_ABORTED
なので、添付したサンプルでは //送信完了待ち のところで無限ループです。
(添付は送信のサンプルですが、受信の場合は、g_i2c_rx_flag ==1 を待てば、受信データの処理に移って良いです。)
SCL, SDAのラインに外部でプルアップ抵抗は付けていますか?
FSPの端子設定のところで、SCL, SDA端子を選択していますか?
動かないとすれば、その辺りかな?と思いますが。
性懲りもなく、また書き込んでいます。
このFSPのようなフラグをコード生成の時代からずっと要求していたんですヨ。
>SCL, SDAのラインに外部でプルアップ抵抗は付けていますか?
これは、オリジナルのスレッドに「関数の実行タイミングで5Vから0Vに変化するだけでした。」とあるので、問題ないはずです。
>>SCL, SDAのラインに外部でプルアップ抵抗は付けていますか?
>これは、オリジナルのスレッドに「関数の実行タイミングで5Vから0Vに変化するだけでした。」とあるので、問題ないはずです。
問題は抵抗値が大きすぎないかもありますね。過去には、数十kΩでプルアップしていて動かないなんて例もありましたね。
実際に、動作して確認していただいてありがとうございます。おしゃるとおり、SCIインタフェースを使用したI2Cを使っています。添付いただいたプログラムと同じようにプログラムを書いているのですが、p_args->event == I2C_MASTER_EVENT_TX_COMPLETEとはならないですね。
EEPROMに接続しているのですが、EEPROMの仕様書を見ると、SDASCLはプルアップ抵抗を介して、Vccに接続されていると記載してあるので、プルアップ抵抗は接続されているはずです。
FSPの端子設定も行っています。
プルアップ抵抗はEEPROMに備え付けられているものなので、具体的な抵抗値は分からないですが、そこまで大きなものではないとは思っています。
プルアップ抵抗が内蔵されたチップがあるんですね。それなら、おそらくデータシートの電気特性の項目に抵抗値の範囲が書いてあると思います。
測るのは簡単です。装置の電源を落としてSCLとVcc(EEPROMの電源)、SDAとVccの抵抗値ですね。
仕様書を改めて確認すると、プルアップ抵抗は自分で接続する必要があるということのようでした。
英語だったのでニュアンスが読み取れていなく、「プルアップ抵抗が接続されています」ということだと思っていたのですが、そのように接続してくださいと意味なんだと理解しました。
通信が上手くいかない原因の一つは、プルアップ抵抗を接続していなかったからだと思います。ただ、tfさんによると、デバイスに接続していなくても波形は出るみたいですので、プルアップ抵抗を接続していなくても波形は出るのでないかと思ったのですが、それ以前にも原因があるのではとも思いました。
実際にプルアップ抵抗を接続して、動作を確認してみます。
「The I2C bus consists of two ‘wires’, SCL and SDA. Thetwo wires are connected to the VCC supply via pull−upresistors. Master and Slave devices connect to the 2−wirebus via their respective SCL and SDA pins.」