本文へスキップ

アトメル社のAVRマイコンをつかった電子工作および無線を使った電子工作を紹介します。





ホーム > 準備室 >AVRマイコンで始めるC言語の使い方 >スイッチ入力をする。->ループで待つ

AVRマイコンで始めるC言語の使い方

スイッチ入力をする。

スイッチをONしている間はLEDを点灯させるプログラムを作ります。これを以下の2つの方法で一緒にプログラムをしていきます。スイッチはPD0に接続されたSW0を使用します。LEDはPD4に接続されたLED4を使用します。
   [方法1]ループで待つ。
   [方法2]外部割込を使う。
スイッチには、チャタリングという特性があります。スイッチがONするときは10ms程度ONとOFFを繰り返した後にONになります。スイッチがOFFするときは10ms程度ONとOFFを繰り返した後OFFになります。プログラムでは、スイッチがONとなってから10msたった後にLEDを点灯します。スイッチがOFFとなるときはスイッチがOFFになってから10msたった後にLEDを消灯します。スイッチがONになったあとすぐにスイッチがOFFになるのを待つようなプログラムを作ったばあいチャタリングを検出してしまいLEDが点滅する可能性があるので10ms待ちます。

[方法1]ループで待つ

前章で勉強したループを使います。スイッチがONになるまでループで待ちます。スイッチがONになったらLEDを点灯させます。次にスイッチがOFFになるまでループで待ちます。スイッチがOFFになったらLEDを消灯させます。以下繰り返します。
 ・スイッチがONになるとポートPD0の状態はL('0')です。
 ・スイッチがOFFになるとポートPD0の状態はH('1')です。
 ・LED4を点灯させるにはPD4にH('1')を出力します。
 ・LED4を消灯させるにはPD4にL('0')を出力します。

1.フローチャート

フローチャート説明

1.スイッチSW0がONになっているか確認します。OFFであればここでループしてONになるまで待ちます。
  while((PIND & 0x01) != 0);  // '1'(スイッチSW0がOFFしている)の間はwhile内でループ。またはwhile( PIND & (1 << PORTD0));という書き方もあります。
2.スイッチSW0がONであれば10ms待ちます。スイッチのチャタリング時間待った後に次の処理に進むことでチャタリングによる誤作動を防ぎます。
     _delay_ms(10);  // delay_ms関数を使用します。
3.LED4を点灯させます。
      PORTD |= 1 << PORTD4;
4.スイッチSW0がOFFになるのを確認します。ONであればここでループしてOFFになるまで待ちます。
     while((PIND & 0x01) == 0); // '0'(スイッチPD0がONしている)の間はwile内でループ。またはwhile( !(PIND & (1 << PORTD0)));という書き方もあります。
5.スイッチSW0がOFFになったら10ms待ちます。
  _delay_ms(10);
6.LED4をOFFします。
      PORTD &= ~(1 << PORTD4);
7.1に戻ります。

2.プログラム

スイッチの状態を読むにはPD0を入力に設定します。設定方法は「LEDを点灯させる->初期設定」頁を参照してください。
スイッチPD0の状態をプログラムに読み込むにはPINDレジスタを使用します。

PINDレジスタ
PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0
スイッチはPD3~PD0に接続されていますので読み込むとPINDレジスタの下位4ビット(PIND3~PIND0)にスイッチの状態が入ります。上位4ビット(PIND7~PIND5)にはLEDのが接続され出力に設定さていますので出力の状態を見ることができます。
スイッチPD0の状態読み込むプログラムはPIND & 0b00000001(またはPIND & 0x01)です。結果が'0'であればスイッチがON、'1'であればスイッチがOFFとなります。
チャタリング10ms待ちは_delay_msを使用しますので"delay.h"をインクルードしてください。

/*
 * avr006_PortLoop.c
 *
 *スイッチ入力をループで待ちます。
 *スイッチONでLED点灯
 *スイッチOFFでLED消灯
 */ 

#define    F_CPU    1000000UL      // 1MHz

#include <util/delay.h>
#include <avr/io.h>

void InitHard( void);   // ポートの初期化

int main(void)
{
        InitHard();     //ポートの初期化を行います。
        
    while(1)    // プログラム全体のループです。この中にスイッチ入力のプログラムを作ります。
    {
        while( PIND & 0x01);                    // スイッチPD0がONになるまでここで待ちます。
                _delay_ms(10);                  // 10ms待ちます。
                PORTD |= 1 << PORTD4;           // LED_PD4を点灯させます。
                
                while( !(PIND & 0x01));         // スイッチPD0がOFFになるまでここで待ちます。
                _delay_ms(10);                          // 10ms待ちます。
                PORTD &= ~(1 << PORTD4);        // LED_PD4をOFFします。
    }
}

void InitHard( void) // ポートの初期化
{
        // ポートB初期設定
        DDRB = 0xff;    // PB7~PB0を出力に設定します。
        PORTB = 0;              // PB7~PB0に'L'を出力します。
        // ポートC初期設定
        DDRC = 0x3f;    // PC7,PC6は初期(入力)、PC5~PC0を出力に設定します。
        PORTC = 0;              // PC7~PC0に'L'を出力します。
        // ポートD初期設定
        DDRD = 0xf0;    // PD7~PD4は出力、PD3~PD0は入力に設定します。
        PORTD = 0;              // PD7~PD0に'L'を出力します。
}

3.実行

スイッチを押している間はLEDが点灯するようになったでしょうか。今回のプログラムでは外部からのノイズ等の影響を考慮していません。一般には以下示すように外乱の影響を考慮します。
   (1)スイッチがONを検出
   (2)チャタリング待ち
   (3)スイッチの状態を再度確認
   (4)スイッチがONであれはLEDを点灯、OFFであれば外乱と判定しLEDは消灯のまま

皆さんでプログラムを改造してみてください。
前ページ次ページ