1
\$\begingroup\$

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

asked May 2, 2017 at 22:47
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

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.

19.5. Output Compare Unit

The 8-bit comparator continuously compares TCNT0 with the Output Compare Registers (OCR0A and OCR0B). Whenever TCNT0 equals OCR0A or OCR0B, the comparator signals a match. A match will set the Output Compare Flag (OCF0A or OCF0B) at the next timer clock cycle. If the corresponding interrupt is enabled, the Output Compare Flag generates an Output Compare interrupt. The Output Compare Flag is automatically cleared when the interrupt is executed. Alternatively, the flag can be cleared by software by writing a '1' to its I/O bit location. The Waveform Generator uses the match signal to generate an output according to operating mode set by the WGM02, WGM01, and WGM00 bits and Compare Output mode (COM0x[1:0]) bits. The max and bottom signals are used by the Waveform Generator for handling the special cases of the extreme values in some modes of operation.

This means you need to configure the TCCR0A register as well accordingly.

answered Apr 13, 2018 at 5:15
\$\endgroup\$
0
\$\begingroup\$

Did you remember the following line?

DDRB |= 1 << 0;

Also, I don't see where you call the function initTimer0() in int main().

You also probably want to declare brightnessA as volatile.

answered May 3, 2017 at 0:25
\$\endgroup\$
2
  • \$\begingroup\$ I don't you need to declare brightnessA as volatile unless it is written to in an ISR, right? \$\endgroup\$ Commented May 3, 2017 at 4:04
  • 1
    \$\begingroup\$ Oh sorry.. yep their is a setup function call as well where I initiate. void setup() { // Set Bank B to Output DDRB = 0xff; initTimer0(); initUSART(); } \$\endgroup\$ Commented May 3, 2017 at 6:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.