#include #include #include #include static uint8_t Pinzustand; static uint8_t Timeout; static inline uint8_t getPinzustand( void ) { return (PINB & ((1 << PINB2) | (1 << PINB1) | (1 << PINB0))) | ((PINA & ((1 << PINA7) | (1 << PINA6))) >> 3); } static inline void setPinzustand( void ) { Pinzustand = getPinzustand(); } static inline uint8_t getPinaenderung( void ) { return Pinzustand ^ getPinzustand(); } static inline void leds_aus( void ) { PORTA = (1 << PINA7) | (1 << PINA6); } static inline void leds_an( void ) { PORTA = (1 << PINA7) | (1 << PINA6) | (1 << PINA5) | (1 << PINA4) | (1 << PINA3) | (1 << PINA2) | (1 << PINA1) | (1 << PINA0); } static inline void powerdown( void ) { // Powerdown Mode als Sparmodus, alles aus, nur Pin Interrupts funktionieren noch set_sleep_mode(SLEEP_MODE_PWR_DOWN); // PCIE0 und PCIE1 Interrupt aktivieren GIMSK = (1 << PCIE1) | (1 << PCIE0); // Powerdown sleep_mode(); // PCIE0 und PCIE1 Interrupt deaktivieren GIMSK &= ~((1 << PCIE1) | (1 << PCIE0)); } int main( void ) { // Analog Comparator deaktivieren ACSR |= (1 << ACD); // Analog to Digital Converter deaktivieren ADCSRA &= ~(1 << ADEN); // Analog to Digital Converter komplett abschalten PRR |= (1 << PRADC); // Digitale Input Buffer für alle Pins von PORTA abschalten DIDR0 = 0xFF; // PINA0, PINA1, PINA2, PINA3, PINA4 und PINA5 als Ausgang, PINA6 und PINA7 als Eingang DDRA = (1 << PINA5) | (1 << PINA4) | (1 << PINA3) | (1 << PINA2) | (1 << PINA1) | (1 << PINA0); // Pullup für PINA6 und PINA7 an, restliche Pins von PORTA auf 0. PORTA = (1 << PINA7) | (1 << PINA6); // Pullup für PINB0, PINB1 und PINB2 an, restliche Pins (PB3 - Reset, aber egal) von PORTB auf 0. PORTB = (1 << PINB2) | (1 << PINB1) | (1 << PINB0); // 250 Hz / 125 = 2 Hz -> 0,5 Sekunden OCR0A = 125 - 1; // CTC Mode TCCR0A = (1 << WGM01); // Timer0 Prescaler 64 => (128.000 Hz/8)/64 = 250 Hz TCCR0B = (1 << CS01) | (1 << CS00); // Pin Change Interrupt für PCINT6 (PA6) und PCINT7 (PA7) aktivieren PCMSK0 = (1 << PCINT7) | (1 << PCINT6); // Pin Change Interrupt für PCINT8 (PB0), PCINT9 (PB1) und PCINT10 (PB2) aktivieren PCMSK1 = (1 << PCINT10) | (1 << PCINT9) | (1 << PCINT8); // Global Interrupts aktivieren sei(); while(1) { // 128.000 Hz / (8 * 64 * 125) = 2 Hz -> 0,5 Sekunden if ( TIFR0 & (1 << OCF0A) ) { TIFR0 = (1 << OCF0A); if ( getPinaenderung() ) { Timeout = 0; setPinzustand(); } else { // 2 Hz * 5 s = 10 if ( ++Timeout > 10 ) { Timeout = 0; leds_aus(); setPinzustand(); powerdown(); leds_an(); } } } } return 0; } // PCIE0 (Nur zum Aufwachen) ISR(PCINT0_vect, ISR_NAKED) { reti(); } // PCIE1 (Nur zum Aufwachen) ISR(PCINT1_vect, ISR_NAKED) { reti(); }