I/Oポートとスイッチの読み取りについて

I/Oポート(ポートA)からスイッチの状態を読み取って処理を行う場合の手順についての注意点について説明する。

スイッチPA3からPA0は、ポートAの下位3bitに接続されている。下の図は、PA_DRとスイッチの接続を表したもの。

     

例として、PA0が押された場合を考えてみる。

 PA0は単独で押される場合と、他のスイッチと一緒に押される場合がある。この事は、アプリケーションの動作によっては区別する必要がある。PA0が押された状態のパターンを一覧にすると、以下のようになる。

  PA_DRの値
(16進数、下位4bit)
 2進数表示  スイッチの状態
 0x0
 0x2
 0x4
 0x6
 0x8
 0xA
 0xC
 0xE
 0000
 0010
 0100
 0110
 1000
 1010
 1100
 1110
 全てのスイッチが押された状態
 PA3=押す、PA2=押す、PA1=離す、PA0=押す
 PA3=押す、PA2=離す、PA1=押す、PA0=押す
 PA3=押す、PA2=離す、PA1=離す、PA0=押す
 PA3=離す、PA2=押す、PA1=押す、PA0=押す
 PA3=離す、PA2=押す、PA1=離す、PA0=押す
 PA3=離す、PA2=離す、PA1=押す、PA0=押す
 PA3=離す、PA2=離す、PA1=離す、PA0=押す

                                   [ 表 PA_DRの値と、スイッチのON/OFF]

以上をふまえて、素直にPA0が押された事を検出するプログラムを作ると、以下の様になる。

#define PA_DDR (*(volatile unsigned char *)0xFFFFD1)
#define PA_DR (*(volatile unsigned char *)0xFFFFD3)

int main()
{
    char sw;
    long int w;

    PA_DDR = 0x00;  // ポートAの全てのbitを入力に設定
    while (1)
    {
        sw = PA_DR & 0xF;
        if ((sw == 0x0) || (sw == 0x2) || (sw == 0x4) || (sw == 0x6) || (sw == 0x8) ||
            (sw == 0xA) || (sw== 0xC) || (sw == 0xE))   // PA0が押されるパターンを列挙
        {
            printf("スイッチが押された");
            for (w=0; w<99999; w++);   // printfの表示がゆっくりになるようにwaitを入れる
        }
        else
        {
            printf("スイッチは押されてない");
            for (w=0; w<999999; w++); // printfの表示がゆっくりになるようにwaitを入れる
        }
    }
    return 0;
}

                                     [図   プログラム例1]
もしくは、

#define PA_DDR (*(volatile unsigned char *)0xFFFFD1)
#define PA_DR (*(volatile unsigned char *)0xFFFFD3)

int main()
{
    long int w;

    PA_DDR = 0x00;
    while (1)
    {
        switch (PA_DR & 0xF)
        {
            case 0x0 : case 0x2 : case 0x4 : case 0x6 :  // PA0が押されるパターンを
            case 0x8 : case 0xA : case 0xC : case 0xE :   // 列挙したもの。
                printf("スイッチが押された");
                for (w=0; w<999999; w++);
                break;
            default
                printf("スイッチは押されてない");
                for (w=0; w<999999; w++);
    }
    return 0;
}

                                           [図 プログラム例2]

 いずれの書き方にしても、記述量も多く、実行効率(処理速度)も遅くなりがち。また、バグも発生し易い。単純にPA0が押されたかどうかを判断するだけなら、bit演算を用いて以下のように記述するのが良い。

#define PA_DDR (*(volatile unsigned char *)0xFFFFD1)
#define PA_DR (*(volatile unsigned char *)0xFFFFD3)

int main()
{
    char sw;
    long int w;

    PA_DDR = 0x00;
    while (1)
    {
       sw = PA_DR & 0x01;   // bit毎のAND演算を用いることで、bit0以外を全て0に
                                          // する。この処理により、swの値は0もしくは1の2値となり
                                          // 判断しなければならない条件が減る。
       if (sw == 0) 
    // if ((PA_DR & 0x1) == 0)   // この様に書いてもよい
        {
            printf("スイッチが押された");
            for (w=0; w<999999; w++);
        }
        else
        {
            printf("スイッチは押されてない");
            for (w=0; w<999999; w++);
        }
        return 0;
}

                                             [図 プログラム例3]

 PA0以外のスイッチが押されたかどうか判断する場合は、bitの位置がずれるので、この点を忘れず考慮する事。
 判断したいスイッチと演算式の関係は、以下のとおりとなる。

  判断したいスイッチ   演算式   演算式が取りうる値

 PA0
 PA1
 PA2
 PA3

 PA_DR & 0x01
 PA_DR & 0x02
 PA_DR & 0x04
 PA_DR & 0x08
 0 もしくは 1
 0 もしくは 2
 0 もしくは 4
 0 もしくは 8

 

 

最終更新:2014年11月07日 09:11
添付ファイル