10 bit PWM on ATmega32u4 (ex. Arduino Micro)

Some magic is required to get 10 bit PWM on ATmega32u4.

Setup:

  pinMode(13, OUTPUT);
  pinMode(10, OUTPUT);
 
  // 10-bit operation
  TC4H = 0x03; OCR4C = 0xFF;
  //Configuration of Timer 4 Registers, OC4A (D13) + 0C4B (D10)
  TCCR4A = 0b10100011;
  //Prescaler
  TCCR4B = 0b00000011;

Set PWM output value, needs to be written separately to upper and lower register, in this order!

void setPwmDutyA(int val){
  TC4H = val >> 8;
  OCR4A = 0xFF & val;
}
 
void setPwmDutyB(int val){
  TC4H = val >> 8;
  OCR4B = 0xFF & val;
}

5 thoughts on “10 bit PWM on ATmega32u4 (ex. Arduino Micro)

  1. Hi,

    Nice post!

    Any chance you could explain which pins/timers that are needed to achieve this? Is it possible on all analog output pins?

    Cheers,
    Sam

    1. It’s possible for pin 13 and 10 because they are connected to OC4A and OC4B (output compare), check http://arduino.cc/en/Hacking/PinMapping32u4.

      You should check the datasheet at http://www.atmel.com/images/doc7766.pdf
      Sections:
      15.12.1 TCCR4A – Timer/Counter4 Control Register A
      15.12.2 TCCR4B – Timer/Counter4 Control Register B
      15.12.7 TC4H – Timer/Counter4 High Byte
      15.12.8 OCR4A – Timer/Counter4 Output Compare Register A
      15.12.9 OCR4B – Timer/Counter4 Output Compare Register B
      15.12.10 OCR4C – Timer/Counter4 Output Compare Register C

      1. Hi!
        I did not succeed in setting the frequency to 64MHz in Arduino without sacrificing the ability to upload a sketch automatically (reset to bootloader).

        Perhaps arduino needs timer 4 for the 1200baud reset logic.
        Or USB freq is not 48MHz, have to debug this. Don’t yet know how to debug arduino scripts in Atmel Studio 6.

        There is some nice guy that wrote what to do with timer4.
        See http://wiki.dsvf.net/index.php?title=Fast_PWM_on_the_Atmega_32U4

        When you experience problems, atmel recommends to switch off irqs when accessing 16 or 10bit registers, atomic operation by storing the Interrupt register temporarily, switching off with cli and restoring the register afterwards, or using the atomic.h .
        So you don’t get torn apart by some irq and the value changes.
        Btw, the top value stays there, even if you write multiple registers. So don’t expect that it would 0 by itself. Because some don’t write to TC4H when they use only up to 8bit…
        See
        http://forum.arduino.cc/index.php?topic=125252.0
        I uploaded a dem atmel studio code. Running in arduino will probably be okay, but you have to initiate the reset to bootloader manually, my pro micro needs a wire there, so I switched to atmel ice and studio.
        Have fun
        Andi

Leave a Reply

Your email address will not be published. Required fields are marked *