Go Down

Topic: Programmable PWM Frequency (Read 395 times) previous topic - next topic



I am currently working on a project and have run into a wall. I need to be able to generate a PWM wave with an adjustable frequency (0 - 10kHZ) with a resolution of ~ 10Hz. This also has to have a Duty cycle of 0-100, with resolution ~1. Is this possible with the Due? I know that pin 9 acts as a true PWM output, but after searching for awhile I couldn't find any straightforward answers. If this isn't possible, are there any hardware solutions, I have looked into programmable oscillators with no luck, as well as PLL's, the last thing I can think of is silly, but an FPGA could do it!


Hi there Julian,

Have a look to pwm_lib, you can use example basic_test.ino as an starting point. The library is available at:


If in any doubt, just let me know.

I hope it helps.


@julianbostick . Hello Julian

As a simple example of PWM implementation, you could try this :
Code: [Select]
void setup() {
  // PWM Set-up on pin PC7 (Arduino Pin 39): see Datasheet chap. 38.5.1
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pine 39, see pinout diagram) ; Peripheral=B

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // Enable PWM
  REG_PIOC_ABSR |= PIO_ABSR_P7;                        // Set PWM pin perhipheral type B
  REG_PIOC_PDR |= PIO_PDR_P7;                          // Set PWM pin to an output

  REG_PWM_ENA = PWM_ENA_CHID2;                         // Enable the PWM channel 2 (see datasheet page 973)
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42);    // Set the PWM clock rate to 2MHz (84MHz/42) ; Adjust DIVA for the resolution you are looking for
                                                       // I suspect that the smaller the DIVA factor, the higher the resolution will be
  REG_PWM_CMR2 = PWM_CMR_CALG |PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 2
  REG_PWM_CPRD2 = 1000000;                             // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ; 1< CPRD < 2exp24  -1 ; here CPRD = 10 exp 6
  REG_PWM_CDTY2 = 200000;                              // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ; here CDTY = 2 * 10 exp 5
 // Alternatively, you can use this format :  PWM->PWM_CH_NUM[2].PWM_CPRD = 1000000 ; 

 // In this example, Frequency is 1 HZ with a DT of 20% so you can see it with an LED attached to pin 39 with a resistor 
  Serial.begin(250000); // for debugging purpose

void loop() {
// If you want to modify the PWM frequency during operation :
REG_PWM_CPRDUPD2 = 800000;


 // if you want to modify duty cycle during operation:


Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131