こんにちは
G10にてCS+のコード生成プラグインのR_IICA0_Slave_Sendを使用して送信をしようと思っています。
二つ目の引数に2を入れて送信したところ、受け側は0xXX 0xFFとなります。1バイト目は〇なのですが、
2バイト目が0xFFになります。どのようなことが考えられますか?
チョコです。
何か誤解があるようなので、少しコメントしておきます。
I2Cバスの仕様では、マスタが受信(スレーブ送信)を終了するときには、スレーブから受信した最後のデータに対してACK応答をしない(NACK応答をする)という規定があります。これは、I2Cバスのハード的な制約(信号がローに引かれた状態は、マスタといえどもハイにすることはできない)に対するもので、「受信を終了するからスレーブにそれ以上データを送るな…
具体的にどのようなタイミングで、どのようにデータを確認しているのでしょうか。
R_IICA0_Slave_Sendや対になったR_IICA0_Master_Receiveで通信が完了したことをどのようにして判断しているのでしょうか。
わたしは、基本的に、コード生成されたAPI関数は使えないと判断して、初期設定だけしか使っていません。(それ以外の部分は自前で作成しています。)コード生成されたコードの問題点として、昔から指摘しているのが、通信の完了をきちんとサポートすべきだということです。これは、他の通信でも共通している内容です。
具体的なプロジェクトを開示(zipで固めて添付)してもらえれば、チェックしてみますが。
以上
初期設定して自前で作る実力をつけたいです。
ところで、今回の相手はルネさんでないです。たぶんマスターとして動作しています。2バイトを読む感じです。
通信の完了が大切ということですが、RL78はひたすら送信です。
uint16_t tx_num=2; uint8_t tx_data[]={0}; tx_data[0]=0x20; tx_data[1]=0x40; f=0; R_IICA0_Slave_Send(tx_data,tx_num); R_IICA0_Set_WakeupOn();//r_iica0_callback~が発生したら終了か待機R_IICA0_Set_WakeupOff();
0x40が相手さんでは0xFFとなっています。相手が悪いという線も並行して考えています。
もう一ヵ所気になりました。以下に示すのは、おそらく、マスタからのNACK応答だと思うのですが、これは正常終了するところですが、returnでいいのですか?
if(f==99){ //callback_slave_errorが発生したら NOP(); return;
コメントの間違いっぽいです。すみませんでした。
static void r_iica0_callback_slave_error(MD_STATUS flag){ f=99;}
static void r_iica0_callback_slave_receiveend(void){ f=1;}
static void r_iica0_callback_slave_sendend(void){ f=11;}
flag=2
なのでNACKでしょうか。
I2Cバスの仕様では、マスタが受信(スレーブ送信)を終了するときには、スレーブから受信した最後のデータに対してACK応答をしない(NACK応答をする)という規定があります。これは、I2Cバスのハード的な制約(信号がローに引かれた状態は、マスタといえどもハイにすることはできない)に対するもので、「受信を終了するからスレーブにそれ以上データを送るな」の意味を持っています。こうすることで、マスタはI2Cバスを制御できるようになり、次の処理(ストップコンディションの発行)を行えるようになります。
初心者は、「受信したデータがおかしいからNACK応答になった」とよく誤解しているようですが、それは間違いです。
と言うことで、スレーブでは「f=99」が正常な終わり方です。以前のコメントの最後で「スレーブの仕様としては、必ず2バイト送信するようになっているのでしょうか。マスタが1バイトで受信をやめることを許していますか。」と書いたのは、このようなI2Cバスの仕様に沿っているかを確認したかったからです。
なお、RL78/G10をI2Cバスのスレーブとして使用した例は、以下の所にあります。
かふぇルネの「Forums & Groups」をクリックして、
その飛び先のページの一番下の「サンプルプログラム等」をクリックした先にあります。
ここから行ってもいいのですが、RL78/G10をI2Cバスのスレーブとして使用した例は、接以下のURLで飛べます。
https://community-ja.renesas.com/cafe_rene/m/sample_program/283
ここにアップされているzipファイルをダウンロードするとプロジェクトと説明のpdfがあります。
RL78/G10のIICA0のスレーブプログラムの例で、出力としてのLED,読み出し用のA/D、読み書きの対象としてのRAMがサポートされています。ちなみにコード生成は初期設定だけで、IICA0の制御は、r_iica0_lib.cとして準備されています。
I2Cの勉強をするなら、「サンプルプログラム等」にかなりプログラムや解説を投稿していますので、参考になると思います。
リンク先ありがとうございます。
RAM_BASEが0x80というのがありますが、
void R_IICA0_Slave_Send(uint8_t * const tx_buf, uint16_t tx_num)だと、どうなっているのか
という疑問がでました。
受信側からみるとコード生成の自局アドレス 仮に0x60 tx_buf[0]
0x80がtx_buf[1]ということ? 0x61?という疑問が湧きました。
RAM_BASEとスレーブアドレスは全く無関係です。
>受信側からみるとコード生成の自局アドレス 仮に0x60 tx_buf[0]
>0x80がtx_buf[1]ということ? 0x61?という疑問が湧きました。
少なくとも、スレーブアドレスはIICA0が対応しているだけで、
ユーザープログラムに対してデータとして渡される訳ではありません。
RAM_BASEはスレーブに書き込むアドレスレジスタ(1バイト目の
データ)の値の中でRAMの先頭を示すデータです。
通常、EEPROMやRAMおよび複数のレジスタを持つスレーブでは、
書き込みの最初のデータがこのようなRAMやレジスタ等のアドレスを
示します。この場合だと、アドレスが0x80以上ならRAMに対応して
いると考えてください。
つくたろうさんのスレーブはこのような内部のアドレス・レジスタは
使っていないようなので、マスタからの読み出し通信が起動されたら
単に送信するデータを順に送信するだけのはずです。
ご回答ありがとうございます。
内部のアドレス・レジスタを使うのは
uint8_t static sreg ~
というのでしょうか? 検索した感じだとショート・ダイレクト・アドレッシングでしょうか。
CS+で新規作成したファイルに宣言しても、うまくいきませんでした。どこか設定を変更する
必要があるのでしょうか。
sregですが、これは、CA78K0Rでの機能です。あのプロジェクトは、CA78K0Rで作成してあり、それをCC-RLに移植しています。
CC-RLのマニュアル(R20UT3123JJ)の移行支援機能オプションを使って移植しています。
添付されているPDFにも、CC-RLのプロパティで以下のように設定しています。
今回は最初からCC-RLなので、「sreg」ではなく、「saddr」を使ってください。
CC-RLコンパイラのマニュアルには以下のような説明があります。
ここらを参考にしてください。
ありがとうございます。