STM32のEXTI割り込みをディセーブル・イネーブルする

STM32のEXTIはGPIOを外部割り込みラインに使える便利な機能ですが、HALの説明が雑で、どうすればイネーブル・ディセーブルできるのかがピンときません。

EXTIを使えばGPIO経由で最大16本のEXTI割り込み線を定義できます。内部ではもっと利用できるのですが、GPIO各ポートが16pinまでなので、EXTIで使える外部線は16というのは合理的です。

さて、EXTIの設定はCubeIDEで出来ますので、ささっと設定して対応するNVICの割り込みラインをイネーブルにすれば、すぐにアプリケーションを割り込み可能に出来ます。ところが、Enable Interrupt, Disable InterruptといったAPIがありません。割り込みを禁止できないアプリケーションというのは、どうも気分がよくありません。

「だったらNVICのラインでイネーブル・ディセーブルすればいい」

という声が返ってきそうですが、それはだめです。STM32の設計ではEXTIの各ラインとNVICの割り込み入力が一対一対応していません。そのため、独立に割り込みラインを制御したければ、NVICを触るのは悪手です。

結局、割り込みのイネーブルとディセーブルは次のAPIを使います。

  • HAL_EXTI_SetConfigLine();
  • HAL_EXTI_ClearConfigLine();

なんでやねん。

以下、プログラムの中でEXTIをディセーブル、イネーブルする手順を説明します。

まず、EXTIのハンドルと設定用変数を定義します。CubeIDEはEXTIのハンドルを生成しませんので、自分で作らなければなりません。ハンドルはEXTIのライン一本一本に専用のハンドルを定義します。

    EXTI_HandleTypeDef hexti_b1 = { 0 };
    EXTI_ConfigTypeDef hexti_b1_config;

次に、ハンドルをを初期化します。初期化はlineメンバー変数にEXTIのラインを設定するだけです。ここで注意すべきは、lineメンバー変数に勝手な変数を代入しては行けないことです。必ずEXTI_LINE_##定数を代入してください。

    hexti_b1.Line = EXTI_LINE_13;

次に、EXTIの設定をペリフェラルから取り出します。最初の引数には先程のハンドルでEXTIラインを指定しします。成功するとAPIは2番めの引数に設定を格納します。

    HAL_EXTI_GetConfigLine(
                           &hexti_b1,
                           &hexti_b1_config
                           );

EXTIのディセーブルにはClear API を使います。

HAL_EXTI_ClearConfigLine( &hexti_b1);

この呼び出しでEXTIの当該ラインの割り込み設定が全てクリアされますので、割り込みディセーブルとすることが出来ます。イネーブルしたい場合には先ほど取り出したEXTI設定を使ってハードウェアを再設定します。

HAL_EXTI_SetConfigLine( &hexti_b1,  &hexti_b1_config);

たかが割り込み線のイネーブル・ディセーブルに設定全体をいじりまわすとは大げさですが、他に適当なAPIがありません。もしもっと良い方法をご存知の方はお教えください。

「STM32のEXTI割り込みをディセーブル・イネーブルする」への2件のフィードバック

  1. 3年前以上前のブログにレスするのもアレですが
    HAL_NVIC_EnableIRQ

    HAL_NVIC_DisableIRQ
    ではダメなんですか?
    引数にはEXTIx_IRQnを指定します
    3年前にはこの関数はなかった?

    返信
    • HAL_NVIC_EnableIRQ()はNVICの割り込みライン単位でイネーブル・ディセーブルを行います。

      STM32はGPIOの複数割り込みラインを同じNVICのラインで共用してしまうため、それらが一斉にイネーブル・ディセーブルされてしまう問題があります。

      ということで、私はこの関数は使っていません。

      返信

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください