Increasing Arduino Mega to have 16 bit PWM

I am sort of confused on how to access the 16 bit timer on the mega. Theoretically...if I just write to the TCNTn register (n = counter register number), I can get 16 bit PWM.

However, before I do this, I have to write 0x0 to TCCR1A (this will make it mode 0) or whatever register I want to represent the PWM pin I want. .

What I am more confused about is that in the manual it says that since the register is 16 bits, you have to write the higher bits to the temp register, then the lower bits to the regular register. Am I understanding that correctly or is that if I wanted to do it in assembly?

Overall, instead of AnalogWrite(....,....) it will just be something like TCNTn = TCNTn + 1 to increment the PWM to the next PWM value?

Gibson486:
Overall, instead of AnalogWrite(....,....) it will just be something like TCNTn = TCNTn + 1 to increment the PWM to the next PWM value?

You use one of the Output Compare Registers to set the PWM value, like OCR1A or OCR1B. You put the Timer/Counter in a mode where it turns the output pin ON until the timer reaches the value in the OCR, then turns the pin OFF until the timer reaches TOP.

OK, I am a little confused…what is the difference between all these PWM modes? Is normal mode a non PWM mode?

Gibson486:
OK, I am a little confused...what is the difference between all these PWM modes? Is normal mode a non PWM mode?

The problem with "Normal" mode is that the Output Compare Register can be changed at any time and things go funny if you set the OCR to a value lower than the current timer count.

Better to use one of the "Fast PWM" modes since that will buffer the OCR1x registers and only update them when the timer resets to 0 (BOTTOM). There are fixed 9, 9, and 10-bit PWM modes but since you want 16-bit PWM you have to manually set TOP to 0xFFFF. To do that you use Mode 14 or 15. If you use Mode 15 you have to use OCR1A for the TOP value (0xFFFF), leaving you only OCR1B for PWM. If you use Mode 14 the TOP value (0xFFFF) is set in ICR1 (Input Compare Register 1) leaving both OCR1A and OCR1B for two separate 16-bit PWM outputs.

Edit: Oops... I was looking at the ATmega328P datasheet. There is a chance the modes on the ATmega2560 timers are different.

I see...I got it to work...I am guessing that changing this also changes the frequency.... I get 250 Hz.

Here is my code to change registers....

TCCR3A = TCCR3A & 0b11111100 | 0x03; //sets PWM type
TCCR3B = TCCR3B & 0b11100111 | 0x18; //sets PWM type
delay(30);
TCCR3B = TCCR3B & 0b11111000 | 0x01; //set frequency
OCR3A = MAXVALUE;//this makes the chosen PWM registers 16 bits

I THINK my code tells it to use a 1 prescaler....so I should be getting the max frequency?

I see how it works. After reading the datasheet and getting lost for a few, I think I understand. Basically, your 2^n is your counts, so it relies on your counts (from your clock) to to get the correct PWM frequency. If you set the max number of bits to 16, you makes the counts 65535. You need 65535 counts from the clock to get the PWM wave. In essence, that means you divide by the frequency by the number of max counts. That right?

A prescale of 1 should give you the maximum frequency of 16 MHz / 65536 = 244.140625 Hz

If you don't need a full 16-bit resolution you can use a lower value for TOP and get a higher PWM frequency:

15-bit -> about 500 Hz
14-bit -> about 1000 Hz
etc