Need Help: AVR Timer Compare

Status
Not open for further replies.

ArdyNT

Full Member level 2
Joined
Nov 6, 2012
Messages
126
Helped
7
Reputation
14
Reaction score
7
Trophy points
1,298
Visit site
Activity points
2,304
Hi, I've built this code:

Code:
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{    
    TCCR1B = 0x02;
}


// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
    if(ldr1<=600)
    {
        if(OCR1A>=150)
        {
        OCR1A=OCR1A-100;
        }
    }
        
    if(ldr1>=700)
    {
        if(OCR1A<=13500)
        {
        OCR1A=OCR1A+100;
        }   
    }

    PORTB.0 = 0;        // Start the pulse
    delay_us(30);       // Pulse width (I know delay is not good solution to be included inside an interrupt)
    PORTB.0 = 1;       // Clear the pulse

    TCCR1B=0x00;
}

This already work well. The problem is that I need to make more than one (at least three pulses, could be PORTB.1, PORTB.2, ...) like this. The problem is my AVR only have one timer compare (timer1) and it is not found in timer0, and timer2. Is there any other way to manipulate it?

Thanks.
 

As you already mentioned, delay inside interrupt is not good at all. I would suggest to keep a timebase using a timer, and do what you want to do from the main program. You didn't mention which AVR you are using and also keep in mind that there are other modes as well, besides output compare. Are you sure that you only need output compare mode?

However you could do it from inside interrupt as well, although it is not suggested. Let's assume that it is for educational purpose. So if you need three pulses, 30, 40 and 60us:

Code:
PORTB.0 = 0;
PORTB.1 = 0;
PORTB.2 = 0;
delay_us(30);  //30us
PORTB.0 = 1;
delay_us(10);  //40us
PORTB.1 = 1;
delay_us(20);  //60us
PORTB.2 = 1;
 

Well, just ignore the problem with delay inside interrupt first coz I didn't get the solution yet.

I use ATmega8535. Timer compare is the only mode that works for my model. I've tried timer overflow, it doesn't work.

Code:
PORTB.0 = 0;
PORTB.1 = 0;
PORTB.2 = 0;
delay_us(30);  //30us
PORTB.0 = 1;
delay_us(10);  //40us
PORTB.1 = 1;
delay_us(20);  //60us
PORTB.2 = 1;

No that is NOT what I want. delay_us(will be the same=30) since the pulse width is the same. The one that will be different is the time to start the pulse. PORTB.0 maybe active after 5ms after ext interrupt. PORTB.1 maybe 3ms after the interrupt, and so does PORTB.2 ...
 

OK I understand what you mean, but again I say that this is something to be done outside timers.

Code:
PORTB.0 = 0;
delay_us(30);
PORTB.0 = 1;

delay_us(2970);  //2970+30=3ms 
PORTB.1 = 0;
delay_us(30);
PORTB.1 = 1;

delay_us(1970);  //3ms+30us+1970us=5ms
PORTB.2 = 0;
delay_us(30);
PORTB.2 = 1;

Timer compare is the only mode that works for my model. I've tried timer overflow, it doesn't work.
Then you should spend more time looking into AVR timers. Maybe this could help you get started.

https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…