Micom Car Rally NET
MCR - Micom Car Rally
2015大会 マイコンカーラリーとは? 今から始めるマイコンカーラリー 技術情報 大会記録 MCRファン倶楽部 お問い合せ
マイコンカーラリートップへ マイコンカーラリートップへ
技術情報 >> R8C/M12A 技術情報
技術情報
アプリケーション
R8C/M12A 技術情報
上位入賞マイコンカー
参加者レポート
よくある質問(FAQ)
ダウンロード
R8C/M12A 技術情報
外部(INT)割り込みを使う

内容

R8C/M12Aには、外部からの信号が"0"から"1"になった瞬間(立ち上がりエッジといいます)、または"1"から"0"になった瞬間(立ち下がりエッジといいます)、またはその両方(両エッジといいます)になったときに割り込みを発生させることができます。これをINT割り込みといいます。R8C/M12Aには、INT0〜INT3の4つあるので最大で同時に4つの外部入力割り込みを発生させることができます。今回は、LEDを一定パターンで点灯させている状態で、INT3割り込みが発生したときにLEDを点滅させるようにします。

ワークスペース


r8cm12a_int3_100.zip
ファイルを解凍し、フォルダを「c:\worksapce」に入れてください。

回路

ブレッドボードの回路を下図に示します(「スイッチの入力(I/Oポートの入力)」と同じ回路です)。

回路図

ブレッドボード実装図

ブレッドボードの実装を下図に示します(「スイッチの入力(I/Oポートの入力)」と同じ実装です)。
ブレッドボード実装図

P3_3に繋がっているディップスイッチを"1"(上図の左側)から"0"(右側)にするとLEDが点滅します。

プログラムの説明


INT3の設定

INT0〜INT3の概要を、下図に示します。

INT0〜3 概要

今回は、INT3割り込みを使用します。入力エッジは立ち下がりエッジにします。
これからINT3割り込みについて、説明します。

■INT0入力端子の選択
INT0入力端子を選択します。今回は使いませんが、使う場合は下記のように設定してください。
    // P1_4端子を使う場合
    p14sel2 = 0;  /* P1_4をINT0端子にする         */
    p14sel1 = 1;
    p14sel0 = 1;

    // P4_5端子を使う場合
    p45sel1 = 0;  /* P4_5をINT0端子にする         */
    p45sel0 = 1;

■INT1入力端子の選択
INT1入力端子を選択します。今回は使いませんが、使う場合は下記のように設定してください。
    // P1_5端子を使う場合
    p15sel2 = 0;  /* P1_5をINT1端子にする         */
    p15sel1 = 1;
    p15sel0 = 1;

    // P1_7端子を使う場合
    p17sel1 = 0;  /* P1_7をINT1端子にする         */
    p17sel0 = 1;

    // P4_6端子を使う場合
    p46sel2 = 0;  /* P4_6をINT1端子にする         */
    p46sel1 = 1;
    p46sel0 = 1;

■INT2入力端子の選択
INT2入力端子を選択します。今回は使いませんが、使う場合は下記のように設定してください。
    // P3_4端子を使う場合
    p34sel1 = 1;  /* P3_4をINT2端子にする         */
    p34sel0 = 0;

    // P4_7端子を使う場合
    p47sel1 = 0;  /* P4_7をINT2端子にする         */
    p47sel0 = 1;

■INT3入力端子の選択
INT3入力端子を選択します。INT3は、P3_3しか選択できないので、必ず今回の設定になります。
    p33sel1 = 1;  /* P3_3をINT3端子にする         */
    p33sel0 = 0;

■外部入力許可レジスタ(INTEN)の設定
bit 7 6 5 4 3 2 1 0
設定
内容
        INT3入力
許可ビット
0:禁止
1:許可
INT2入力
許可ビット
0:禁止
1:許可
INT1入力
許可ビット
0:禁止
1:許可
INT0入力
許可ビット
0:禁止
1:許可
設定値         1      
ビットの
名称
        INT3EN INT2EN INT1EN INT0EN

INT3入力を許可します。この設定でINT3入力端子(今回はP3_3端子)がINT3入力になります。INT3を使う場合は、必ずこのビットを許可にしてください。
プログラムを下記に示します。
    int3en = 1; /* INT3入力許可ビット:許可     */

■INT入力フィルタ選択レジスタ0(INTF0)の設定
bit 7 6 5 4 3 2 1 0
設定
内容
INT3入力フィルタ
選択ビット
00:フィルタなし
01:フィルタあり、
f1でサンプリング
10:フィルタあり、
f8でサンプリング
11:フィルタあり、
f32でサンプリング
INT2入力フィルタ
選択ビット
00:フィルタなし
01:フィルタあり、
f1でサンプリング
10:フィルタあり、
f8でサンプリング
11:フィルタあり、
f32でサンプリング
INT1入力フィルタ
選択ビット
00:フィルタなし
01:フィルタあり、
f1でサンプリング
10:フィルタあり、
f8でサンプリング
11:フィルタあり、
f32でサンプリング
INT0入力フィルタ
選択ビット
00:フィルタなし
01:フィルタあり、
f1でサンプリング
10:フィルタあり、
f8でサンプリング
11:フィルタあり、
f32でサンプリング
設定値 1 1            
ビットの
名称
INT3F1 INT3F0 INT2F1 INT2F0 INT1F1 INT1F0 INT0F1 INT0F0

入力フィルタとは、入力端子の状態を一定時間ごとにチェックして、3回連続して同じ状態なら変化したと見なす機能です。チャタリングなどで、信号にノイズが含まれている場合などに有効です。期間は、f1(20MHz=50nsごとにチェック)、f8(2.5MHz=400nsごとにチェック)、f32(0.625MHz=1600nsごとにチェック)の3つから選ぶことができます。今回はスイッチなのでf32を選択します。3回連続で同じ状態ということなので、1600ns×3=4.8μs以上同じ状態なら変化したと見なします。
プログラムを下記に示します。
    int3f1 = 1;   /* INT3入力フィルタ選択ビット   */
    int3f0 = 1;   /* 11=f32でサンプリング         */

■ INT入力エッジ選択レジスタ0(ISCR0)の設定
bit 7 6 5 4 3 2 1 0
設定
内容
INT3入力エッジ
選択ビット
00:立ち下がりエッジで割り込み要求を発生
01:立ち上がりエッジで割り込み要求を発生
11:立ち下がり、立ち上がりの両エッジで割り込み要求を発生
INT2入力エッジ
選択ビット
00:立ち下がりエッジで割り込み要求を発生
01:立ち上がりエッジで割り込み要求を発生
11:立ち下がり、立ち上がりの両エッジで割り込み要求を発生
INT1入力エッジ
選択ビット
00:立ち下がりエッジで割り込み要求を発生
01:立ち上がりエッジで割り込み要求を発生
11:立ち下がり、立ち上がりの両エッジで割り込み要求を発生
INT0入力エッジ
選択ビット
00:立ち下がりエッジで割り込み要求を発生
01:立ち上がりエッジで割り込み要求を発生
11:立ち下がり、立ち上がりの両エッジで割り込み要求を発生
設定値 0 0            
ビットの
名称
INT3SB INT3AB INT2SB INT2AB INT1SB INT1AB INT0SB INT0AB

「立ち下がりエッジで割り込み要求を発生」は、信号が"1"から"0"になった瞬間に割り込みを発生させます。「立ち上がりエッジで割り込み要求を発生」は、信号が"0"から"1"になった瞬間に割り込みを発生させます。「立ち下がり、立ち上がりの両エッジで割り込み要求を発生」は、両方で割り込みを発生させます。ただし、入力フィルタを設定している場合は、一定時間毎にチェックして3回連続で同じ状態のときに割り込みが発生します。今回は立ち下がりエッジで割り込みを発生させる設定にします。
プログラムを下記に示します。
    int3sb = 0;   /* INT3入力エッジ選択ビット     */
    int3sa = 0;   /* 00=立ち下がりエッジで割込発生  */

■割り込み優先レベルレジスタA(ILVLA)
bit 7 6 5 4 3 2 1 0
設定
内容
    INT2の割り込み優先
レベル設定ビット
00:レベル0
(割り込み禁止)
01レベル1
10:レベル2
       
設定値                
ビットの
名称
    ILVLA5 ILVLA4        

割り込み優先レベルは、複数の割り込みが同時に発生したとき、どの割り込みを優先させるか設定するものです。レベル2とレベル1を設定することができ、レベル2に設定した割り込みが優先されます。レベルが同じ時は、ハードウェアマニュアルの表に従って優先順位が決まります。詳しくは、R8C/M12Aのハードウェアマニュアルを参照してください。
割り込み優先レベルレジスタA(ILVLA)は、INT2の割り込み優先レベルを設定します。今回はINT2は使いませんので、このレジスタの設定はしません。

■割り込み優先レベルレジスタC(ILVLC)
bit 7 6 5 4 3 2 1 0
設定
内容
    INT1の割り込み優先
レベル設定ビット
00:レベル0
(割り込み禁止)
01レベル1
10:レベル2
       
設定値                
ビットの
名称
    ILVLC5 ILVLC4        

割り込み優先レベルレジスタC(ILVLC)は、INT1の割り込み優先レベルを設定します。今回はINT1は使いませんので、このレジスタの設定はしません。

■割り込み優先レベルレジスタD(ILVLD)
bit 7 6 5 4 3 2 1 0
設定
内容
            INT3の割り込み優先
レベル設定ビット
00:レベル0
(割り込み禁止)
01レベル1
10:レベル2
設定値             1 0
ビットの
名称
            ILVLD1 ILVLD0

割り込み優先レベルレジスタD(ILVLD)は、INT3の割り込み優先レベルを設定します。今回はINT3以外の割り込みを使いませんのでレベル1でもレベル2でもどちらでも構いませんが、一応レベルの高い、レベル2を設定しておきます。
プログラムを下記に示します。
    ilvld1 = 1;   /* 割り込み優先レベル設定ビット */
    ilvld0 = 0;   /* INT3はD1とD0に設定 10=レベル2*/

■割り込み優先レベルレジスタE(ILVLE)
bit 7 6 5 4 3 2 1 0
設定
内容
    INT0の割り込み優先
レベル設定ビット
00:レベル0
(割り込み禁止)
01レベル1
10:レベル2
       
設定値                
ビットの
名称
    ILVLE5 ILVLE4        

割り込み優先レベルレジスタE(ILVLE)は、INT0の割り込み優先レベルを設定します。今回はINT0は使いませんので、このレジスタの設定はしません。

■全体の割り込みを許可する

外部入力許可レジスタ(INTEN)で、INT3入力による割り込みを許可しましたが、初期状態ではマイコン全体の割り込みが禁止になっています。
そのため、最後にマイコン全体の割り込みを許可します。全体割り込み許可は、マイコンのCPUレジスタという、C言語では操作できない場所にあるので、下記の様にアセンブラで命令を記述します。asm関数は、C言語プログラム内でアセンブラ命令を記述する命令です。
    /* 全体割り込みの許可 */
    asm(" fset I ");    /* 全体の割り込み許可 */

今まで説明したINT3の設定は、init関数内で行います。最終プログラムを下記に示します。

    /* INT3割り込み設定 */
    p33sel1 = 1;  /* P3_3をINT3端子にする         */
    p33sel0 = 0;
    int3en = 1;   /* INT3入力許可ビット:許可     */
    int3f1 = 1;   /* INT3入力フィルタ選択ビット   */
    int3f0 = 1;   /* 11=f32でサンプリング         */
    int3sb = 0;   /* INT3入力エッジ選択ビット     */
    int3sa = 0;   /* 00=立ち下がりエッジで割込発生  */
    ilvld1 = 1;   /* 割り込み優先レベル設定ビット */
    ilvld0 = 0;   /* INT3はD1とD0に設定 10=レベル2*/

    /* 全体割り込みの許可 */
    asm(" fset I ");  /* 全体の割り込み許可       */

割り込みプログラム

割り込みプログラムを下記に示します。今回はP3_3端子に立ち下がりエッジの信号("1"→"0"になった瞬間)が入力されたとき、このプログラムが実行されます。

#pragma interrupt intINT3(vect=26)
void intINT3( void )
{
    flag_int3 = 1;
}

intINT3関数が、INT3入力割り込みが発生したときに実行される関数です。この関数がINT3入力割り込みの実行先ということを設定するのが、「#pragma interrupt」命令です。この命令の書式を下記に示します。
#pragma interrupt 割り込み関数名(vect=割り込み番号)
void 割り込み関数名( void )
{
    割り込みプログラム
}

INT3の割り込み番号は26と決まっています。どの内蔵周辺機能が何番の割り込み番号かは、ルネサス エレクトロニクスの「R8C/M11Aグループ、R8C/M12Aグループ ユーザーズマニュアル ハードウェア編」の「可変ベクタテーブル」部分を参照してください。
INT0〜INT3の割り込み番号を下表に示します。

INT番号 割り込み番号
INT0 29
INT1 25
INT2 21
INT3 26

割り込み関数名は、自由に付けて構いません。今回はINT3割り込みなので、割り込みの「interrupt」とINT3の「INT3」を略して、「intINT3」としました。

今回のプログラムではflag_int3という変数に1を代入します。LEDの点滅動作は、main関数内で行っています。

main関数

main関数を下記に示します。

void main( void )
{
    int i;

    init();   /* 初期化                       */

    while( 1 ) {
        p1 = 0b00001111;
        timer( 1000 );
        p1 = 0b11110000;
        timer( 1000 );
        p1 = 0b00000000;
        timer( 1000 );

        if( flag_int3 == 1 ) {
            // INT3割り込みが発生したなら
            flag_int3 = 0;

            // 10回、LEDを交互に点滅させる
            for( i=0; i<10; i++ ) {
                p1 = 0b10101010;
                timer( 200 );
                p1 = 0b01010101;
                timer( 200 );
            }
        }
    }
}

if文でflag_int3変数が1かどうかチェックして、1なら、LEDを"1010 1010"と"0101 0101"を0.2秒ごとに10回点灯させ、INT3割り込みが発生したことをLEDで知らせます。

チャタリングについて

今回、スイッチはディップスイッチを使っています。INT3割り込みは立ち下がりエッジの設定なので、ディップスイッチを"1"→"0"にするとLEDが点滅します。しかし、たまに"0"→"1"(立ち上がりエッジ)にしたときもLEDが点滅することがあります。ディップスイッチが変化したときの電圧をオシロスコープで見たときの波形を下図に示します。

チャタリング

スイッチを"0"→"1"にしたつもりでも、短い時間の間で何度も"0"になったり"1"になったりします。これを「チャタリング」といいます。R8C/M12Aは20MHzで動作しているので、50ns(1/20MHz)より時間が長い信号は検出してしまいます。今回のINT3入力フィルタは、「f32でサンプリング」に設定していますが、それでも4.8μsより長い間、チャタリングが発生した場合は誤検出してしまいます。今回の波形は"1"→"0"に1回しかしていないつもりでも、波形自体は2回以上(もしかしたらオシロスコープで検出できないチャタリングがあるかもしれない)変化しました。
解決方法は、回路側で対処するか、プログラム側で対処します。例えば、回路側での対応は、チャタリングの発生しない回路を入れます。プログラム側での対応は、割り込みが発生したら、0.1秒間は割り込みが発生しても無視するようにする、などします。ここでは解決例は記載しませんので、自分なりに考えたり、「チャタリング防止回路」で検索して調べたりして、対処してみてください。

BACK