ピンの変更割り込みを使用して、押されたボタンを検出しようとしています。これまでは、この種の割り込みを扱ったことはなく、いくつかの問題があるので、これが正しい使い方かどうかを確認したいと思います。
データシートが正しい場合、ピン変更割り込みを使用するには、次のことを行う必要があります。
- 制御するPINをPCMSKレジスタに設定します
- ピン変更割り込み制御(PCICR)のPINレジスタを有効にする
- 割り込みを有効にする
- 対応する割り込みベクターを使用する
プロジェクト:シンプルなムードランプ、4つのボタンで色を制御。
セットアップ:
- Atmega168A-PU
- 4つのミニプッシュボタンスイッチ
- 私の3ワットRGB LEDを制御するMOSFET
これが私が使用しているコードで、期待どおりに機能していません:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BUTTON1 (1<<PC5)
#define BUTTON2 (1<<PC4)
#define BUTTON3 (1<<PC3)
#define BUTTON4 (1<<PC2)
#define GREEN (1<<PB1)
#define BLUE (1<<PB2)
#define RED (1<<PB3)
void init() {
// enable LED
DDRB |= GREEN;
DDRB |= BLUE;
DDRB |= RED;
// button pullups
PORTC |= BUTTON1;
PORTC |= BUTTON2;
PORTC |= BUTTON3;
PORTC |= BUTTON4;
// pin change interrupts for buttons
PCMSK1 |= PCINT13;
PCMSK1 |= PCINT12;
PCMSK1 |= PCINT11;
PCMSK1 |= PCINT10;
// enable pin change for buttons
PCICR |= PCIE2;
sei();
}
ISR(PCINT2_vect) {
PORTB = BLUE;
}
void ledTest() {
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
}
int main() {
init();
ledTest();
_delay_ms(500);
PORTB |= GREEN;
while(1) {
_delay_ms(100);
}
}
注:ボタンはデバウンスする必要があります。私は一歩一歩これを試みており、それがLEDをオンにするために合わないはずなので、ここではそれを無視しました。
質問:割り込みの使用方法は正しいですか?
私のセットアップに関する問題:
- ボタン1〜3は完全に無視されます。
- Button4がatmegaのリセットをトリガーしています
私がチェックしたもの:
- ボタンがリセットPINに接続されていない
- ボタンが押された場合、ボタンは正しくGNDに接続されています
- ボタンが押されていない場合、ボタンはGNDに接続されていません
ボタンは、私が中断することなくそれらを利用する場合、うまく機能します。例:
if(!(PINC&BUTTON4)){PORTB ^ =ブルー; }
- 16MHZ外部クリスタル/内部クリスタル
- ルーティングのエラー
- AtmegaでPWRとGNDの間に100nFのコンデンサーを使用しています
- VCC(7)、GND(8)、GND(22)、AVCC(20)が接続されています(AREFは必要ないため、接続されていません)