| |
RL78/F24、F25マイコンではスマートコンフィグレータを用いることにより、CAN通信もレジスタを直接操作するよりは容易に使うことができます。
レポートNO.0106 で作成した、タイマーのカウンタ機能によるLチカのプロジェクトを改造して、使ってみます。
最初にクロックの設定を行います。
クロックについては、制限事項があります。これを守らないと、正しくCAN機能が使用できません。
CAN機能の動作で使用するクロックfCANの周波数は、マイコンの演算回路等で使用されるクロックfCLK(CPU/周辺ハードウェア・クロック周波数)と同一かそれよりも低い必要があります。
このときのfCLKとfMP(メイン/PLL 選択クロック周波数)との関係は、fMPの半分の周波数がfCLKの周波数となるように設定しなければなりません。
以上のことは、ハードウェアマニュアル(R01UH1061JJ0120 Rev.1.20)の1318ページ目に明記されています。
ですがスマートコンフィグレータではこの点についての警告やエラー等は一切表示されませんので注意が必要です。
今までのfCLKは初期値の32MHzで使用していましたが今回は上限の40MHzとなるように設定し、fMPが2倍の周波数となる80MHzに設定します。
スマートコンフィグレータのクロックタブを開き、左上にある「基本周波数」を「80」MHzに変更します。
その下の高速オンチップ・オシレータの「周波数」も「80」MHzに変更します。
右側にスクロールし、「分周器」が「x1/2」となって、「fCLK」が「40000」kHzとなっていることを確認します。
下のほうにスクロールし、タイマRDクロックにビックリマーク付いていると思います。
クロック選択スイッチは、下側(1/2へ分周前のクロック)を選択します。
選択を切り替えると、ビックリマークが消えます。
クロック周波数を変更したことにより、今まで使用していたLチカ用タイマーのクロックソースにビックリマークが付いてしまいます。これはクロックを上げたことによって、設定値までカウントできなくなったためです。
クロックソースを変更して、分周比を変更することによってエラーが消えます。
今回は、「fCLK/2^9」に切り替えました。
では、CAN用のコンポーネントを追加しましょう。
コンポーネントタブを開き、赤矢印のコンポーネントの追加ボタンを押します。
なぜか標準状態では、CANのコンポーネントが含まれていません。
下のほうにある「RL78 Software Integration Systemモジュールをダウンロードする」をクリックします。
インターネット経由でダウンロードが発生するため、ネットと繋がってない環境ではダウンロードできません。
「RL78/F25 RS-CANFD lite モジュール Software Integration System...」にチェックを入れて、「ダウンロード」ボタンを押します。
免責事項が表示されますので、「Accept」をクリックします。
ダウンロードが開始されるので、しばらく待ちます。
赤矢印のコンポーネントアイコンをクリックし、「ミドルウェア」->「ジェネリック」->「r_rscanfd_rl78」をクリックしてプロパティを表示させます。
「Use CAN channel 0」は、チェックを入れて「CAN0 Use」に変更します。
「Channel Mode (Classical / FD)」は、今回はCAN FDを使用しないので「(Classical CAN only mode」に変更します。
「Nominal Baudrate Settings」は、CANの通信速度を設定します。RENESAS独特なTqという概念で設定します。
では、設定値の考え方について説明しましょう。
通信速度やTqの考え方は、ハードウェアマニュアルの1316ページ目に記載されています。
この説明だけでは意味不明ですよね。
ハードウェアマニュアル(R01UH1061JJ0120)、1544ページ目にある「表19-26 ノミナル・ビットのボー・レート設定例」には、クロックfCLKとCAN通信速度の関係表があります。
今回は、fCLKが40MHz、CANの通信速度は500kbpsで使用しますので、ピンク枠内の「8Tq(10)」もしくは「20Tq(4)」が設定値となります。この()内の数値は分周比です。例えば20Tq(4)の場合、40MHzを分周比1/4で分周させるので、10MHzとなります。Tqとは、この分周されたクロック周波数の1周期分を指します。ですのでこのときの1Tqは0.1usとなります。500kbpsのとき、1ビット分の周期は2usとなります。1ビット分に必要なTq数は、2us÷0.1us = 20Tq となります。ですので、設定値は「20Tq(4)」となります。
と具体的に説明されれば、なるほど!と分かると思います。
でもホントに分かりにくいですよね、これ。
で、20Tqをどうやって振り分けるかが、TSEG1、TSEG2、SJW です。SSは1固定で、合計値20Tqには含まれません。
TSEG1、TSEG2、SJW は、信号1ビット分の時間内で各処理にどれくらい時間を使うかの設定値です。こんなのいちいち設定する必要性ってあるのでしょうか?拘りたい人向けに、RAマイコンのFSPみたいにオプションでマニュアル設定できるようにすべきです。
ハードウェアマニュアル(R01UH1061JJ0120)、1542ページ目にある「表19-25 ビット・タイミング設定例」には、振り分けの推奨値が記載されています。
赤枠内が、8Tqと20Tqにおける振り分け方の推奨値です。今回は20Tqを使用し、TSEG1=13、TSEG2=6、SJW=1 の条件を使用します。
なお、RL78 F24、F25 におけるCAN通信の仕様詳細については、ルネサス発行のアプリケーションノート R01AN6464JJ0100
「RS-CANFD lite コンフィグレーション、受信、送信」にて確認できます。
で、設定画面に戻って、「TSEG1=13、TSEG2=6、SJW=1」の値を入れます。
「Channel Nominal Baud Rate Prescaler」は、分周比を指定します。今回は、500kbps、fCLK=40MHz、20Tq(4)を使用しますので、()内の分周比から1引いた値を入力します。今回は分周比=4 ですので、1引いた3が設定値です。
「Nominal Time Segment 1」は、TSEG1 の値を入力します。
「Nominal Time Segment 2」は、TSEG2 の値を入力します。
「Nominal Resynchronization Jump Width」は、SJW の値を入力します。
次に受信設定を行います。
CANメッセージを受信する方法には、「メッセージボックス」を使う方法と「受信FIFOバッファ」を使う方法があります。
メッセージ方法は、CAN ID、メッセージフォーマット、DLCなどの値を予め設定しておき、そのメッセージのみ受信できます。
受信FIFOバッファは、とりあえずすべてのメッセージを受信対象としますが、CAN IDやDLC、メッセージフォーマット等でフィルタリングして受信条件を絞ることもできます。
今回は受信FIFOバッファでメッセージを受信します。
「RXMB and FIFOs Settings (Shared buffers up to 16)」->「RX FIFO0 Depth Configuration」の値を、最小の「4 Messages」に変更します。
自動車の車載におけるCANメッセージは最新の値を使うのが基本です。古い値をバッファしておいても意味がない程度では済まなく、間違った制御をして人命を危険に晒すことになります。
※ただし例えばフリーズフレームデータなどのイベント的な内容に関するメッセージは残す必要があります。
メッセージ受信時には割り込みを発生させて、メッセージの受信処理を行います。
「Global Interrupt Settings」->「CAN0 global receive FIFO interrupt Use」の値を「Use」に変更します。
Use/Unuse ではなく、一般的な Enable/Disable で設定できるようにすべきだと思いますが、
この辺りの考え方も全体的な分かりにくさを示す一例として挙げてもよいのではないでしょうか。
割り込み発生時に呼び出される関数名は、任意に変更できます。今回は初期値の「my_can0_glb_rxfifo_callback」をそのまま使用します。
「RX FIFO0 Interrupt Enable」を「Interrupt Enabled」に変更します。
「RX FIFO0 Interrupt Mode」を「at the end of every received message storage」に変更します。
「RX FIFO0 Interrupt Generation Counter Value (RFIGCV)」を「when FIFO is 1/4 Full」に変更します。
上記の設定のみだと、なぜか受信割り込みが発生しません。
「Channel Interrupt Settings」->「CAN0 transmit/receive FIFO receive interrupt Use」を「Use」に変更する必要があるようです。
有効にすると、送受信兼用のCommon FIFO用の割り込み関数「CAN0 transmit/receive FIFO receive interrupt callback」も有効になってしまうので、どこかに空の関数my_can0_cfifo_rx_callbackを配置しないとコンパイルエラーになってしまいます。
送信バッファについては、特に設定する項目はありません。
最後にCAN0のCTXD0端子とCRXD0端子を「使用する」にします。
スマート・コンフィグレータの「端子」タブを開き、「CANインタフェース」の「CAN0」について「使用する」に変更し、端子番号を36、37へ変更します。
CANメッセージの送信は、今回は定期送信で行いますのでタイマーを追加します。タイマーは、TAU10を使用します。
タイマーの使い方は、レポートNo.0104 などと同じです。
今回は20ms周期で送信を行います。
以上で設定完了です。最後にコードの生成を実行して終了します。
プロジェクトツリーを確認すると、CAN関係のコードが追加されています。関数や構造体等の仕様については、追加されたドキュメントの r01an7347jj0100-rl78f25.pdf に記載されています。
マニュアルの r01an7347jj0100-rl78f25.pdf を読んでみると、r_rscanfd_rl78_config.h という記載があります。
追加されたコードの一覧にはないため、どこにあるのか探してみたところ「r_config」の中にありました。
ちなみにr_rscanfd_rl78_config.h で設定できるパラメーターはスマートコンフィグレータ上で設定できるので、直接コードをいじって設定変更する必要はありません。うーん、分かりにくいですね。
では、main.cのコードを追記修正します。
まずは宣言部分です。CAN関係の関数を使用するため、r_rscanfd_rl78_if.h と r_rscanfd_rl78_config.h をインクルードします。するとiodefine.h が重複するエラーが発生しますので、iodefine.hをコメントアウトします。
定期送信用で追加したタイマー用の Config_TAU1_0.h も追加します。
受信したメッセージを格納する構造体は、今回はグローバルで宣言しました。
処理に応じて関数内で宣言してもかまいません。
main.c 宣言部分
次にmain関数内の処理です。
CANを使うのに必要な初期処理を追加します。
受信ルール設定をキチンと行わないと、メッセージが受信できません。
定期送信用に追加した、タイマーをスタートさせる関数も呼びます。
main関数
main.c の一番下あたりに、CANの受信割り込みで呼び出される関数を追加します。
FSPみたいにドラッグ&ドロップできないので手書きで追加します。
実際に呼び出されるのは「 void my_can0_glb_rxfifo_callback (uint16_t arg)」のみですが、
割り込みを発生させるために有効にした「void my_can0_cfifo_rx_callback (uint16_t arg)」も
どこかに記載しないとコンパイルエラーとなるため、空の関数も一緒に追加します。
引数であるargの値がよく分からないのですが、とりあえず受信できた場合は1が返ってくるようです。
R_CAN0_ReadRXFIFO関数で、受信メッセージをFIFOバッファから取得します。
次は、CAN ID の判定を行います。今回は CAN ID = 0xFE0010 を受信したときに処理を行うようにするため、そのように記載します。今回は、データの1バイト目が0xFFの場合はLチカON、0x00の場合はLチカOFFとするため、そのように処理を書きます。
Lチカの処理内容については、レポートNO.0106 を参照してください。
受信FIFO割込用 my_can0_cfifo_rx_callback関数、my_can0_glb_rxfifo_callback関数
定期送信は、今回追加した TAU1_0 を使用して行います。
Config_TAU1_0_user.c 内の処理は、以下のように追加します。
宣言部分は、main.cと同じようにCAN関係の関数を使用するため、r_rscanfd_rl78_if.h と r_rscanfd_rl78_config.h をインクルードします。
送信するメッセージを格納する構造体は、今回はグローバルで宣言しました。
処理に応じて関数内で宣言してもかまいません。
今回は送信メッセージに送信毎にカウントアップさせるデータを載せるため、カウントアップ用の変数をグローバルで宣言します。
Config_TAU1_0_user.c 宣言部分
r_Config_TAU1_0_interrupt()関数内の処理です。
最初に送信するCANメッセージを設定します。
tx_frame はグローバル変数(構造体)として宣言していますので、
変わらない値は1度設定すれば良いのですが、今回は分かりやすいように毎回設定しています。
IDEは、メッセージタイプが11bit標準CANなのか、29bit拡張CANなのかを指定します。
FDCTRは、基本的にCAN FDを使用するときのみに指定します。今回は普通のCANを使用するため、0固定です。
1バイト目のdata[0]には、LED_0 の点灯状態を出力します。
7バイト目のdata[6]には、0〜255の範囲で送信ごとにカウントアップさせた値を格納します。
8バイト目のdata[7]には、7バイト目をビット反転させた値を格納します。
メッセージごとに異なる値を入れることで、送信側の処理がフリーズしている、送信側がAck信号を受信できずに同じメッセージ送信をリトライしている等の異常な状態であるかが判断できるようになります。ホンダさんは昔からこれやってますね。
最後に、R_CAN0_SendByTXMB関数を使用して送信します。今回は送信メッセージボックスのChannel 0を使用するので、CAN_TXBUF0 を指定します。
以上でコードの追記修正は完了です。
プロジェクトをビルドして、デバッグでマイコンを動作をさせます。CANメッセージの送受信は相手側も必要ですので、ツールを使って動作を確認します。
r_Config_TAU1_0_interrupt 割込関数
|