Timer0 Flag TOV0 reading problem

Hi guys,

I'm struggling with a problem that seems easy.
My goal is to create a variable that will be changed by timer0. I need this variable for further PWM signal generation.

So far:

1.Basic frequency = 16 MHz
2.My prescaler is 1024, so the output clock frequency is 15.625 kHz
3.My timer0 is set as phase correct, so counting is 0...255...0 (510 steps) for one cycle.
4.full count 0...255...0 takes 1/30 s (15.625 kHz/510 ≈ 30 Hz)
5.After 1 full count, my variable will increase by 1. If it reaches 255, it decreases by 1 to 0 and then increases again like the timer, but at a slower frequency.

The program seems very easy:

  1. First, the clock is set up.
  2. Secondly, timer overflow is being checked.
int16_t duty = 0, value = 1;

void setup() {
  TCCR0A |= (1 << WGM00);  // WGM02:0 - counting type bits for timer 0, 001 - phase correct TOP = 0xFF (Flag TOV0 is activated when the timer reaches BOTTOM)  
  TCCR0A &= ~(1 << WGM01); 
  TCCR0B &= ~(1 << WGM02); 
  TCCR0B |= (1 << CS00);  // CS02:0 - clock source and prescaler. Fout = (Fclk/prescaler). 101 - prescaler-> 1024. 15.625 kHz = (16 MHz/1024)
  TCCR0B |= (1 << CS01); 
  TCCR0B &= ~(1 << CS02); 
  Serial.begin(1000000);
}

void loop() {
  if (TIFR0 & (1 << TOV0)) {
    TIFR0 |= (1 << TOV0);  // Overflow flag reset by writing 1 to it.
    duty += value;
    if (duty == 0 || duty == 255) {
      value = value * (-1);
    }
  }
  Serial.println("Timer = " + String(TCNT0) + ", Flag = " + String(TOV0) + ", duty = " + String(duty) + ", value = " + String(value));
}

BUT the problem is that the flag is ALWAYS 0, and my code cannot work properly.

Here are the readings from serial communication:
Timer = 4, Flag = 0, duty = 0, value = 1
Timer = 16, Flag = 0, duty = 0, value = 1
Timer = 29, Flag = 0, duty = 0, value = 1
...
Timer = 9, Flag = 0, duty = 0, value = 1
Timer = 4, Flag = 0, duty = 0, value = 1
Timer = 16, Flag = 0, duty = 0, value = 1

Your topic does not indicate a problem with IDE 2.x and hence has been moved to a more suitable location.

Please edit your post, select all code and click the <CODE/> button; next save your post.

This will apply code tags which will make the code easier to read and copy and the forum software will display it correctly.

Please read How to get the best out of this forum again.

What board are you using?
millis() uses timer0 on some Arduino boards, see the reference

Arduino Nano - Atmega328P

There are timer presets generated by the Arduino IDE. For Timer0 these presents are used to generate the millis() and micros() values. For Timer1 and Timer2 the presets are for the pwm outputs of those timers.

When using the timers for your own purposes,(and its really not clear if Timer0 and loss of the millis() is appropriate) it's best to initialize the timers by clearing all the ide presets.

TCCR0A = 0;
TCCR0B = 0;

EDIT:
Can you have an interrupt flag if the interrupt has not been enabled?

if (TIFR0 & (1 << TOV0)) {

Perhaps the code needs
TIMSK0 = (1<<TOIE0);

without using interrupts, your loop() is too slow to actually catch when you hit the top and/or bottom. If you switch to using interrupts and using Timer2, it will work

volatile int16_t duty = 0, value = 1;

/**
  * URL: https://dbuezas.github.io/arduino-web-timers/#mcu=ATMEGA328P&timer=2&timerMode=PCPWM&clockPrescalerOrSource=1024
  * Mode     : PCPWM
  * Period   : 32.64 ms
  * Frequency: 30.63725 Hz
  * Outputs  : none
  */
void setup(){
  noInterrupts();
  TCCR2A = 
    1 << WGM20;
  TCCR2B = 
    1 << CS22 |
    1 << CS21 |
    1 << CS20;
  TIMSK2 = 
    1 << TOIE2;

  interrupts();

  Serial.begin(1000000);
}
ISR(TIMER2_OVF_vect) {
    /* on overflow */
    duty += value;
    if (duty == 0 || duty == 255) {
      value = value * (-1);
    }
}


void loop() {

	noInterrupts();
	int16_t my_duty = duty;
	int16_t my_value = value;
	interrupts();

 //Serial.println("Timer = " + String(TCNT0) + ", Flag = " + String(TOV0) + ", duty = " + String(duty) + ", value = " + String(value));
 	Serial.print("Timer = ");
	Serial.print(TCNT2);
	Serial.print(", Flag = ");
	Serial.print(TOV2);
	Serial.print(", duty = ");
	Serial.print(my_duty);
	Serial.print(", value = ");
	Serial.println(my_value);
}

The link at the start of the code is a great site for setting up timers.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.