Trying to use 16bit Timer at AtMega8 but it does not work

Thread Starter

SelimKeles

Joined Jun 6, 2020
3
Hi There,

This is my first post at the forum and I really do not know what I am doing wrong. I read the datasheet, watched tutorials, looked at the forum posts but could not find any proper reason for why it is not working.

I explained what code does at comments but in summary, it counts every one and two seconds to toggle LEDs. LEDs are initially ON but interrupt never happens after code starts. I used a 16-bit timer (timer1) and avr/interrupt library which saves me from writing all the code for sei() function. However, I try to use the ınterrupt function which compares using comparator a which gives the opportunity to range between 0 to 2^16 but I am using only 999.

I used Prescaler which divides frequency to 8 and since set tick number set as 999 at the previous part, interrupt must occur every 1milliSecond due to math (8 000 000)/(1000*8)=1000Hz. So I used counters in interrupt function which counts 1000 and 2000 times when zero crosses occurs and the main function calls for led blinking functions. By math (Since 1000hz = 1/1000 sec, 1000*(1/1000)=1sec or 2000*(1/1000)=2sec) main function calls the led blinking functions every 1 second for one led and every 2 seconds for the other led.

But it never happens and I do not understand why. Also, do you have any advice which is better than doing all this stuff for getting a specific time for check some function over and over again?

Best Regards,
Selim.




C:
/*
 * InterruptwithMega8.c
 * 16
 * Created: 05.06.2020 22:07:46
 * Author : Selim Keles
    
    Using timer1(16bit timer) with 8 Mhz internal oscillator. Every 1mSecond interrupt occurs due to math 8 000 000 /8/1000 = 1000Hz.
    So I add a counter in interrupt which counts to 1000. After 1000 count (1000*(1/1000)=1s), ledblink function will call.
 */

#define F_CPU 8000000
#define firstledtime 1000  //d0 pin will blink every 1 second
#define    secondledtime    2000 //d1 pin will blink every 2 sec

volatile unsigned int t1;        //Flag for first led which I used in interrupt
volatile unsigned int t2;        //Flag for second led

#include <avr/io.h>
#include <avr/interrupt.h>


void init(void);                    //Inıt function
void blinkled1(void);                //Function which toggle led1
void blinkled2(void);                //Function which toggle led2

//*********************************************************************************
int main(void)
{
    init();
    while (1)
    {
        if (0==t1){t1=firstledtime; blinkled1();};            //Calls the function if 1 second passed. (1000Hz*1000=1second)
        if (0==t2){t2=secondledtime; blinkled2();};            //Calls the function if 2 second passed. (1000Hz*2000=2second)
    }
}
//***********************************************************************************
void init(void){                    //init function
    cli();
    DDRD |= (1<<DDD0) | (1<<DDD1);    //D0 and D1 ports selected as output
    PORTD |= 0x03;                    //Leds are initially on
    TIMSK|=OCIE1A;                    //Mask will be compare with comparator A. If match occurs interrupt function will be called.
    OCR1A|=999;                        //8Mhz/8/1000 =1000 frequency is 1000. t1 and t2 will count to 1000 and 2000 in interrupt function to reach 1 sec and 2 sec
    TCCR1B|=(1<<WGM12) | (1<<CS11);    //Prescaler is 8 and CTC active which clears counter obtained by prescaler and thick counter
    t1=firstledtime;                //initially set to 1000 because ı will decrement it in interrupt function
    t2=secondledtime;
    sei();                            //Interrupts are active
}
//********************************************************************************


void blinkled1(){
    PORTD ^= (1<<PD0);                //Toggles Led1 at port d0
}

void blinkled2(){
    PORTD ^= (1<<PD1);                //Toggles Led2 at port d1
}

//********************************************************************************

ISR(TIMER1_COMPA_vect){
    if (t1>0){--t1;};                //decrements t1 from 1000 to 0 which helps to obtain 1 sec
    if (t2>0){--t2;};                //decrements t2 from 2000 to 0 which helps to obtain 2 sec
}

//*******************************************************************************
 

BobTPH

Joined Jun 5, 2013
8,967
Don’t know about Arduino, but on pic’s there is an enable flag for each type of interrupt and an an interrupt flag that you mist clear m the handler or it will reenter the handler immediately again and never get back To your main.

Bob
 

Thread Starter

SelimKeles

Joined Jun 6, 2020
3
Don’t know about Arduino, but on pic’s there is an enable flag for each type of interrupt and an an interrupt flag that you mist clear m the handler or it will reenter the handler immediately again and never get back To your main.

Bob
Thank you, Bob

I tried it on the 42nd row. By enabling CTC using WGM12 bit on Timer Counter Control Register-B. Also since atMega8 has 2 Timer Counter Control Register, I used TCCRA to clear flag as you mention. But nothing changed. I am suspicious about interrupt function. But since I am using comparator-A, I set function for comparator-A at 61st row.

Regards,
Selim
 

MrChips

Joined Oct 2, 2009
30,808
Your TIMSK is incorrect.
OCIE1A is a bit number, not the actual mask. Use

TIMSK |= (1 << OCIE1A);

I have not checked that other settings on the timer are correct.

It is always a good idea to check first that the ISR is being entered.
You can send a pulse out and look for it on an oscilloscope or just flash an LED.

For example:

C:
ISR(TIMER1_COMPA_vect)
{
   DDRB = 0x01;
   PORTB = 0x01;
   _delay_ms(1);    // whatever delay function you can use
   PORTB = 0x00;
}
 

Thread Starter

SelimKeles

Joined Jun 6, 2020
3
Thank you, it helped so much. I think I should use the debugger at Atmel Studio for preventing that kind of mistake again. And also check the functions which I am not familiar with before as you mentioned.

Thank you.
 
Top