Skip to content

Instantly share code, notes, and snippets.

@dotchetter
Forked from fpigerre/interrupts.md
Created October 27, 2020 15:08
Show Gist options
  • Save dotchetter/4bcb3040450f669a306fc53f95d13252 to your computer and use it in GitHub Desktop.
Save dotchetter/4bcb3040450f669a306fc53f95d13252 to your computer and use it in GitHub Desktop.
Timer/Counter and Interrupt cheat-sheets for the Atmel ATMega324A microcontroller

AVR Interrupts

Each of the pins on the AVR may have multiple functions. For example, pin D0 and D1 are able to serve as receive and transmit pins for serial port one, respectively. Similarly, a number of pins on the AVR are able to transmit interrupt requests to the CPU when they receive a particular signal. How to implement this functionality is shown below.

Register Summary

Register Name Purpose of Register
PCICR Pin Change Interrupt Control Register (Enable interrupts for a particular set of PCINT ports)
PCIFR Pin Change Interrupt Flag Register (When a logic change triggers an interrupt on a particular PCINT pin, the corresponding flag will be set)
PCMSK0 Pin Change Mask Register (Select whether interrupts are enabled on a particular PCINT pin)

Bit Summary

Register Name Bit Name Purpose of Bit
PCICR PCIE0 - 3 Enable interrupts for each set of 8 pins
PCIFR PCIF0 - 3 Interrupt flags for each set of 8 pins
PCMSK0 PCINT0 - 7 Enable masks for each of 8 pins in set 0

Handling Interrupts Example

// Integer defined as volatile to prevent compiler optimizations
volatile int changeable_digit;

ISR (PCINT0_vect) {
    // Interrupt handler code goes here
}

int main(void) {
    // Enable interrupts for PCINT[7:0]
    PCICR |= (1 << PCIE0);
    
    // Clear the interrupt flag for PCINT[7:0]
    PCIFR |= (1 << PCIF0);
    
    // Enable interrupts on PCINT0 (PIN A0)
    PCMSK0 |= (1 << PCINT0);
    
    // Enable interrupts globally
    sei();
}

AVR Timer/Counter

The Atmel ATMega324A microcontroller contains three Timer/Counter devices available for use. The second Timer/Counter, labeled T/C 1 has a width of 16-bits, as opposed to 8-bits.

Output Compare Value formula:

The following formula can be used to calculate the required Output Compare value for a particular desired frequency.

Output Compare Formula

In this case, O is the resulting Output Compare Value to be placed in register OCR1A (in decimal), C is the clock rate of the device (typically a value such as 8 000, 000 -- corresponding to 8MHz), P is the value of the selected pre-scaler (for example 8, or 64, or 256) and r is the desired rate at which you would like the Timer/Counter comparator to trigger some sort of event (this could be a value such as 100, for an event every 10ms (corresponding to 100Hz)).

Timer/Counter Register Summary

The following summary assumes that Timer/Counter 1 is being used. Three Timer/Counters are available on the AVR, labeled 0 - 3. To access the 8-bit Timer/Counter 0, TCCR0A would be used instead of TCCR1A.

Register Name Purpose of Register
TCCR1A Timer/Counter Control Register (Set compare output mode and define how counting sequence occurs)
TCCR1B Timer/Counter Control Register (Define how counting sequence occurs and select a pre-scaler)
TCNT1H, TCNT1L Direct access to the counter value (be careful about writing)
OCR1AH, OCR1AL Output compare register for channel A (holds value to be compared with)
OCR1BH, OCR1BL Output compare register for channel B
TIMSK1 Timer interrupt mask (set interrupt if compare match)
TIFR1 Timer interrupt flag register (contains input/match/overflow flags)

Timer/Counter Bit Summary

Register Name Bit Name Purpose of Bit
TCCR1A COM0A0, COM0A1 Compare output mode bits for channel A (disable/toggle/clear/set OC1A pin on compare match)
TCCR1A COM0B0, COM0B1 Compare output mode bits for channel B (disable/toggle/clear/set OC1B pin on compare match)
TCCR1A WGM11, WGM10 Lower two bits of Waveform Generation Mode selection (how counting sequence occurs. Normal Mode, Clear Timer on Compare match (CTC), Pulse Width Modulation (PWM))
TCCR1B WGM13, WGM12 Upper two bits of Waveform Generation Mode selection (see above)
TCCR1B CS12, CS11, CS10 Prescaler selection bits (001 for no prescaler)
TIMSK1 OCIE1A Enable timer compare interrupts for channel A
TIMSK1 OCIE1B Enable timer compare intterupts for channel B
TIFR1 OCF1A Set when a compare match occurs for channel A
TIFR1 OCF1B Set when a compare match occurs for channel B

Timer/Counter Example

In order to setup a timer that matches a compare value and triggers an interrupt 100 times per second (every 10ms), the compare value can be set to 9999, with a pre-scaler value of 8.

// (Clock / (pre-scaler * rate)) - 1
// (8MHz / (8 * 100)) - 1
OCR1A = 9999;
 
// Don't toggle any pins
TCCR1A = 0;
 
// Clear timer once matched, pre-scaler of 8
TCCR1B = ((1 << WGM13) | (1 << WGM12) | (1 << CS11));
 
// Enable channel A interrupts
TIMSK1 = (1 << OCIE1A);
 
// Clear interrupt flag for channel A
TIFR1 = (1 << OCF1A);
 
// Enable interrupts globally
sei();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment