PWM frequency not what I expected

Hello all, I've spent the last several hours going through the ATMega32u4 datasheet trying to set the appropriate registers to give myself a PWM output at 25khz. This is part of my first microcontroller project so its all a bit foreign to me.

I'm using a Pro Micro which is Leonardo based running at 16MHz.

Here's my code:

void setup() {
	pinMode(10, OUTPUT);

	//Set WGM1 bits 3:0 to 0b1110 corresponding to "Fast PWM" with Top set to the value stored in OCR1A
	TCCR1A |= 0b00000011;
	TCCR1B |= 0b00011000;

	//Set timer 1 prescaler to 1
	TCCR1B |= 0b00000001;

	//Set COM1B0 and COM1B1 to 0b10 to select the compare mode: "Clear OCnA/OCnB/OCnC on compare match, set OCnA / OCnB / OCnC at TOP"
	//1B corresponds to OC1B, which is pin 10 on the pro micro
	TCCR1A |= 0b00100000;

	//Set Top to 640 which is 16Mhz/25khz
	OCR1A = 640;

	//Compare match value every 320 clocks = 50% duty cycle
	OCR1B = 320;

...

}

Changing OCR1B changes the duty cycle as expected, but my PWM frequency is only 390Hz. It's like my Timer1 is being prescaled but I set the register to tell it to not use prescalaing so I don't understand what's happening.

In addition to that, if I set the prescaling to a higher value it actually has no effect on the output frequency...

Thanks for taking the time to help.

Try to look at this topic :slight_smile:

I think the problem may be that you forgot to clear the registers before OR-ing in the bits you want set to 1. If one of the clock select bits is already set you may be getting a prescale of 64 instead of 1. That would give you about 390 Hz instead of 25 kHz.

Note: Your comment says “//Set WGM1 bits 3:0 to 0b1110 corresponding to “Fast PWM” with Top set to the value stored in OCR1A”. The comment shows the value 14 (0b1110) but the description is for Mode 15. It looks like you are setting the right bits, though.

16000000 / 25000 = 640, but remember to subtract 1 and use 639.

Thats it! My bitwise OR was the problem, thank you.

I would have replied sooner, but I somehow corrupted my Pro Micro. It was showing up in Device Manager as an "Unknown device" so I reprogrammed the bootloader using a USBASP programmer, which made it show up as a COM port again, but I can't program it anymore. It shows up as a COM port then disappears after seveal seconds. If I time it right, I can make an attempt to program it, but the Arduino IDE throws a bunch of errors starting with "avrdude: ser_send(): write error: sorry no info avail"

This is my second Pro Micro I've killed in this project so I'm thinking it must be my circuit doing it.