Using Timer Compare Match IRQs
In This Video
- Change timer mode to Clear Timer on Compare Match (CTC) mode.
- Enable Compare Match IRQ.
- Update the interrupt vector efficiently (from timer overflow to CTC match on channel A).
- Write a generic function to overflow the timer at a given frequency.
Procedure
Change the Mode
We want to change the Mode to Clear Timer on Compare Mode instead of Normal Mode used in theWe see in the Waveform Generation Mode Bit Description table below that in order to set the mode to CTC, we need to set the bit in WGM12.
The WGM12 bit exists in the TCCR1B register as indicated in the accompanying image.
Let's pull up our code from the previous lesson and make the necessary modification to change to CTC mode.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LED_ON PORTB |= (1<<PORTB5)
#define LED_OFF PORTB &= ~(1<<PORTB5)
#define LED_TOGGLE PINB |= (1<<PINB5)
ISR(TIMER1_OVF_vect)
{
LED_TOGGLE;
}
int main(void) {
DDRB |= (1 << PB5); // set PB5 as output pin
DDRB &= ~(1<<DDB7); //set PB7 as an input pin
TCCR1B |= (1 << CS12); //Set up the clock source
TIMSK1 |= (1 << TOIE1); //Enable the overflow interrupt
sei(); //Enable global interrupts
while (1) {
}
}
From above, you can see that we're already writing to TCCR1B to set up the clock source. We need to change the mode so we modify the line to read as:
Change the Interrupt Type
Previously, we used the overflow interrupt but we need to make a change in our code to use a CTC interrupt instead. Going back to the TMSK1 register we see in the accompanying image that we need to set bit 1.
We modify this line:
To read like this line:
Set up the Interrupt Vector
Find the Interrupt Table in the datasheet and look for Timer/Counter1 Compare Match A to find the interrupt vector source.
Modify this line:
To read like this line:
Here is everything we have so far:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LED_ON PORTB |= (1<<PORTB5)
#define LED_OFF PORTB &= ~(1<<PORTB5)
#define LED_TOGGLE PINB |= (1<<PINB5)
ISR(TIMER1_COMPA_vect)
{
LED_TOGGLE;
}
int main(void) {
DDRB |= (1 << PB5); // set PB5 as output pin
DDRB &= ~(1<<DDB7); //set PB7 as an input pin
TCCR1B |= (1 << CS12) | (1 << WGM12); //Set clock source & set mode to CTC
TIMSK1 |= (1 << OCIE1A); //Enable the CTC interrupt
sei(); //Enable global interrupts
while (1) {
}
}
Rearrange the Frequency Equation
Recall the frequency equation from the Timer Overflow lesson.
We want to rearrange this equation so that we are solving for OCRnx and using f0cnx. This equation would now look like this after we substitute F_CPU for fclk_I/0, OCR1A for OCRnx, and include freq as a variable in place of f0Cnx.
OCR1A = (F_CPU/(freq*2*256)-1)
Create a function called Timer_Frequency and call it from our main.
Using the rearranged formula from above and moving our clock source and CTC interrupt into it we get the following function:
{
TCCR1B |= (1 << CS12) | (1 << WGM12); //Set clock source & set mode to CTC
TIMSK1 |= (1 << OCIE1A); //Enable the CTC interrupt
OCR1A = (F_CPU/(freq*2*256)-1);
}
Here is the completed code a call to the Timer_Frequency function. We will set jit at a frequency of 4Hz.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LED_ON PORTB |= (1<<PORTB5)
#define LED_OFF PORTB &= ~(1<<PORTB5)
#define LED_TOGGLE PINB |= (1<<PINB5)
ISR(TIMER1_COMPA_vect)
{
LED_TOGGLE;
}
void Timer_Frequency(uint8_t freq)
{
TCCR1B |= (1 << CS12) | (1 << WGM12); //Set clock source & set mode to CTC
TIMSK1 |= (1 << OCIE1A); //Enable the CTC interrupt
OCR1A = (F_CPU/(freq*2*256)-1);
}
int main(void) {
DDRB |= (1 << PB5); // set PB5 as output pin
DDRB &= ~(1<<DDB7); //set PB7 as an input pin
Timer_Frequency(4);
sei(); //Enable global interrupts
while (1) {
}
}
Program the Device
Program the device by selecting the Make and Program Device Main Project button at the top of the MPLAB X GUI . You should see the LED blinking at 4Hz.
Try changing the frequency value. You should see the LED blinking at different rates each time you change it.
Learn More