pp.166-176
https://github.com/ti-nspire/AVR/tree/master/capSense
容量性センサーは、2枚のアルミフォイルを紙で絶縁して作った。
一定時間での充放電の回数を数える。手をかざすと容量が増えて、一定時間での充放電回数が減る。その回数がしきい値を下回ったときにLEDを点ける。
内部プルアップは、放電の具合を見ているときには有効化されてほしくないので最初に全部無効にしておく。
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/power.h> extern "C" { #include "USART.h" } #define THRESHOLD 7600 #define SENSE_TIME 80 volatile uint16_t count; void initPCINT(){ PCICR |= (1 << PCIE1); // ポートCをピン変化割り込みに使う。 PCMSK1 |= (1 << PC1); // PC1から割り込む。 } ISR(PCINT1_vect){ count++; DDRC |= (1 << PC1); // 充電を開始して(このときピン変化割り込みフラグが立つ)、 _delay_us(1); // 念のため充電しきるまで少しだけ待って、 DDRC &= ~(1 << PC1); // 放電を開始して、 PCIFR |= (1 << PCIF1); // ピン変化割り込みフラグをクリアしてから(※)、 } // ISRを抜けて、_delay_ms(SENSE_TIME)が再開される。 // ISRを抜けてしばらくたってHからLに変化した瞬間にまたピン変化割り込みフラグが立ってISRが呼ばれる。 // (※)充電時にセットされたピン変化割り込みフラグをクリアしておかないと、 // そのフラグのせいで、ISRを抜けた瞬間に(放電によってHからLに変化する前に)またISRが呼ばれてしまう。 int main(){ clock_prescale_set(clock_div_1); initUSART(); DDRB = 0xff; // ポートBのIOを全部OUTにする。そこにLEDをつなぐ。 MCUCR |= (1 << PUD); // 内部プルアップを全部無効にする。 DDRC |= (1 << PC1); PORTC |= (1 << PC1); // (1)充電して、 initPCINT(); while(1){ count = 0; sei(); // (2)グローバル割り込みフラグを立てて、 DDRC &= ~(1 << PC1); // (3)放電を開始して、HからLに変化した瞬間にISRへ制御が移って、 _delay_ms(SENSE_TIME); cli(); if(count < THRESHOLD){PORTB = 0xff;} else {PORTB = 0x00;} printWord(count); printString("\n"); } return 0; }
これでChapter 8 Hardware Interruptsが終わり。