Skip to main content
+ background info, fixed port pins
Source Link
Edgar Bonet
  • 45.2k
  • 4
  • 42
  • 81

If you don't define your own main(), your program will be linked with the main() provided by the Arduino core library, which roughly looks like this (I am simplifying a little bit):

int main(void)
{
    init();      // Arduino core initialization
    setup();     // user's initialization
    for (;;)
        loop();  // user's main loop
}

The core's init() function configures Timer 1 for 8-bit phase correct PWM at 490 Hz, which means that, by the time your setup() runs, the timer's control registers are not in their default state anymore, and some of their bits are already set to 1. If you then update these registers using the |= operator, you end up with a mix of the core's configuration and your own.

This can be fixed either by zeroing these registers first or, more simply, by setting their values with the = operator, which has the effect or setting every bit of those registers to the value you want.

The following works whether you use or not the Arduino core library:

#ifdef NOCORE
int main(void)
#else
void setup()
#endif
{
    DDRB   = _BV(PB1PB5) | _BV(PB2PB6);
    TCCR1A = _BV(COM1A1)
           | _BV(COM1B1)
           | _BV(WGM11);
    TCCR1B = _BV(WGM12)
           | _BV(WGM13)
           | _BV(CS10);
    ICR1   = 0x7fff;  // TOP
    OCR1A  = 0x3fff;  // 50% of ICR1
    OCR1B  = 0x3fff;  // 50% of ICR1
}

#ifndef NOCORE
void loop(){}
#endif

Note that:

  1. The control registers are set (=) rather than just modified with |=
  2. The mode is set before the output compare registers. This is because setting the output compare registers does not work well when the timer is in an 8-bit mode.

The following works whether you use or not the Arduino core library:

#ifdef NOCORE
int main(void)
#else
void setup()
#endif
{
    DDRB   = _BV(PB1) | _BV(PB2);
    TCCR1A = _BV(COM1A1)
           | _BV(COM1B1)
           | _BV(WGM11);
    TCCR1B = _BV(WGM12)
           | _BV(WGM13)
           | _BV(CS10);
    ICR1   = 0x7fff;  // TOP
    OCR1A  = 0x3fff;  // 50% of ICR1
    OCR1B  = 0x3fff;  // 50% of ICR1
}

#ifndef NOCORE
void loop(){}
#endif

Note that:

  1. The control registers are set (=) rather than just modified with |=
  2. The mode is set before the output compare registers. This is because setting the output compare registers does not work well when the timer is in an 8-bit mode.

If you don't define your own main(), your program will be linked with the main() provided by the Arduino core library, which roughly looks like this (I am simplifying a little bit):

int main(void)
{
    init();      // Arduino core initialization
    setup();     // user's initialization
    for (;;)
        loop();  // user's main loop
}

The core's init() function configures Timer 1 for 8-bit phase correct PWM at 490 Hz, which means that, by the time your setup() runs, the timer's control registers are not in their default state anymore, and some of their bits are already set to 1. If you then update these registers using the |= operator, you end up with a mix of the core's configuration and your own.

This can be fixed either by zeroing these registers first or, more simply, by setting their values with the = operator, which has the effect or setting every bit of those registers to the value you want.

The following works whether you use or not the Arduino core library:

#ifdef NOCORE
int main(void)
#else
void setup()
#endif
{
    DDRB   = _BV(PB5) | _BV(PB6);
    TCCR1A = _BV(COM1A1)
           | _BV(COM1B1)
           | _BV(WGM11);
    TCCR1B = _BV(WGM12)
           | _BV(WGM13)
           | _BV(CS10);
    ICR1   = 0x7fff;  // TOP
    OCR1A  = 0x3fff;  // 50% of ICR1
    OCR1B  = 0x3fff;  // 50% of ICR1
}

#ifndef NOCORE
void loop(){}
#endif

Note that:

  1. The control registers are set (=) rather than just modified with |=
  2. The mode is set before the output compare registers. This is because setting the output compare registers does not work well when the timer is in an 8-bit mode.
Source Link
Edgar Bonet
  • 45.2k
  • 4
  • 42
  • 81

The following works whether you use or not the Arduino core library:

#ifdef NOCORE
int main(void)
#else
void setup()
#endif
{
    DDRB   = _BV(PB1) | _BV(PB2);
    TCCR1A = _BV(COM1A1)
           | _BV(COM1B1)
           | _BV(WGM11);
    TCCR1B = _BV(WGM12)
           | _BV(WGM13)
           | _BV(CS10);
    ICR1   = 0x7fff;  // TOP
    OCR1A  = 0x3fff;  // 50% of ICR1
    OCR1B  = 0x3fff;  // 50% of ICR1
}

#ifndef NOCORE
void loop(){}
#endif

Note that:

  1. The control registers are set (=) rather than just modified with |=
  2. The mode is set before the output compare registers. This is because setting the output compare registers does not work well when the timer is in an 8-bit mode.