Timerより作ったDelay関数が動かない

Hi、武です。

今RL78マイコンを勉強しています。RL78/G12で規定された時間にLEDを点灯したい。ですので時間のDelay関数が必要かなと思います。

使用環境CS+ for CA/CXです。タイマのチャンネル2を使い、インターバル時間は1msを設定しています。

r_cg_timer_user.cのコード:

uint16_t counter_timer2 = 0;

__interrupt static void r_tau0_channel2_interrupt(void)
{
counter_timer2 ++;
}

中断ファイルc_cg_intc_user.cのコード:

extern uint16_t counter_timer2;

void delay_ms_1(uint16_t dlms)
{
counter_timer2 = 0;
R_TAU0_Channel2_Start();
while(counter_timer2 < dlms);
R_TAU0_Channel2_Stop();
}

ただし、動かないです。理由はタイマが起動されでも、void delay_ms_1のWhileのcounter_timer2 が変わらない。0のままです。Loopから抜かれないです。

どう修正すれば正しいDelayができるか教えていただきたいと思います。

Parents
  • 割り込みハンドラは呼び出されていますね?

    最適化が有効の場合、ファイルをまたいでの最適化でcounter_timer2が考慮されず、counter_timer2が0なのでwile文はwhile(0<dlms)として展開されていると考えられます。もしくは割り込みハンドラのインクリメントが参照がないので消されているかも。volatile宣言を追加すると解決するかもしれません。

    uint16_t counter_timer2 = 0;


    volatile uint16_t counter_timer2 = 0;

  • r_cg_timer_user.cのコード:

    volatile uint16_t counter_timer2 = 0;

    __interrupt static void r_tau0_channel2_interrupt(void)
    {
    if (counter_timer2) {

    counter_timer2--;

    }
    }

    中断ファイルc_cg_intc_user.cのコード:

    extern volatile uint16_t counter_timer2;

    void delay_ms_1(uint16_t dlms)
    {
    counter_timer2 = dlms;
    while(counter_timer2);
    }

    タイマは低い優先度で常時動作状態。私ならこう書きます。タイマの位相によって割り込みまでのタイミングが変わるので必ず指定時間より待たすならdlsms+1をセットするか、タイマの値を0から開始するコードも入れる必要があります。

  • ご回答ありがとうございます。やってみましたが、あまり変わっていないようです。確認のコードが下記になります。

    r_main.cのコード:

    void main(void)
    {
    R_MAIN_UserInit();
    /* Start user code. Do not edit comment generated here */
    R_TAU0_Channel1_Start();
    R_TAU0_Channel2_Start();
    R_KEY_Start();
    P6.3 = 1;
    while (1U)
    {;}
    }

    中断ファイルコード:

    extern volatile uint16_t counter_timer2;

    void delay_ms_1(uint16_t dlms)
    {
    counter_timer2 = dlms;
    while(counter_timer2);
    }

    タイマファイルコード:

    volatile uint16_t counter_timer2 = 0;

    __interrupt static void r_tau0_channel1_interrupt(void)
    {
    if (counter_timer2) {counter_timer2--;}
    }

    実行中のDebugモードで、Delay関数のWhile中Counter2を見ました。ずーど初期値1000のままでした。LOOPの繰り返しに、タイマが止まっているか、タイマのcounter_timer2が変わっても、Loopへの更新できないかになるかな?この方法がだめかな。。。

  • 割り込みハンドラが1ms間隔で実行されているかは確認できていますか?

  • Yamamoto様、確認しました。

    外部Keyを押さなければ、つまり、中断がなければ、タイマが普通に動いていた。Keyを押したら、中断が発生しましたので、Delay関数を呼ばれました。Delayのwhile関数条件のcounter_timer2の値は変わらないので、永遠のLoopになります。この時に、Debug状態でタイマの状態が見えなくなります。おそらく、実行されていないかなと思います。やはり、永遠のLoopから抜かないと、なんでも停止いしているように見えます。

  • チョコです。

    基本的に、割り込みを使う手順が理解できてないように見えます。

    参考になりそうな、アプリケーションノートはあるのですが、RL78/G12ではアセンブリ言語しかないようです。

    そうなると、RL78/G13にも「RL78/G13 タイマ・アレイ・ユニット(インターバル・タイマ)R01AN0456」というサンプルコードがあるので、こちらを参考にすることをお勧めします。

    RenesasのHPのトップで「R01AN0456」で検索すると、下のような結果が得られます。このサンプルコードを参照してください。

    基本的に、コード生成機能を使って必要な設定を行い、その上で必要なプログラムを作成しています。

    例えば、TM00は下に示すようにインターバルタイマで使用しています。

    TM00(チャネル0)は以下のように2msのインターバルに設定しているようです。

    生成されるファイルは以下のようになっていました。

    これをRL78/G12に持っていこうとしたのですが、私の環境では、新しいプロジェクトを作成できませんでした。これからやるなら、CA78K0R環境ではなく、CC-RL環境でやるべきでしょうね。

    ここで、タイマ割り込み部分を下に示します。

    39行目が割り込み要求(INTC00)とその処理部(R_INTC0_Interrupt)を関係づけしている部分です。これがないと割り込みは動作しません。ここらがきちんとできてないのが動作しない原因の一つであると思います。

    また、「Forums&Groups」のページのページの左下の「 チョコさんのRL教室」があります。

    その中には以下に示すような内容があるので、ここも参考にしてください。

    以上

  • チョコ様が書いているように割り込み処理の実現部分に問題があり、そこを解決しないと先には進めないです。複数の割り込み処理がちゃんと実行されるようになれば解決すると思います。

  • チョコです。

    武さん。以下の処理は、外部Keyに対応した割り込み処理の中でタイマのチャンネル2の割り込みを実行させたい(受付けさせたい)ように見えます。

    そうなると、2つのことをきちんとする必要があります。

    1つ目は、「外部Keyに対応した割り込み処理」の優先順位よりも「タイマのチャンネル2の割り込み処理」の優先順位をより優先に設定する。

    2つ目は、「外部Keyに対応した割り込み処理」の先頭で、割り込み許可(EI();)を実行すべきです。

    つまり、多重割り込みをきちんと実行する必要があるということです。

    以上

  • チョコさん、Yamamotoさん

    ご回答ありがとうございます。簡単と思いましたが、難しいのところかなと思います。もっと勉強が必要かなと思います。この件は大丈夫です。ご示教ありがとうございました!

  • チョコです。

    実は、紹介したサンプルコードは、多重割り込みを使用しないで、同じようなことを実現しようとしています。下に示すINTP0割り込み処理の中で、タイマ割り込みをHALTモードの解除に利用して、タイマ割り込みでの実処理部を普通の関数にしてあるので、その関数を呼び出すことで、INTP0割り込み処理の中で、タイマ割り込み処理を実現しています。

    個人的には、このようなやり方(長い期間割り込み処理の中に留まる)は好きではない(と言うよりやってはいけない)のですが、このようなことを行えば(サンプルコードを参考にすれば)、武さんのやりたいことはそれほど難しくなく実現はできますよ。

    それよりは、多重割り込みを使いこなす方が常道です。

    以上

Reply
  • チョコです。

    実は、紹介したサンプルコードは、多重割り込みを使用しないで、同じようなことを実現しようとしています。下に示すINTP0割り込み処理の中で、タイマ割り込みをHALTモードの解除に利用して、タイマ割り込みでの実処理部を普通の関数にしてあるので、その関数を呼び出すことで、INTP0割り込み処理の中で、タイマ割り込み処理を実現しています。

    個人的には、このようなやり方(長い期間割り込み処理の中に留まる)は好きではない(と言うよりやってはいけない)のですが、このようなことを行えば(サンプルコードを参考にすれば)、武さんのやりたいことはそれほど難しくなく実現はできますよ。

    それよりは、多重割り込みを使いこなす方が常道です。

    以上

Children
No Data