I'm trying to manipulate mega2560 Timer5 in order to set phase and frequency correct pwm on pins 44 e 45 but I don't really know much about register and prescalers so I got 2 questions. I need to set a 10kHz frequency on that pins, am I able to change only OCR5A value to obtain 10kHz? Or there is a prescaler to set that helps me going much more near to desired frequency?
I'm trying to understand:
16MHz/10kHz= 1600
OCR5A=1600; //MEANS 10KhZ
DID I dream that? :o
16MHz/64...16....8...1/256
here is 16MHz/1/256= 62500 Hz pwms??
//arduino mega2560 Timer5
//here is my code where I generate 799,92Hz freq, PWM of
//75% on OC5B and PWM of 75% on OC5C with clock system
//phase & freq correct PWM
int outputB = 45; //D45
int outputC = 44; //D44
void setup()
{
//outputs via timer5
pinMode(outputB, OUTPUT); // select Pin as ch-B
pinMode(outputC, OUTPUT); // select Pin as ch-C
TCCR5A = B00101001; // Phase and frequency correct PWM change at OCR5A
TCCR5B = B10001; // System clock
OCR5A = 10000; // 799,92Hz
OCR5B = 7500; // 75%
OCR5C = 7500; // 75%
}
1 Like
You set the frequency of a timer/counter by setting prescale and TOP. Prescale changes the base clock rate. TOP is the value at which the PWM counter goes back to 0. The prescale is set with some bits in the Timer/Counter Control Registers (TCCRnx) and other bits in the TCCR's will select either a constant TOP or a register in which you store a value for TOP.
To get the maximum PWM resolution you want TOP to be as large a number as possible. This means you want as fast a counter as possible (prescale as low as possible). In your case you can use a prescale of 1 (16 MHz clock) because 16MHz/10kHz (1600) firs in a 16-bit register. You actually want to set TOP to 1599 to get a 10 kHz cycle time. Then you can set the Output Control Register to a value between 0 and 1599 to get 1600 values of PWM and 10 kHz.
If you wanted a slow PWM like 100 Hz you can't fit 159,999 in a 16-bit register so you would use a prescale like 8 to bring the 16 MHz clock down to 2 MHz. Then to get a 100 Hz rate you would use a TOP of 19,999 which DOES fit in the register.
Thank you for your help! 
int outputB = 45;
int outputC = 44;
void setup()
{
pinMode(outputB, OUTPUT); // select Pin as ch-B
pinMode(outputC, OUTPUT); // select Pin as ch-C
TCCR5A = B00101001; // Phase and frequency correct PWM change at OCR5A
TCCR5B = B10001; // System clock
OCR5A = 1599; // 16MHz/10kHz=1600 prescaler set to 1
OCR5B = 0;
OCR5C = 0;//motors stop
}
What does it change between writing as I did and using _BV() | _BV() function to set bits HIGH?
On my google long trips I found that:
//...after ARDUINO UNO Timer1 (phase and freq correct) pwm settings
//20kHz
void setPWM(uint8_t pin, int dutyCycle) { // dutyCycle is a value between 0-TOP
if(pin == leftPWM) {
OCR1AH = (dutyCycle >> 8);
OCR1AL = (dutyCycle & 0xFF);
} else if (pin == rightPWM) {
OCR1BH = (dutyCycle >> 8);
OCR1BL = (dutyCycle & 0xFF);
}
}
Why do we rewrite those bits?
Like I said: "Then you can set the Output Control Register to a value between 0 and 1599 to get 1600 values of PWM and 10 kHz." There is an OCR register for each PWM output pin. That function you showed looks at which pin you are setting to determine which register to set.
Programming Note:
OCR1BH = (dutyCycle >> 8);
OCR1BL = (dutyCycle & 0xFF);
is equivalent to:
OCR1B = dutyCycle;
I don't know why they would break the int into two bytes and write them separately. Probably from lack of experience.
Isn't required to access the 16 bit registers in the 8 bit processors?
The Timer/Counter (TCNTn), Output Compare Registers (OCRnA/B/C), and Input Capture Register (ICRn) are all
16-bit registers. Special procedures must be followed when accessing the 16-bit registers. These procedures are
described in the section “Accessing 16-bit Registers” on page 135.
The TCNTn, OCRnA/B/C, and ICRn are 16-bit registers that can be accessed by the AVR CPU via the 8-bit data
bus. The 16-bit register must be byte accessed using two read or write operations. Each 16-bit timer has a single 8-
bit register for temporary storing of the high byte of the 16-bit access. The same Temporary Register is shared
between all 16-bit registers within each 16-bit timer. Accessing the low byte triggers the 16-bit read or write operation.
When the low byte of a 16-bit register is written by the CPU, the high byte stored in the Temporary Register,
and the low byte written are both copied into the 16-bit register in the same clock cycle. When the low byte of a 16-
bit register is read by the CPU, the high byte of the 16-bit register is copied into the Temporary Register in the
same clock cycle as the low byte is read.
Not all 16-bit accesses uses the Temporary Register for the high byte. Reading the OCRnA/B/C 16-bit registers
does not involve using the Temporary Register.
To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low byte must be read
before the high byte.
So using OCR1B = dutyCycle; instead of writing before high byte and then low ones can cause a collapse down to pwm frequency?
void setPWM(uint8_t pin, int dutyCycle) {
if(pin == leftPWM) {
OCR5BH = (dutyCycle >> 8);
OCR5BL = (dutyCycle & 0xFF);
} else if (pin == rightPWM) {
OCR5CH = (dutyCycle >> 8);
OCR5CL = (dutyCycle & 0xFF);
}
}
@johnwasser
Frequency is given by F_CPU/(2NICR) - where N is the prescaler, we use no prescaling so frequency is given by F_CPU/(2*ICR) - ICR = F_CPU/PWM_FREQUENCY/2 so 800 instead of 1600?
Can cause problems using TCCR5B=B10001; syntax instead of _BV() | _BV() or it's the same?
The AVR GCC compiler knows enough to write the high byte first and read the high byte second when doing a 16-bit operation on one of the 16-bit registers that has a shadow high byte TEMP register.