I use Atmega328p Timer0 and its two OCRs:
void timer0_ini(void)
{
TCCR0A = 0;// set entire TCCR0A register to 0
TCCR0B = 0;// same for TCCR0B
TCNT0 = 0;//initialize counter value to 0
OCR0B = 125; // OCR0B is less than OCR0A, so it works
OCR0A = 250;
TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(1<<COM0B0)|(1<<WGM01)|(0<<WGM00);
TCCR0B |= (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(1<<CS00);
TIMSK0 = (1 << OCIE0A)|(1 << OCIE0B);
}
ISR (TIMER0_COMPB_vect)
{
PORTB ^= (1 << PORTB2);
}
ISR (TIMER0_COMPA_vect)
{
PORTB ^= (1 << PORTB1);
}
It works only when OCR0B < OCR0A. I can't understand why it makes sense.
Using 0, 1, 0
for WGM02, WGM01, WGM00
, you enabled CTC (Clear Timer on Compare match mode) — TCNT0
register will be cleared after it reaches OCR0A
value so that OCR0B
value will never be reached if it is higher than OCR0A
.
Updated to answer the questions in comment:
Yes, it is possible to disable clearing of TCNT0. Just set WGM0x bits to 0. See table Waveform Generation Mode Bit Description at end of TCCR0A description.
No, a top value for the TCNT0 register is OCR0A or fixed 0xFF, see the same table.
It is not clear from your question what do you want to do. Perhaps, one can place the larger value into OCR0A and the smaller into OCR0B and set a flag that says which interrupt should change which port bit.
If you want to make two independent frequencies, set timer in free-running mode (all WGM bits equal 0) and try
ISR (TIMER0_COMPB_vect)
{
PORTB ^= (1 << PORTB2);
OCR0A += 125;
}
ISR (TIMER0_COMPA_vect)
{
PORTB ^= (1 << PORTB1);
OCR0B += 250;
}