スイッチが押されると、LEDがON/OFFとトグルする簡単なコードを書きました。
スイッチはPC5, LEDはPD4に接続してあります。
PC5はプルアップしてあり、スイッチによりGNDに短絡されると、割り込み(PCINT1_vect)が入り、PD4の出力がXOR演算でトグルされます。
初期化では、ポートのIN/OUT、1/0の設定、割り込み関係のレジスタの設定がなされます。
ポイントは、スイッチのチャタリングをソフトウェアで吸収することです。
スイッチを押したり/離したりするときのバタつきが納まるまで10ms待ちます。さらに、押している最中のバタつきを無視するために、「前は離されていて、今は押されている」というときのみボタンが押されたと判定します。押している最中のバタつきは、「前は押されていて、今は押されている」という状況になり、排除されます。
今回のように「押したらLEDをトグルする」という処理をするときにはこのような判定が必要ですが、「押している間だけLEDをON」という処理ならば、チャタリングで一瞬LEDがOFFになっても気づかないので、必要ありません。
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile int8_t last;
SIGNAL(PCINT1_vect){
_delay_ms(10);
int8_t now = PINC & (1 << PINC5);
if ((last != 0) & (now == 0)){
PORTD ^= (1 << PORTD4);
}
last = now;
}
int main(void){
//button: pc5(PCINT13)
//led: pd4
DDRB = 0xFF;//direction 1 out, 0 in
DDRC = 0b11011111;//in: pc5
DDRD = 0xFF;
PORTB = 0x00;//off
PORTC = (1 << PORTC5);//pullup: pc5
PORTD = 0b00010000;
last = 1;
///INT.
PCICR |= 1 << PCIE1;//allow int. for pin group 1(8-14)
PCMSK1 |= (1 << PCINT13);//PCMSK1 = 0x30
sei(); // allow interrupts
while(1){
}
return 0;
}
割り込みを有効にする前にlast = 1;としないと、ボタンを初めて押した時にボタンが効きません。初期化と同時に代入するのでも良いです。