I want to create a PWM on any PIN and therefore using ISRs to achieve this. The setup I chose, working with my ATMEGA328p and Timer0 is:
static inline void initTimer0(void) {
// Timer Counter Control Register B
// Must b4 /64 or more for ISR timing
TCCR0B |= (1 << CS00) | (1 << CS01);
// Timer Counter Interrupt Mask Register
// both output compare interrupts
TIMSK0 |= ((1 << OCIE0A) | (1 << OCIE1B));
// Timer Counter Overflow Interrupt Enable
TIMSK0 |= (1 << TOIE0);
sei();
}
/* Timer/Counter0 Overflow */
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect) {
PORTB |= (1 << 0);
OCR0A = brightnessA;
}
// ISR fired when a match occurs
ISR(TIMER0_COMPA_vect) {
PORTB ^= (1 << 0);
}
int main(void)
{
setup();
int d = 10;
while (1)
{
for (int i = 0; i < 255; i++) {
_delay_ms(d);
brightnessA = i;
}
}
}
I would have expected that the LED on PORTB would dim up but nothing happens. I think I have a gap in understanding here. I would have assumed that TIMER0_COMPA_vect ISR would fire everytime I reach the new OCR0A compare value and turn the LED of, therefore control the duty cycle.
Can you help me?
Thanks
Best Answer
You need to configure the waveform generation mode as well in order to get this working. Page 128 of ATmega328 Datasheet describes exactly how WGM bits need to be set.
This means you need to configure the
TCCR0A
register as well accordingly.