25kHz PWM on Arduino Nano 33 IoT

Hello everyone! I want to get output a 25kHz PWM signal on an Arduino Nano 33 IoT to control a 12v fan. I found this code written by MartinL to output a 38kHz frequency but I'm not sure how to adapt it to produce a 25kHz frequency.

My idea is:
replace TCC1->PER.reg = 1262 with TCC1->PER.reg = 1919 since 48MHz/(1919+1) = 25kHz
replace TCC1->CC[0].reg = 630; with TCC1->CC[0].reg = 950; (to get a 50%) duty cycle
and then for any other duty cycles, TCC1 would be 1900*duty cycle?

Is this correct? Or are there any other changes to be made?

Here is the code for 38kHz:

// Output 38kHz PWM on digital pin D7 on Nano33
void setup()
{
// Feed GCLK0 at 48MHz to TCC0 and TCC1
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 as a clock source
GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 at 48MHz
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK0 to TCC0 and TCC1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

// Enable the port multiplexer for pins D7
PORT->Group[g_APinDescription[7].ulPort].PINCFG[g_APinDescription[7].ulPin].bit.PMUXEN = 1;

// D7 is on EVEN port pin PA06 and TCC1/WO[0] channel 0 is on peripheral E
PORT->Group[g_APinDescription[7].ulPort].PMUX[g_APinDescription[7].ulPin >> 1].reg = /PORT_PMUX_PMUXO_E |/ PORT_PMUX_PMUXE_E;

// Normal (single slope) PWM operation: timer countinuouslys count up to PER register value and then is reset to 0
TCC1->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; // Setup single slope PWM on TCC1
while (TCC1->SYNCBUSY.bit.WAVE); // Wait for synchronization

TCC1->PER.reg = 1262; // Set the frequency of the PWM on TCC1 to 38kHz: 48MHz / (1262 + 1) = 38kHz
while (TCC1->SYNCBUSY.bit.PER); // Wait for synchronization

TCC1->CC[0].reg = 630; // TCC1 CC0 - 50% duty cycle on D7
while (TCC1->SYNCBUSY.bit.CC0); // Wait for synchronization

TCC1->CTRLA.bit.ENABLE = 1; // Enable the TCC1 counter
while (TCC1->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}

void loop()
{
// Using buffered counter compare registers (CCBx)
TCC1->CCB[0].reg = 315; // TCC1 CCB1 - 25% duty cycle on D7
while (TCC1->SYNCBUSY.bit.CCB0); // Wait for synchronization
delay(1000); // Wait for 1 second
TCC1->CCB[0].reg = 945; // TCC1 CCB1 - 75% duty cycle on D7
while (TCC1->SYNCBUSY.bit.CCB0); // Wait for synchronization
delay(1000); // Wait for 1 second
}

Thanks for any help!

Hi @ericwinter

The frequency of the PWM signal is determined by the period (PER) register where:

PER = 48MHz / frequency (PWM) - 1

Therefore to generate 25kHz:

PER = 48MHz / 25kHz - 1 = 1919

The PWM duty-cycle determined by the TCC1's buffered CCB[0] register and can be any value between 0 and PER for 0 to 100%.

Thanks a lot!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.