/* * Use the timers pwm to dim a light on demand. * The light will change continously until you * press the button to stop. */ #define F_CPU 16000000UL #define __AVR_ATmega328P__ #include #include #include #define PWM_LOW 0 #define PWM_HIGH 96 #define DELAY 25 void change(); typedef enum { UP, STOP, DOWN } State; State state = UP; int brightness = PWM_HIGH; // code for INT0 ISR(INT0_vect) { PORTB |= (1 << PORTB5); state = UP; } // code for INT1 ISR(INT1_vect) { PORTB &= ~(1 << PORTB5); state = STOP; } int main(void) { // read from D2 and D3, write to D6 DDRD |= (1 << PORTD6); DDRB = 0xff; // used for internal led only PORTD |= (1 << PORTD2) | (1 << PORTD3); // pull up D2 and D3 // enable external interruprs EIMSK |= (1 << INT0); EIMSK |= (1 << INT1); // trigger when anything changes EICRA |= (1 << ISC00); // for INT0 EICRA |= (1 << ISC10); // for INT1 // Timer 0 // Mode: Fast PWM // Prescaler: /8 // max: dynamic depending on pushed button TCCR0A |= (1 << WGM01) | (1 << WGM00); // Fast PWM Mode OCR0A = brightness; // max value for timer TCCR0A |= (1 << COM0A1); // set non inverting mode, start initialized TCCR0B |= (1 << CS02) | (1 << CS00); // enable with prescaler 1024 sei(); // magic interrupt macro while (1) { change(); _delay_ms(DELAY); } } void change() { // start looping through brightnesses if (state == UP) { OCR0A = brightness++; if (brightness >= PWM_HIGH) { state = DOWN; } } if (state == DOWN) { OCR0A = brightness--; if (brightness <= PWM_LOW) { state = UP; } } }