いつもお世話になっております。
現在私は、
TeraTermで一文字を入力~送信
↓
TeraTermで受信、マイコン(RL78/G14)で文字を受け取る
マイコンを経由しててLCD(AQM1602XA-RN-GBW)に受け取った一文字を表示
という事をさせたく思っています。
現在詰まっている点は、TeraTermで1文字を入力してもそれがLCDに表示されない事です(シリアル通信なので、デバックでどこまでできているか確認できず…)。
シリアル通信無しの場合、文字送信が確認できています。
恐らくシリアル通信そのものか、変数による受け渡しがうまくいっていないと予想しています。
おききしたいのは、下記のコーディング内容において、どこがネックになっているかについてです。
【メイン関数内容】************************************************************************************************
void main(void){ uint8_t recv_buf ; //割り込みで受け取った文字を格納する R_MAIN_UserInit(); //割り込み許可 R_IT_Start(); //インターバルタイマスタート acc_data_Init(); //LCD初期化 R_UART0_Start(); while (1U) { if(SW1 == SW_ON) { R_UART0_Receive((unsigned char *)recv_buf,1); Send_Char_LCD(recv_buf); } }}
***********************************************************************************************************************
//【LCD初期化(動作確認済み)】******************************************************************************void acc_data_Init(void){uint8_t lcd_init_data[] = {0x38, 0x39, 0x14, 0x73, 0x56, 0x6C, 0x38, 0x01, 0x0C};uint8_t i;i2c_flag = 0;while (0 == time_flag);time_flag = 0;
for (i = 0; i < 9; i++){uint8_t data_to_send[2] = {0x00, lcd_init_data[i]};R_IICA0_Master_Send(0x3e << 1, data_to_send, sizeof(data_to_send), 1); // 2バイト送信while (0 == time_flag);time_flag = 0;while (i2c_flag == 0); /* 送信完了待ち */R_IICA0_StopCondition(); /* I2C通信終了 */while (SPD0 == 0); /* ストップ・コンディション検出待ち */}}/***********************************************************************************************************************/
//【LCD文字送信(動作確認済み)】******************************************************************************void Send_Char_LCD (uint8_t dat){uint8_t buf[2];
buf[0] = 0x40; /* DDRAMアドレスを指定 */buf[1] = dat; /* レジスタに書き込む値を指定 */
i2c_flag = 0;R_IICA0_Master_Send(0x3E << 1, buf, 2, 1);while (i2c_flag == 0); /* 送信完了待ち */R_IICA0_StopCondition(); /* I2C通信終了 */while (SPD0 == 0); /* ストップ・コンディション検出待ち */}/***********************************************************************************************************************/
RL78マイコンに深い知識はないですが、R_UART0_Receiveという関数の説明ではその後にR_UART0_Startを呼び出すようになっていますよ。あと、戻り値の確認はすべきです。もっと言えばデータ型も揃えるべきだと思います。uint8_tはstdint.hに定義されています。https://www.renesas.com/jp/ja/document/apn/rl78g13-serial-array-unit-uart-communication-rev200図5.10を見て書いています。
チョコです。
RL78だけは、マニュアルについてほぼ10年ながめていて、RL78/G10からは実際にハードとソフトを作成しています。
パセリを食べようさん、以下の処理は、受信が完了する前にR_UART0_Receiveから戻ってしまいます。これが誤動作の原因でしょう。IICAと同じような通信完了フラグを追加すべきです。
Shoji Yamamotoさん、参照されているアプリケーション・ノートは、あまり推奨できません。なぜなら、このサンプル・コードでは、受信完了をHALT状態で待っています。これは、他に割り込みがない場合で、受信データが1キャラクタなら使えないことはないのですが、それ以外の一般的な使い方では、正常な動作は望めません。(実際に、初心者が同じようにHALTで通信完了待ちを行い、別の割り込みでHALTが解除されてしまい、正常に動作しなかった書き込みがありました。)パセリを食べようさんも同じところでトラブっているようです。
わたしは、「R5F1006AでUART送信が上手くいかない」という以下のスレッドで
https://community-ja.renesas.com/cafe_rene/forums-groups/mcu-mpu/rl78/f/forum18/10504/r5f1006a-uart
簡単な通信完了を知る方法を紹介しています。これは、送信ですが、受信でも同様です。
また、「R_UART0_Receiveという関数の説明ではその後にR_UART0_Startを呼び出すようになっていますよ。」と言うように、実際に以下のような処理になっていて、これはコード生成の説明に記載されている順番です。
個人的には、これは気にいりません。ソフトの立場では、受信バッファがきちんとセットされてから動作させるのは当然かもしれませんが、UARTでは、受信データはいつ来るか分からないので、早めに受信準備は行っておくべきです。ところが、「R_UART0_Receive」という関数は上位ソフトが実際の受信準備段階で呼び出します。その後「R_UART0_Start」でUARTを起動するのではUARTのハードが動作するタイミングが遅くなってしまいます。私(ハード屋)は、パセリを食べようさんの順番がいいと思います。遅くなってしまうことへの対策として、「サンプルプログラム等」に「R_UART0_Start」は起動してすぐに呼び出すようにしたサンプルコードを以下の名前でアップしています。
「RL78コード生成へのリングバッファ追加」
https://community-ja.renesas.com/cafe_rene/m/sample_program/306
このサンプル・コードでは、「R_UART0_Receive」によるバッファの指定が無くても、内部のリングバッファに受信データを格納するようにしています。
ちょっと細かくなってしまいましたが、参考に。
以上
「RL78/G13 リアル・アレイ・ユニット(UART 通信)」のプロジェクトをじっくり眺めていて、おかしなことに気が付きました。(基本的に、CS+環境を対象にします。)
main関数の頭の部分は以下のようになっていました。少し気になる点がありました。それは、どこで、ベクタ割り込みを許可しているかです。
そこで、プロジェクト・ツリーを眺めると以下のようになっていました。
これは明らかにあるべきファイルがありません。それは、スタートアップ・ルーチンです。それ以外に使用する内蔵周辺機能の初期化ファイルもありません。ちなみに、これをビルドすると、当然ながらエラーとなります。
ここまでひどいとは思ってはいませんでした。どうも、他の環境で作成された明示的なファイルだけをCS+環境に持ってきただけのように思われます。
最初は、受信完了のコールバック関数で「g_Uart0RxErr = 0U」とやっていること(フラグの使い方)を問題にしようとしたのですが、そこまでたどり付けませんでした。
この問題はルネサスに報告して、対処してもらうことにします。
CA78K0Rはここ数年ほとんど使ってなかったので、誤解していました。CA78K0Rではプロジェクト・ツリーにはスタートアップ・ルーチンは出てきませんでした。
どうもCC-RLに慣れすぎてしまって、それとの差が気になってしまっていたようです。
それでも、エラーが出たのは間違いありません。情報を整理するために新しいプロジェクトを作成してコード生成したところ、元のプロジェクトでもエラーは出なくなりました。今回使っていたPCではCA78K0Rでプロジェクトを作成したことはなかったので、今回のような状態になったようです。
ということで、このサンプル・コードでは、「g_Uart0RxErrという変数を2つの異なる使い方をしている」という問題があることで、あまり参照しない方がいいという結論です。
また、1キャラクタ受信して、4キャラクタを応答するという動作を実現するために、送信中には受信割り込みをマスクしてしまっているという、通信を全く無視している状態になっていることからも参照に値しないと思います。
ということで、コメントを終わります。
チョコ様
正月休みの為、返信が遅くなりました。
無事LCDの表示ができました。どうもありがとうございます。
最後の仕上げとして行き詰っている部分があります。
パリティエラー、フレーミングエラーが起きた時の処理を割り込み関数内(r_cg_serial_user.cファイル内のstatic void r_uart0_callback_error(uint8_t err_type))に書きたいと思っていますが、記述関数はこちらで良いのでしょうか?また、この関数は、コーディング内容に該当するエラーが生じたら、自動で呼び出される関数なのでしょうか。
UARTシリアル通信.pdf
↑を参考にしてみましたが、こちらのサンプルコードではmain関数に書かれている為、
割り込みで実現したい場合についてご教授頂ければ幸いです。
①r_cg_serial_user.cファイル内のどの関数にコーディングすればいいか
②パリティは無しで設定しているので、そうでない場合(エラー時)の処理
(レジスタやビットを操作すればいいのか?)
②フレーミングエラーの検出の仕方のコーディング
について行き詰っています。
>パリティエラー、フレーミングエラーが起きた時の処理を割り込み関数内(r_cg_serial_user.cファイル内のstatic void r_uart0_callback_error(uint8_t err_type))に書きたいと思っていますが、記述関数はこちらで良いのでしょうか?
割り込みの中に記述するなら、そこになりますが、お勧めできません。なぜなら、エラー処理を実行している最中には、他の割り込み(受信割り込み等)を処理できなくなるからです。
>①r_cg_serial_user.cファイル内のどの関数にコーディングすればいいか
コード生成のUART0関係の割り込みは以下に示す3関数になります。
上から、受信完了割り込み、受信エラー割り込み、送信完了割り込みです。受信の場合、エラーが検出されなかった場合には、「・・・・_receive」割り込み関数が起動されます。エラーが検出された場合には、「・・・・_error」割り込み関数が起動されます。その処理内容は下に示すコード生成プレビューに示すようになっています。
ここで、実際のエラー処理は以下のようになっています。
SSR01レジスタがUART0の受信関係のステータスを示していて、その中の下位3ビットが受信エラー関係を示しています。ハードウェア マニュアルには以下のように説明されています。
FEFはフレーミング・エラー(ストップビットがハイでなかった)、PEFはパリティ・エラー、OVFはオーバーラン・エラーを示しています。
この状態はSIRレジスタでクリアされるまで、保持されます。
>②パリティは無しで設定しているので、そうでない場合(エラー時)の処理
動作モードでパリティなしに設定すると、パリティ・エラーは発生することはありません。(何もやる必要はありません。)
お待たせしております。
教えて頂いた通りにレジスタを操作するよう割り込みにかけたら、おかげ様で解決に至りました。
今回は割り込みでエラーを検出してみるということでしたので、今回はこの仕様のままで問題ありません(あくまで割り込みでできるという確認がしたかったので)。