Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AVR Timer Interrupt Examples
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
/*
* A global flag used to communicate between the Interrupt Service Routine
* and the main program. It has to be declared volatile or the compiler
* might optimize it out.
*/
volatile bool update = false;
/*
* The interrupt service routine. This is run whenever the interrupt
* "TIMER1_OVF_vect" is triggered. This is an interrupt that the ATmega328P
* triggers whenever Timer 1 overflows past its maximum value. It sets
* the update flag to "true" to tell the main program that it needs to
* do something.
*/
ISR(TIMER1_OVF_vect) {
update = true;
}
int main(void) {
// Set PORTB pins as output, but off
DDRB = 0xFF;
PORTB = 0x00;
// Turn on timer with no prescaler on the clock for fastest
// triggering of the interrupt service routine.
TCCR1B |= _BV(CS10);
TIMSK1 |= _BV(TOIE1);
// Turn interrupts on.
sei();
for(;;) {
// This turns interrupts off for the code inside it. Probably
// not needed here but it's good to know about.
ATOMIC_BLOCK(ATOMIC_FORCEON) {
// If the ISR has indicated we need to update the state
// then run this block.
if (update) {
// Toggle the pins on PORTB on/off.
PORTB ^= 0xFF; // Toggle the pins on/off
/*
* We reset the update flag to false to indicate that
* we are done. This ensures that this block will not
* be executed until update is set to true again, which
* is only done by the interrupt service routine.
*/
update = false;
}
}
}
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <stdbool.h>
#include <util/delay.h>
/*
* Struct to hold the old and new pin states;
*/
volatile struct {
uint8_t d_old;
uint8_t d;
} pins;
/*
* Change the current pin state to the old pin state and read the new pin
* state.
*/
ISR(TIMER1_OVF_vect) {
pins.d_old = pins.d;
pins.d = PIND;
}
int main(void) {
DDRB = 0x01;
PORTD = 0x04; // pullup on PD2
// Turn on timer with no prescaler on the clock for fastest
// triggering of the interrupt service routine.
TCCR1B |= _BV(CS10);
TIMSK1 |= _BV(TOIE1);
// Turn interrupts on.
sei();
for(;;) {
ATOMIC_BLOCK(ATOMIC_FORCEON) {
// Toggle pin state on low edge (pull-up on PD2 means the pin is active low)
if ( !(pins.d & _BV(PD2)) && (pins.d_old & _BV(PD2)) ) {
PORTB ^= _BV(PB0);
_delay_ms(10);
}
}
}
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <stdbool.h>
#include <util/delay.h>
/*
* Struct to hold the old and new pin states;
*/
volatile struct {
uint8_t b_old;
uint8_t b;
} pins;
/*
* Change the current pin state to the old pin state and read the new pin
* state.
*/
ISR(TIM0_OVF_vect) {
pins.b_old = pins.b;
pins.b = PINB;
}
int main(void) {
DDRB = 0b011110; // PB1 through PB4 as outputs
PORTB = 0b000001; // pullup on PB0 as an input
// Turn on timer with no prescaler on the clock for fastest
// triggering of the interrupt service routine.
TCCR0B |= _BV(CS00);
TIMSK |= _BV(TOIE0);
// Turn interrupts on.
sei();
for(;;) {
ATOMIC_BLOCK(ATOMIC_FORCEON) {
// Toggle pin state on low edge (pull-up on PB0 means the pin is active low)
if ( !(pins.b & _BV(PB0)) && (pins.b_old & _BV(PB0)) ) {
if (PORTB & _BV(PB1))
PORTB &= ~_BV(PB1);
else
PORTB |= _BV(PB1);
_delay_ms(10);
}
}
}
}
@kunguz

This comment has been minimized.

Copy link

kunguz commented Feb 8, 2013

Thank you very much this piece of code help me understand the concept.

@vicvicvar

This comment has been minimized.

Copy link

vicvicvar commented Jul 4, 2018

Like!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.