NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Need advice regarding TIMERS/COUNTERS and Interrupts.

March 30, 2012
by rmore
rmore's Avatar

Hello all!

This is my first post on here. I recently worked through the Nerdkits project and now am trying to learn other things that I can find on-line. I came across TIMERS/Counters and Interrupts and am working on that for now.

Basically I am trying to light up a LED every 1 second. I am getting the code to work as I want it to for this - but I am not sure I understand the code completely. I have some misunderstanding about the channels A and B in OCR1A/B.

The code is:


#define F_CPU 14745600
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

// Practice for Counters AND Interrupts

int main(void) 
    {
sei();                      // Setting global interrupts

DDRC |= (1 << PINC2);       // Setting output on register C, pin 2 (LED to blink twice as slow) 
DDRC |= (1 << PINC3);       // Setting output on register C, pin 3 (LED to blink)

TCCR1B |= (1 << CS12) | (1 << CS10) | (1 << WGM12 );    // CS12 and CS10 for using prescale of 1024. WGM12             for reseting counter TCNT1 to 0 once OCR1A reaches 15625
TIMSK1 |= (1 << OCIE1A);        //

OCR1A = F_CPU/1024;             // Value to be compared for TCNT1

while (1) 
{
}

}

// Interrupt Service Routine (ISR)

ISR(TIMER1_COMPA_vect)
 {
PORTC ^= (1 << PINC3);      // Action to perform when value reached - blink LED
 }
******************************************************************************************************

My question is - This code works. But if I change to OCR1B and (TIMER1_COMPB_vect), the LED does not blink. Why is this so? I tried to read the data sheet and it says we can use OCR1A as well as OCR1B for comparison purpose.

My second question is - The above code is for blinking an LED per second. If I have to blink another LED in the same circuit at a different rate, do I need to use a different TIMER and Comparison method? How can I actually do this?

Please answer my questions.

Thanks a lot.

  • rmore
March 30, 2012
by pcbolt
pcbolt's Avatar

Hi rmore -

I think you need to enable the 1B timer interrupt like you did for 1A. Line 20 above shows:

TIMSK1 |= (1 << OCIE1A);

This enables the 1A interrupt. To enable both, use:

TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);

You could use two timers or you can use the same timer for two different events IF the timing for the events are even multiples of each other. In your example you blink an LED every second. If you want to blink another every 1/2 second, setup your interrupt to trigger every 1/2 second and blink the 1/2-second LED each time. For the 1-second LED, just put some code in your interrupt routine to ignore every other trigger (use a global count or flag variable) so it blinks every second.

Post a Reply

Please log in to post a reply.

Did you know that talking to the microcontroller over the USB/Serial link is easy under Windows, Linux, and OS X? Learn more...