RL78/G13 基本的な多重割り込み処理の操作方法

皆様、

初心者です。ご教示お願いします。

・外部のモメンタリSWに接続した割り込みP137端子(INTP0)と12bitインターバルタイマを使い、外部割り込みSWのチャタリング防止のプログラムを作成しました。

・INTP0で呼ばれる#pragmaで定義される割り込みルーチンプログラムの冒頭に、12bitインターバルタイマによるwait_25ms()を記述したところ、このwait_25ms()のHALT()で止まってしまいます。

・そこで、割り込みルーチンのwait_25ms()の代わりに、割り込みを使用しないNOP()を繰り替えすループを作成したところ(100ms程度?)、P137のSW動作はうまく行くようになりました。

お尋ねしたいのは、

(1)外部SWのチャタリング防止のウエイトのために、12bitインターバルタイマを使用するには、どうしたらよいのでしょうか?

(2)INTP0のデフォルト割り込み優先順位は"2"のようです(H/Wマニュアル)。インターバルタイマはこれより低い順位です。wait_25ms()の前に、EI()を入れ、後にDI()を挿入すればことたりるのでしょうか?

初歩的な内容ですが、よろしくお願いします。

Parents
  • こんにちは。NoMaYです。

    > 非常に短い時間のうちに割り込が連続して発生する、ということになります

    確かに、そうですね。

    実は、私は実務でチャタリング除去処理すら書いたことが無いという、少々経験が偏っている人物だったりするので、後は本物のベテランの方にお任せします。(でないと、間違ったことを言いそうなので、、、)

    #最近、FreeRTOSのサンプルプログラムでvTaskDelay()によるチャタリング除去を書いていたので反応してしまいました、、、すみません、、、

  • NoMayさん、わいわいさん

    ご指導ありがとうございます。
    本来の多重割り込みの基本的な使い方から、チャタリング対策処理に話題が移りました。
    チャタリング対策処理に関し、お二人に共通しているのは、INTP0の外でタイマーを使うということですね。これは了解いたしました。

    >わいわいさん
    INTP0は、チャタリング除去ではなく、SW押下のチェックのために使用したいというのがそもそもです。
    SWがバタついても、P137の"最初"のエッジ低下が認識されると、INTP0の割り込みルーチンに飛びます。
    このルーチンの始めにタイマーでウエイトさせ、その後、プルアップされているP137のステータスを再度確認し、0であれば、SWが押されたというフラグをセットし割り込みルーチンを抜けるというロジックです。現在は、割り込みを使用しないタイマーを使っています。
    チャタリング防止あるいはSW押下の認識方法とは別に、このような場合に、wait_25ms()というタイマー割り込みのHALT()を避けるにはどうしたらよいでしょうか?

    よろしくお願いします。
  • 失礼しました。わわいさんでした。
    NoMayさん、わわいさん

    ご指導ありがとうございます。
    本来の多重割り込みの基本的な使い方から、チャタリング対策処理に話題が移りました。
    チャタリング対策処理に関し、お二人に共通しているのは、INTP0の外でタイマーを使うということですね。これは了解いたしました。

    >わわいさん
    INTP0は、チャタリング除去ではなく、SW押下のチェックのために使用したいというのがそもそもです。
    SWがバタついても、P137の"最初"のエッジ低下が認識されると、INTP0の割り込みルーチンに飛びます。
    このルーチンの始めにタイマーでウエイトさせ、その後、プルアップされているP137のステータスを再度確認し、0であれば、SWが押されたというフラグをセットし割り込みルーチンを抜けるというロジックです。現在は、割り込みを使用しないタイマーを使っています。
    チャタリング防止あるいはSW押下の認識方法とは別に、このような場合に、wait_25ms()というタイマー割り込みのHALT()を避けるにはどうしたらよいでしょうか?

    よろしくお願いします。
Reply
  • 失礼しました。わわいさんでした。
    NoMayさん、わわいさん

    ご指導ありがとうございます。
    本来の多重割り込みの基本的な使い方から、チャタリング対策処理に話題が移りました。
    チャタリング対策処理に関し、お二人に共通しているのは、INTP0の外でタイマーを使うということですね。これは了解いたしました。

    >わわいさん
    INTP0は、チャタリング除去ではなく、SW押下のチェックのために使用したいというのがそもそもです。
    SWがバタついても、P137の"最初"のエッジ低下が認識されると、INTP0の割り込みルーチンに飛びます。
    このルーチンの始めにタイマーでウエイトさせ、その後、プルアップされているP137のステータスを再度確認し、0であれば、SWが押されたというフラグをセットし割り込みルーチンを抜けるというロジックです。現在は、割り込みを使用しないタイマーを使っています。
    チャタリング防止あるいはSW押下の認識方法とは別に、このような場合に、wait_25ms()というタイマー割り込みのHALT()を避けるにはどうしたらよいでしょうか?

    よろしくお願いします。
Children
  • わわいです
    > このような場合に、wait_25ms()というタイマー割り込みのHALT()を避けるにはどうしたらよいでしょうか?

    そうしなければ動かない、ということが、そもそもSW入力を割り込みに入れているため、でしょう。
    そこをどうにかしましょう。
  • わわいです
    このような状況でどう処理をするか、というと、来た複数の割り込みを、それぞれ適切に処理をする、ということになります。

    一つのスイッチのアクション、入れるときと切るときに複数の割り込みがかかります。それを適切に処理をしましょう。

    #複数の割り込み、それは数個かもしれないし、数十個かもしれない。

    それができないでいるからこそ、不要なウェイトを噛ませたり割り込みをディセーブルしないといけないことになります

    #RL78はあんまし使ったことないので、具体的なことは言えませぬ
  • toko2010さん NAKAといいます。
    toko2010さんがやりたいことと違うかもしれませんが、INTP0の割込みが入ったら、割込み処理の一番初めでINTP0の割込みを禁止してしまうのはどうでしょうか?あとは適当なチャタリングが収まるタイミング(タイマーでもいいし、定期処理で数えてもいい)で再度INTP0割込みを許可するのは?toko2010さんがどれだけ早くこのスイッチを押したいかによりますが、手で押すならせいぜい0.5sくらい?SWの機械的チャタリングなら100msもあれば収まるとおもいます。もっと早くSWの確認を確実にしたいのでしょうか?高橋名人のように......古!!!!

     

    例えば

    /************************/
    /*外部入力0割り込み関数*/
    /************************/
    void __near IRQ0_INT(void)
    {
     PMK0 = 1; //IRQ0割り込みの禁止
     PIF0 = 0; //IRQ0割り込み要求フラグクリア
     f_SW = 1; //SW押されたフラグ
    }

    /************************/
    /*MAINの中で  */
    /************************/
    while(1)
    {
      if(f_1ms)    //1msの定期処理
      {
     
        if(f_SW == 1)
         {
           c_100ms++;
            if(c_100ms >= 100)
            {
             c_100ms=0;
             PMK0 = 0;        //IRQ0割り込みの許可

            f_SW = 0; //SW押されたフラグ
            }
         }

      }

    }

    みたいな

     

    P.S.

    僕も普通の手で押すSWにINTP0は使わないかな?SLEEP状態の機器を起こしたりする時なんかは使うけど....

  • NAKAさん

    ご指導ありがとうございます。

    割り込み関数の中での、

    PMK0 = 1; //IRQ0割り込みの禁止

    PIF0 = 0; //IRQ0割り込み要求フラグクリア

    さらに後続の処理で、

    PMK0 = 0;        //IRQ0割り込みの許可

    について了解いたしました。

    これを、私の割り込み関数の中にいれたところ、割り込みを使用しないウエイトを使うと、以前よりも安定的に動作し始めました。このPMK0、PIF0の操作をしないと、わわいさんが言われるように、SW押下でバタつくと思います。

    以下が現在のコードで、赤字部部分がご教示いただいた箇所です。ここで、インターバルタイマを使用したwait_50ms() に変更し、SW押下すると、このタイマで停止してしまいます。このコードには、多重割り込みのネスティング、特に多重割り込みの優先順位の取り扱いに誤りがあると考えます。INTP0の優先順位変更が必要だと思いますが、当方には不詳です。

    static void __near r_intc0_interrupt(void)

    {

       /* Start user code. Do not edit comment generated here */

       PMK0 = 1;  //INTP0割り込みの禁止(=割り込みマスクオン)

       PIF0 = 0;  //INTP0割り込み要求フラグクリア

       // wait_50ms();

       // wait_50ms();

       wait_noint(); // 割り込みを使用しないNOP()のforループ

       if ( 0 == P13_bit.no7 )

       {

       NOP();

       band_counter++;

       if ( band_counter > 10)

       {

       band_counter = 1;

       }

       }

       PMK0 = 0; //INTP0割り込み許可(=割り込みマスククリア)

       /* End user code. Do not edit comment generated here */

    }